File: pusimp.patch

package info (click to toggle)
fenics-dolfinx 1%3A0.10.0.post4-1exp1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 6,028 kB
  • sloc: cpp: 36,535; python: 25,391; makefile: 226; sh: 171; xml: 55
file content (130 lines) | stat: -rw-r--r-- 5,293 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
Index: fenics-dolfinx/python/dolfinx/__init__.py
===================================================================
--- fenics-dolfinx.orig/python/dolfinx/__init__.py	2025-11-12 15:50:15.708582994 +0100
+++ fenics-dolfinx/python/dolfinx/__init__.py	2025-11-12 15:50:15.700715425 +0100
@@ -27,6 +27,29 @@
     default_scalar_type = _np.float64
     default_real_type = _np.float64
 
+import pusimp
+
+def pip_uninstall_call(executable: str, dependency_pypi_name: str, dependency_actual_path: str) -> str:
+    """Report to the user how to uninstall a dependency with pip."""
+    output = f"{executable} -m pip uninstall --break-system-packages {dependency_pypi_name}"
+    if dependency_actual_path.startswith("/usr"):
+        return f"sudo {output}"
+    else:
+        return output
+
+
+pusimp.prevent_user_site_imports(
+    "dolfinx", "apt", "https://fenicsproject.discourse.group/",
+    "/usr/lib/python3/dist-packages",
+    ["basix", "ffcx", "ufl"],
+    ["fenics-basix", "fenics-ffcx", "fenics-ufl"],
+    [False, False, False],
+    ["", "", ""],
+    pip_uninstall_call
+)
+
+del pip_uninstall_call, pusimp
+
 from dolfinx import common
 from dolfinx import cpp as _cpp
 from dolfinx import fem, geometry, graph, io, jit, la, log, mesh, nls, plot
Index: fenics-dolfinx/python/test/debian-only/test_pusimp.py
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ fenics-dolfinx/python/test/debian-only/test_pusimp.py	2025-11-12 15:50:15.701779222 +0100
@@ -0,0 +1,91 @@
+# Copyright (C) 2024 by the pusimp authors
+#
+# This file is part of pusimp for FEniCSx.
+#
+# SPDX-License-Identifier: LGPL-3.0-or-later
+"""Test DOLFINx patches."""
+
+import os
+import typing
+
+import pytest
+import requests
+
+from pusimp.utils import (
+    assert_package_import_errors_with_local_packages,
+    assert_package_import_errors_with_broken_non_optional_packages,
+    assert_package_import_success_with_allowed_local_packages,
+    assert_package_import_success_without_local_packages
+)
+
+try:
+    response = requests.get("https://www.debian.org", timeout=5)
+except requests.ConnectionError:
+    has_internet = False
+else:
+    has_internet = True
+
+if os.getenv("PUSIMP_EXPECT_DOLFINX_IN_CWD") is None:
+    dolfinx_python_prefix = "/usr/lib/petsc/lib/python3/dist-packages/dolfinx"
+else:
+    dolfinx_python_prefix = os.path.join(os.getcwd(), "dolfinx")
+
+
+def pip_install_call(executable: str, dependency_pypi_name: str) -> str:
+    """Command to be run to install a dependency with pip."""
+    return (
+        f"{executable} -m pip install --ignore-installed --break-system-packages {dependency_pypi_name}"
+        # debian does not ship numpy 2.0 yet, and a pip install-ed numpy 2.0 would break binary compatibility
+        + " 'numpy<2.0'"
+    )
+
+
+def pip_uninstall_call(executable: str, dependency_pypi_name: str, dependency_actual_path: str) -> str:
+    """Command to be run to uninstall a dependency with pip."""
+    return f"{executable} -m pip uninstall --break-system-packages {dependency_pypi_name}"
+
+
+def test_dolfinx_import_success_without_local_packages() -> None:
+    """Test that dolfinx imports correctly without any extra local packages."""
+    assert_package_import_success_without_local_packages(
+        "dolfinx", os.path.join(dolfinx_python_prefix, "__init__.py")
+    )
+
+
+@pytest.mark.skipif(not has_internet, reason="Requires downloading from pypi.org")
+@pytest.mark.parametrize("dependencies_import_name,dependencies_pypi_name,dependencies_extra_error_message", [
+    (["ufl"], ["fenics-ufl"], []),
+    (["basix", "ufl"], ["fenics-basix", "fenics-ufl"], [])
+])
+def test_dolfinx_import_errors_with_local_packages(
+    dependencies_import_name: typing.List[str], dependencies_pypi_name: typing.List[str],
+    dependencies_extra_error_message: typing.List[str]
+) -> None:
+    """Test that dolfinx fails to import with extra local packages."""
+    assert_package_import_errors_with_local_packages(
+        "dolfinx", dependencies_import_name, dependencies_pypi_name, dependencies_extra_error_message,
+        pip_install_call, pip_uninstall_call
+    )
+
+
+@pytest.mark.skipif(not has_internet, reason="Requires downloading from pypi.org")
+@pytest.mark.parametrize("dependencies_import_name,dependencies_pypi_name", [
+    (["ufl"], ["fenics-ufl"])
+])
+def test_dolfinx_import_success_with_allowed_local_packages(
+    dependencies_import_name: typing.List[str], dependencies_pypi_name: typing.List[str]
+) -> None:
+    """Test that dolfinx imports correctly even with extra local packages when asked to allow user-site imports."""
+    assert_package_import_success_with_allowed_local_packages(
+        "dolfinx", os.path.join(dolfinx_python_prefix, "__init__.py"),
+        dependencies_import_name, dependencies_pypi_name, pip_install_call
+    )
+
+
+@pytest.mark.parametrize("dependencies_import_name", [
+    ["ufl"],
+    ["ffcx"]
+])
+def test_dolfinx_import_errors_with_broken_non_optional_packages(dependencies_import_name: typing.List[str]) -> None:
+    """Test that dolfinx fails to import with broken local packages."""
+    assert_package_import_errors_with_broken_non_optional_packages("dolfinx", dependencies_import_name, [False])