diff --git a/pyproject.toml b/pyproject.toml index f4518c0c..876953bf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "poli" -version = "1.0.0.dev11" +version = "1.0.0.dev12" description = "poli, a library of discrete objective functions" readme = "README.md" authors = [{name="Miguel González-Duque", email="miguelgondu@gmail.com"}, {name="Simon Bartels"}] @@ -38,7 +38,10 @@ protein = [ "python-levenshtein", "pdb-tools", ] -ehrlich_holo = [ +ehrlich = [ + "pytorch-holo", +] +ehrlichholo = [ "pytorch-holo", ] tdc = [ @@ -76,7 +79,7 @@ profile = "black" exclude = ["src/poli/core/util/proteins/rasp/inner_rasp", "src/poli/objective_repository/gfp_cbas"] [tool.bumpversion] -current_version = "1.0.0.dev11" +current_version = "1.0.0.dev12" parse = """(?x) (?P0|[1-9]\\d*)\\. (?P0|[1-9]\\d*)\\. diff --git a/setup.cfg b/setup.cfg index 55d4e145..acd86cf7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = poli -version = "1.0.0.dev11" +version = "1.0.0.dev12" author = Miguel González-Duque author_email = miguel.gonzalez-duque@bio.ku.dk description = A library of discrete objective functions diff --git a/src/poli/__init__.py b/src/poli/__init__.py index 96fd2974..5ffc17ac 100644 --- a/src/poli/__init__.py +++ b/src/poli/__init__.py @@ -1,6 +1,6 @@ """poli, a library for discrete black-box objective functions.""" -__version__ = "1.0.0.dev11" +__version__ = "1.0.0.dev12" from .core.util.isolation.instancing import instance_function_as_isolated_process # from .core import get_problems diff --git a/src/poli/core/util/isolation/external_function.py b/src/poli/core/util/isolation/external_function.py index ea76807f..1d9ae149 100644 --- a/src/poli/core/util/isolation/external_function.py +++ b/src/poli/core/util/isolation/external_function.py @@ -89,16 +89,51 @@ def __getattr__(self, __name: str) -> Any: attribute : Any The attribute of the underlying black-box function. """ - self.process_wrapper.send(["ATTRIBUTE", __name]) + self.process_wrapper.send(["IS_METHOD", __name]) msg_type, *msg = self.process_wrapper.recv() if msg_type == "EXCEPTION": e, traceback_ = msg print(traceback_) raise e else: - assert msg_type == "ATTRIBUTE" - attribute = msg[0] - return attribute + assert msg_type == "IS_METHOD" + is_method = msg[0] + + if is_method: + return lambda *args, **kwargs: self._method_call(__name, *args, **kwargs) + else: + self.process_wrapper.send(["ATTRIBUTE", __name]) + msg_type, *msg = self.process_wrapper.recv() + if msg_type == "EXCEPTION": + e, traceback_ = msg + print(traceback_) + raise e + else: + assert msg_type == "ATTRIBUTE" + attribute = msg[0] + return attribute + + def _method_call(self, method_name: str, *args, **kwargs) -> Any: + """Calls a method of the underlying isolated function. + + Asks for the method of the underlying + isolated function by sending a message + to the process w. the msg_type "METHOD". + + Parameters + ---------- + method_name : str + The name of the method. + """ + self.process_wrapper.send(["METHOD", method_name, args, kwargs]) + msg_type, *msg = self.process_wrapper.recv() + if msg_type == "EXCEPTION": + e, traceback_ = msg + print(traceback_) + raise e + else: + assert msg_type == "METHOD" + return msg[0] def __del__(self): self.terminate() diff --git a/src/poli/external_isolated_function_script.py b/src/poli/external_isolated_function_script.py index f24c3595..e81cb966 100644 --- a/src/poli/external_isolated_function_script.py +++ b/src/poli/external_isolated_function_script.py @@ -114,8 +114,20 @@ def run(objective_name: str, port: int, password: str) -> None: y = f(x, context=context) conn.send(["QUERY", y]) elif msg_type == "ATTRIBUTE": - attribute = getattr(f, msg[0]) + attribute_name = msg[0] + attribute = getattr(f, attribute_name) conn.send(["ATTRIBUTE", attribute]) + elif msg_type == "IS_METHOD": + attribute_name = msg[0] + is_method = callable(getattr(f, attribute_name)) + conn.send(["IS_METHOD", is_method]) + elif msg_type == "METHOD": + method_name = msg[0] + method_args = msg[1] + method_kwargs = msg[2] + method = getattr(f, method_name) + result = method(*method_args, **method_kwargs) + conn.send(["METHOD", result]) except Exception as e: tb = traceback.format_exc() conn.send(["EXCEPTION", e, tb]) diff --git a/src/poli/tests/registry/toy_discrete_problems/test_ehrlich_holo.py b/src/poli/tests/registry/toy_discrete_problems/test_ehrlich_holo.py index 62e6d410..9747a14f 100644 --- a/src/poli/tests/registry/toy_discrete_problems/test_ehrlich_holo.py +++ b/src/poli/tests/registry/toy_discrete_problems/test_ehrlich_holo.py @@ -40,11 +40,13 @@ def test_ehrlich_holo_builds_and_queries(): These issues will be addressed by the new isolation interface, and if the user installs this black box with -`pip install poli[ehrlich_holo]` they won't face these issues. +`pip install poli[ehrlich]` they won't face these issues. + +The error we currently get is the following: +multiprocessing.context.AuthenticationError: digest sent was rejected Testing it locally seems to work well. TODO: install in Colab and test. -TODO: fix. """ # @pytest.mark.poli__ehrlich_holo # def test_ehrlich_holo_works_on_isolation(): @@ -57,7 +59,7 @@ def test_ehrlich_holo_builds_and_queries(): # epistasis_factor=0.0, # force_isolation=True, # ) -# x0 = black_box.initial_solution() +# x0 = black_box.initial_solution(100) # print(black_box(x0)) # x_final = black_box.optimal_solution() diff --git a/tox.ini b/tox.ini index a12f4834..c7972973 100644 --- a/tox.ini +++ b/tox.ini @@ -120,6 +120,6 @@ wheel_build_env = .pkg deps= {[testenv]deps} -r requirements.txt - -e.[ehrlich_holo] + -e.[ehrlich] commands= pytest {tty:--color=yes} -v -m 'not slow and poli__ehrlich_holo' {posargs} \ No newline at end of file