• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pyiron / pyiron_base / 8192293926

07 Mar 2024 05:26PM UTC coverage: 91.951% (-0.003%) from 91.954%
8192293926

push

github

web-flow
[patch] Introduce a flag for _not_ mangling the name of wrapped function jobs (#1356)

* Introduce a flag for _not_ mangling the name of wrapped function jobs

* Don't even override with function name, just keep the given name

* Add comment on the private var

* Indent and isolate the entire mangling block

Then fall back on super() otherwise, to further clarify the intent of the mangling

* Update pyiron_base/jobs/flex/pythonfunctioncontainer.py

Co-authored-by: Jan Janssen <jan-janssen@users.noreply.github.com>

* Fix early return logic

That we broke by committing the readability suggestion

* Use a more descriptive name

* fix formatting

* Format black

---------

Co-authored-by: Jan Janssen <jan-janssen@users.noreply.github.com>
Co-authored-by: pyiron-runner <pyiron@mpie.de>

12 of 15 new or added lines in 1 file covered. (80.0%)

8659 of 9417 relevant lines covered (91.95%)

1.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.75
/pyiron_base/jobs/flex/pythonfunctioncontainer.py
1
import inspect
2✔
2
import hashlib
2✔
3
import re
2✔
4
import cloudpickle
2✔
5
import numpy as np
2✔
6
from pyiron_base.jobs.job.template import PythonTemplateJob
2✔
7

8

9
def get_function_parameter_dict(funct):
2✔
10
    return {
2✔
11
        k: None if v.default == inspect._empty else v.default
1✔
12
        for k, v in inspect.signature(funct).parameters.items()
1✔
13
    }
14

15

16
def get_hash(binary):
2✔
17
    # Remove specification of jupyter kernel from hash to be deterministic
18
    binary_no_ipykernel = re.sub(b"(?<=/ipykernel_)(.*)(?=/)", b"", binary)
2✔
19
    return str(hashlib.md5(binary_no_ipykernel).hexdigest())
2✔
20

21

22
class PythonFunctionContainerJob(PythonTemplateJob):
2✔
23
    """
24
    The PythonFunctionContainerJob is designed to wrap any kind of python function into a pyiron job object
25

26
    Example:
27

28
    >>> def test_function(a, b=8):
29
    >>>     return a+b
30
    >>>
31
    >>> from pyiron_base import Project
32
    >>> pr = Project("test")
33
    >>> job = pr.wrap_python_function(test_function)
34
    >>> job.input["a"] = 4
35
    >>> job.input["b"] = 5
36
    >>> job.run()
37
    >>> job.output
38
    >>>
39
    >>> test_function_wrapped = pr.wrap_python_function(test_function)
40
    >>> test_function_wrapped(4, b=6)
41
    """
42

43
    def __init__(self, project, job_name):
2✔
44
        super().__init__(project, job_name)
2✔
45
        self._function = None
2✔
46
        self._executor_type = None
2✔
47
        self._automatically_rename_on_save_using_input = True
2✔
48

49
    @property
2✔
50
    def python_function(self):
2✔
51
        return self._function
×
52

53
    @python_function.setter
2✔
54
    def python_function(self, funct):
2✔
55
        self.input.update(get_function_parameter_dict(funct=funct))
2✔
56
        self._function = funct
2✔
57

58
    def __call__(self, *args, **kwargs):
2✔
59
        self.input.update(
2✔
60
            inspect.signature(self._function).bind(*args, **kwargs).arguments
1✔
61
        )
62
        self.run()
2✔
63
        return self.output["result"]
2✔
64

65
    def to_hdf(self, hdf=None, group_name=None):
2✔
66
        super().to_hdf(hdf=hdf, group_name=group_name)
2✔
67
        self.project_hdf5["function"] = np.void(cloudpickle.dumps(self._function))
2✔
68
        self.project_hdf5["_automatically_rename_on_save_using_input"] = (
2✔
69
            self._automatically_rename_on_save_using_input
1✔
70
        )
71

72
    def from_hdf(self, hdf=None, group_name=None):
2✔
73
        super().from_hdf(hdf=hdf, group_name=group_name)
2✔
74
        self._function = cloudpickle.loads(self.project_hdf5["function"])
2✔
75
        self._automatically_rename_on_save_using_input = bool(
2✔
76
            self.project_hdf5["_automatically_rename_on_save_using_input"]
1✔
77
        )
78

79
    def save(self):
2✔
80
        if self._automatically_rename_on_save_using_input:
2✔
81
            job_name = self._function.__name__ + get_hash(
2✔
82
                binary=cloudpickle.dumps(
1✔
83
                    {"fn": self._function, "kwargs": self.input.to_builtin()}
1✔
84
                )
85
            )
86

87
            self.job_name = job_name
2✔
88

89
            if self.job_name in self.project.list_nodes():
2✔
NEW
90
                self.from_hdf()
×
NEW
91
                self.status.finished = True
×
NEW
92
                return  # Without saving
×
93
        super().save()
2✔
94

95
    def run_static(self):
2✔
96
        if (
1✔
97
            self._executor_type is not None
1✔
98
            and "executor" in inspect.signature(self._function).parameters.keys()
1✔
99
        ):
100
            input_dict = self.input.to_builtin()
2✔
101
            del input_dict["executor"]
2✔
102
            output = self._function(
2✔
103
                **input_dict, executor=self._get_executor(max_workers=self.server.cores)
1✔
104
            )
105
        else:
106
            output = self._function(**self.input.to_builtin())
2✔
107
        self.output.update({"result": output})
2✔
108
        self.to_hdf()
2✔
109
        self.status.finished = True
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc