Skip to content

Conversation

@krystophny
Copy link
Member

@krystophny krystophny commented Dec 12, 2025

Fixes pip install . failing due to invalid pyproject.toml keys and avoids clobbering the repo build/ dir by scikit-build.

Also declares f90wrap as a runtime dependency for pysimple and improves import error messages when f90wrap or _simple_backend is missing.

Test: make test (log: /tmp/simple_make_test2.log)

@qodo-code-review
Copy link

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Misleading import error handling

Description: The ImportError handling branches on exc.name being "_simple_backend", but the code
imports "simple_backend", which may mask genuine import errors and mislead users with
incorrect guidance.
init.py [25-36]

Referred Code
if getattr(exc, "name", None) == "f90wrap":
    raise ImportError(
        "f90wrap is required to import SIMPLE Python bindings. Install f90wrap."
    ) from exc
if getattr(exc, "name", None) == "_simple_backend":
    raise ImportError(
        "Fortran extension _simple_backend failed to import. "
        "Rebuild SIMPLE with Python bindings enabled."
    ) from exc
raise ImportError(
    "simple_backend module not found. Build SIMPLE with Python bindings enabled."
) from exc
Misleading import error handling

Description: The ImportError handling checks exc.name for "_simple_backend" while importing
"simple_backend", potentially hiding the actual import failure source and causing
confusing error messages.
_backend.py [35-46]

Referred Code
if getattr(exc, "name", None) == "f90wrap":
    raise ImportError(
        "f90wrap is required to import SIMPLE Python bindings. Install f90wrap."
    ) from exc
if getattr(exc, "name", None) == "_simple_backend":
    raise ImportError(
        "Fortran extension _simple_backend failed to import. "
        "Rebuild SIMPLE with Python bindings enabled."
    ) from exc
raise ImportError(
    "simple_backend module not found. Build SIMPLE with Python bindings enabled."
) from exc
Ticket Compliance
🟡
🎫 #6
🔴 Make the threshold estimation for fractal dimension independent of the number of points
and transparent, targeting ~1.7 for chaos classification.
🟡
🎫 #4
🔴 Add a switch to enable or disable evaluation of non-canonical z at full time-steps.
🟡
🎫 #7
🔴 Add an option to specify initial energy in simple.in.
🟡
🎫 #5
🔴 Make activation and timing of the Poincaré classifier configurable.
🟡
🎫 #10
🔴 Fix parsing of simple.in to avoid "Bad real number in item 1 of list input" error when
reading cut_in_per or related input.
🟡
🎫 #8
🔴 Convert simple.in to namelist format.
🟡
🎫 #9
🔴 Change the last column in confined_fraction.dat to show number of confined particles or
remove it to avoid confusion.
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
No audit logs: The new error-handling paths raise ImportError with clearer messages but do not add any
audit logging for these critical initialization failures, which may be desired for
diagnostics.

Referred Code
if getattr(exc, "name", None) == "f90wrap":
    raise ImportError(
        "f90wrap is required to import SIMPLE Python bindings. Install f90wrap."
    ) from exc
if getattr(exc, "name", None) == "_simple_backend":
    raise ImportError(
        "Fortran extension _simple_backend failed to import. "
        "Rebuild SIMPLE with Python bindings enabled."
    ) from exc
raise ImportError(
    "simple_backend module not found. Build SIMPLE with Python bindings enabled."
) from exc

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Refactor duplicated logic into a helper

Refactor the duplicated ImportError handling logic from _load_backend into a new
helper function, _import_simple_backend, to centralize the logic and improve
maintainability.

python/pysimple/_backend.py [25-47]

+def _import_simple_backend() -> ModuleType:
+    """Import simple_backend with detailed error handling."""
+    try:
+        return import_module("simple_backend")
+    except ImportError as exc:
+        if getattr(exc, "name", None) == "f90wrap":
+            raise ImportError(
+                "f90wrap is required to import SIMPLE Python bindings. Install f90wrap."
+            ) from exc
+        if getattr(exc, "name", None) == "_simple_backend":
+            raise ImportError(
+                "Fortran extension _simple_backend failed to import. "
+                "Rebuild SIMPLE with Python bindings enabled."
+            ) from exc
+        raise ImportError(
+            "simple_backend module not found. Build SIMPLE with Python bindings enabled."
+        ) from exc
+
+
 def _load_backend() -> ModuleType:
     """
     Lazily import the f90wrap backend.
     """
     global _BACKEND
 
     if _BACKEND is None:
-        try:
-            _BACKEND = import_module("simple_backend")
-        except ImportError as exc:  # pragma: no cover - exercised in test skips
-            if getattr(exc, "name", None) == "f90wrap":
-                raise ImportError(
-                    "f90wrap is required to import SIMPLE Python bindings. Install f90wrap."
-                ) from exc
-            if getattr(exc, "name", None) == "_simple_backend":
-                raise ImportError(
-                    "Fortran extension _simple_backend failed to import. "
-                    "Rebuild SIMPLE with Python bindings enabled."
-                ) from exc
-            raise ImportError(
-                "simple_backend module not found. Build SIMPLE with Python bindings enabled."
-            ) from exc
+        _BACKEND = _import_simple_backend()
     return _BACKEND

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies significant code duplication introduced in the PR and proposes a sound refactoring to improve maintainability by centralizing the import logic.

Medium
Remove duplicated import handling logic

Replace the duplicated ImportError handling in init.py by importing and
using the proposed _import_simple_backend helper function from the _backend
module.

python/pysimple/init.py [22-36]

-try:
-    import simple_backend as _backend
-except ImportError as exc:
-    if getattr(exc, "name", None) == "f90wrap":
-        raise ImportError(
-            "f90wrap is required to import SIMPLE Python bindings. Install f90wrap."
-        ) from exc
-    if getattr(exc, "name", None) == "_simple_backend":
-        raise ImportError(
-            "Fortran extension _simple_backend failed to import. "
-            "Rebuild SIMPLE with Python bindings enabled."
-        ) from exc
-    raise ImportError(
-        "simple_backend module not found. Build SIMPLE with Python bindings enabled."
-    ) from exc
+from ._backend import _import_simple_backend
 
+_backend = _import_simple_backend()
+
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies duplicated import logic and proposes replacing it with a call to a centralized helper function, which improves code quality and maintainability.

Medium
  • More

@krystophny krystophny force-pushed the fix/pip-install-and-backend-import branch from 193a066 to dd90ed8 Compare December 21, 2025 23:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants