Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
73 changes: 10 additions & 63 deletions .github/workflows/build-wheels.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,77 +2,24 @@ name: Build and upload to PyPI

on:
workflow_dispatch:
pull_request:
push:
branches:
- main
release:
types:
- published

jobs:
build_wheels:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, windows-11-arm, macos-15-intel, macos-latest]

steps:
- uses: actions/checkout@v5
with:
submodules: recursive # Critical: fetch packmol submodule

- name: Build wheels
uses: pypa/cibuildwheel@v3.3.0
env:
# Set macOS deployment target dynamically based on runner
CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=15.0

- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
path: ./wheelhouse/*.whl

build_sdist:
name: Build source distribution
pypi-publish:
name: Upload release to PyPI
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
submodules: true

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Build SDist
run: uv build --sdist

- name: Upload SDist
uses: actions/upload-artifact@v4
with:
name: cibw-sdist
path: dist/*.tar.gz

upload_pypi:
needs: [build_wheels, build_sdist]
environment:
name: pypi
url: https://pypi.org/p/molify
permissions:
id-token: write
runs-on: ubuntu-latest
if: github.event_name == 'release' && github.event.action == 'published'
steps:
- name: Download all artifacts
uses: actions/download-artifact@v5
with:
pattern: cibw-*
path: dist
merge-multiple: true

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
- uses: actions/checkout@v5
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Build
run: |
uv build
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

1 change: 0 additions & 1 deletion external/packmol
Submodule packmol deleted from 7cb4c1
116 changes: 0 additions & 116 deletions hatch_build.py

This file was deleted.

9 changes: 2 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "molify"
version = "0.2.0"
version = "0.2.1"
description = "Molecular Structure Interface with RDKit, ASE, Packmol and NetworkX"
readme = "README.md"
license = "Apache-2.0"
Expand All @@ -12,6 +12,7 @@ dependencies = [
"ase>=3.25.0",
"matplotlib>=3.10.1",
"networkx>=3.4.2",
"packmol>=0.1.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify that packmol version 0.1.0 is available on PyPI.

The PR description mentions waiting for a PyPI release with the correct version number. Ensure that packmol>=0.1.0 is published and accessible before merging.


🌐 Web query:

Is packmol version 0.1.0 or higher available on PyPI?

💡 Result:

Short answer: No — the PACKMOL program is not published as a "packmol" package on PyPI. It is distributed from the project (source/binaries) and via conda-forge (or via the Packmol.jl wrapper). See the official project and installation instructions. [1][2]

Sources:

  • Packmol official (download/install instructions). [1]
  • Packmol GitHub repository. [2]
  • Example PyPI-using projects recommending conda install -c conda-forge packmol (e.g., mdinterface). [3]

Remove or correct the invalid packmol dependency in pyproject.toml.

The PACKMOL program is not published as a "packmol" package on PyPI. The line "packmol>=0.1.0", will fail during package installation when pip cannot resolve this dependency. It is distributed from the project source/binaries and via conda-forge. Either remove this dependency if it's optional, or update to use the correct package distribution method (conda-forge), or verify if there is a different PyPI package that provides the required functionality.

🤖 Prompt for AI Agents
In pyproject.toml around line 15, the dependency entry "packmol>=0.1.0" is
invalid because PACKMOL is not published to PyPI; remove this line or move it to
optional/development extras and update installation docs to instruct users to
install PACKMOL via conda-forge (or from project binaries) instead;
alternatively, if you rely on a different PyPI package that wraps PACKMOL,
replace the entry with that validated package name and version and add a note in
pyproject or README about the required external installation method.

"rdkit>=2024",
]

Expand Down Expand Up @@ -57,11 +58,5 @@ extend-ignore = [
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.hooks.custom]
path = "hatch_build.py"

[tool.hatch.build.targets.wheel]
packages = ["src/molify"]

[tool.codespell]
skip = "*.ipynb"
Binary file removed src/molify/binaries/packmol
Binary file not shown.
14 changes: 3 additions & 11 deletions src/molify/pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from ase.io.proteindatabank import write_proteindatabank
from rdkit import Chem

from molify.packmol import get_packmol_binary
from molify.utils import calculate_box_dimensions

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -147,7 +146,7 @@ def pack(
seed: int = 42,
tolerance: float = 2,
verbose: bool = False,
packmol: str | None = None,
packmol: str = "packmol",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Breaking change: Verify documentation and migration guide.

Changing from packmol: str | None = None to packmol: str = "packmol" is a breaking change. Users who previously relied on the bundled Packmol binary will now need to install Packmol separately and ensure it's available in their system PATH.

Run the following script to check if the README or documentation mentions the new Packmol installation requirement:


🏁 Script executed:

#!/bin/bash
# Check if documentation mentions packmol installation requirement

echo "=== Checking README ==="
fd -t f "README" --exec cat {} \; | grep -i "packmol" -C 3

echo -e "\n=== Checking docs directory ==="
fd -t f . docs/ --exec grep -l "packmol" {} \; 2>/dev/null | head -5

echo -e "\n=== Checking for installation instructions ==="
rg -i "install.*packmol|packmol.*install|pip install.*packmol" -C 2

Length of output: 967



🏁 Script executed:

#!/bin/bash
# Check documentation content and changelog

echo "=== README content (full) ==="
fd -t f "README*" --exec cat {} \;

echo -e "\n=== Checking docs/source/index.rst ==="
cat docs/source/index.rst 2>/dev/null | head -100

echo -e "\n=== Looking for CHANGELOG or version notes ==="
fd -t f "CHANGELOG|HISTORY|CHANGES|NEWS" --exec cat {} \; 2>/dev/null | head -50

echo -e "\n=== Checking if pack.py has error messages about packmol ==="
rg -n "packmol" src/molify/pack.py | head -20

Length of output: 6392



🏁 Script executed:

#!/bin/bash
# Check setup configuration and error handling

echo "=== Checking setup.py / pyproject.toml ==="
fd -t f "setup.py|pyproject.toml|setup.cfg" --exec cat {} \;

echo -e "\n=== Error handling in pack.py around line 227-234 ==="
sed -n '220,240p' src/molify/pack.py

echo -e "\n=== Full _run_packmol function ==="
sed -n '63,80p' src/molify/pack.py

Length of output: 2791



🌐 Web query:

What does the packmol package on PyPI provide?

💡 Result:

There isn't an official "packmol" Python library on PyPI that contains the PACKMOL solver itself. PACKMOL is a standalone packing program (source/binaries distributed from the project site and via conda-forge) that creates initial molecular configurations for MD simulations. PyPI instead hosts related packages that wrap or integrate PACKMOL (e.g. packmol-step — a SEAMM plug‑in for building periodic fluid boxes; mdapackmol — an MDAnalysis wrapper around Packmol). [1][2][3]

Sources:

  • PACKMOL official site / project (download, description). [1]
  • packmol-step (PyPI) — SEAMM plug‑in using Packmol. [2]
  • mdapackmol (PyPI) — MDAnalysis wrapper around Packmol. [3]


🌐 Web query:

packmol PyPI package what is it

💡 Result:

Short answer: "Packmol" is primarily a standalone program (written in Fortran) that builds initial molecular configurations by packing molecules into user‑defined regions for molecular‑dynamics or docking setups. It is not primarily a pure‑Python PyPI package — instead you usually install the Packmol executable (e.g., from the Packmol GitHub/releases or via conda‑forge) and use Python wrappers on PyPI that call it (examples: mdapackmol, packmol-step). Sources: Packmol GitHub (project & install info) [1], PyPI pages for Python wrappers (mdapackmol, packmol‑step) [2][3].

References

  • Packmol GitHub (project, build/install instructions). [1]
  • mdapackmol — "An MDAnalysis wrapper around Packmol" (PyPI). [2]
  • packmol-step — SEAMM/Packmol plugin (PyPI). [3]


🌐 Web query:

packmol 0.1.0 PyPI package

💡 Result:

There is no official PyPI package named "packmol" (version 0.1.0) — PACKMOL is distributed from its upstream site and via OS packages; Python wrappers/integration packages exist on PyPI (e.g., packmol-step, mdapackmol). Sources: PACKMOL upstream (download/docs). [1] Packmol-step on PyPI. [2] MDAPackmol on PyPI. [3]

Sources

  • PACKMOL homepage (upstream downloads/docs). [1]
  • packmol-step on PyPI (example PyPI package integrating PACKMOL). [2]
  • mdapackmol on PyPI (MDAnalysis wrapper around PACKMOL). [3]


🏁 Script executed:

#!/bin/bash
# Check if there's actually a packmol package on PyPI or if this is a broken dependency

echo "=== Searching for any reference to packmol package in repo ==="
rg -i "packmol" pyproject.toml setup.py setup.cfg 2>/dev/null

echo -e "\n=== Checking if packmol is imported anywhere ==="
fd -t f "\.py$" --exec grep -l "import packmol\|from packmol" {} \; 2>/dev/null

echo -e "\n=== Looking at imports in pack.py ==="
head -30 src/molify/pack.py

Length of output: 1268



🏁 Script executed:

#!/bin/bash
# Final verification - check git history or comments about packmol dependency

echo "=== Checking git log for packmol changes ==="
git log --oneline -20 2>/dev/null | head -10

echo -e "\n=== Check if this is perhaps a typo or if packmol.py file exists ==="
fd -t f "packmol" src/

echo -e "\n=== Look at molify.packmol module (referenced in pyproject.toml) ==="
fd -t f "packmol.py" --exec head -50 {} \;

Length of output: 649



🏁 Script executed:

#!/bin/bash
# Check the latest commit details

echo "=== Full commit message for latest packmol change ==="
git show df9c6e8 --stat 2>/dev/null

echo -e "\n=== What changed in that commit ==="
git show df9c6e8 --no-stat 2>/dev/null | head -100

echo -e "\n=== Check if packmol package actually exists by searching PyPI ==="
python3 << 'EOF'
import urllib.request
import json
try:
    with urllib.request.urlopen("https://pypi.org/pypi/packmol/json") as response:
        data = json.loads(response.read().decode())
        print(f"Package found: {data['info']['name']}")
        print(f"Latest version: {data['info']['version']}")
        print(f"Description: {data['info']['summary']}")
except urllib.error.HTTPError as e:
    print(f"Package not found on PyPI (HTTP {e.code})")
EOF

Length of output: 2740


Multiple critical issues: Broken dependency, misleading documentation, and unhandled breaking change.

The breaking change itself is legitimate, but the implementation has critical flaws:

  1. Broken PyPI dependency: pyproject.toml lists packmol>=0.1.0, but web search confirms no official PyPI package named "packmol" exists. Installation will fail with "ERROR: Could not find a version that satisfies the requirement packmol>=0.1.0".

  2. Outdated README: README states "The molify package ships with an installation of packmol" — this is now false and will confuse users.

  3. Insufficient error handling: The subprocess call to packmol (line 72 in _run_packmol) will fail silently or with a cryptic error if the executable is missing. No validation before attempting execution.

  4. Missing installation guidance: Users upgrading will face installation failure, then need to manually install packmol externally — but there's no documentation explaining this requirement or how to install the actual PACKMOL binary from the official source.

Remove the broken packmol>=0.1.0 dependency from pyproject.toml, update the README and documentation to clearly state that PACKMOL must be installed separately (e.g., via conda-forge or from the official GitHub), and add validation in the code to provide a helpful error message if the packmol executable is not found.

🤖 Prompt for AI Agents
In src/molify/pack.py around line 149, the constant packmol: str = "packmol" and
related code must guard against missing external PACKMOL binary and inform
docs/package metadata: update code to check for the packmol executable before
invoking subprocess (use shutil.which or pathlib to verify PATH), raise a clear,
user-facing exception with actionable install instructions (e.g., "PACKMOL
executable not found; install via conda-forge or from
https://github.com/wordom/packmol") if not found, and ensure subprocess calls
only run after this validation; separately remove the invalid pyproject
dependency on packmol>=0.1.0 and update README/docs to state PACKMOL is an
external dependency with installation guidance.

pbc: bool = True,
output_format: FORMAT = "pdb",
ratio: tuple[float, float, float] = (1.0, 1.0, 1.0),
Expand All @@ -169,11 +168,8 @@ def pack(
The tolerance for the packing algorithm, by default 2.
verbose : bool, optional
If True, enables logging of the packing process, by default False.
packmol : str or None, optional
The path to the packmol executable. If None (default), uses the bundled
packmol binary shipped with molify. You can provide a custom path to
use a different packmol installation (e.g., "packmol" to use system
PATH, or "/path/to/custom/packmol").
packmol : str, optional
The path to the packmol executable.
pbc : bool, optional
Ensure tolerance across periodic boundaries, by default True.
output_format : str, optional
Expand All @@ -199,10 +195,6 @@ def pack(
>>> print(packed_system)
Atoms(symbols='C10H44O12', pbc=True, cell=[8.4, 8.4, 8.4])
"""
# Use bundled packmol binary if not specified
if packmol is None:
packmol = str(get_packmol_binary())

selected_images = _select_conformers(data, counts, seed)
cell = calculate_box_dimensions(images=selected_images, density=density)

Expand Down
102 changes: 0 additions & 102 deletions src/molify/packmol.py

This file was deleted.

Loading
Loading