-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Black line length * Add tests for loading and inspecting * Introduce and test helper classes for loading and inspecting * Don't deprecate the conversion argument It gets used in iter methods in a reasonable way * Use just inspect or load if conversion is not a variable * Format black * Update pyiron_base/project/generic.py Co-authored-by: Marvin Poul <poul@mpie.de> * Break test into subtests * Directly check getattr, as suggested by @pmrv * Move loader classes to their own module, per @jan-janssen's suggestion * Use full import path * Move tests to their own test module * Break sub tests into separate tests * PEP8 * Also work without a database, per @jan-janssen's concern * Make sure loader values are always synced with project values The project knows how to stay up-to-date with the state; instead of re-inventing this security, let's just directly use the project attributes. * Store and restore all the settings Let's see if this recovers the `project_path` configuration setting that the projectpath tests seem to be relying on * Format black * Add logging to try and debug remote ci * Remove sibling tests * Add path to debug print * More logging * More logging * Log more about the loader project * Add filters progressively in logging * Log the filetable path * Log the actual folder contents * Narrow the search * Just look at length and look before turning off the database too * Log the actual recursion check results * Revert changes, the problem is upstream in FileTable still I don't see trouble on my local machine because I don't specify TOP_LEVEL_DIRS in my config but the CI does. * Resolve some codacy nits * Update class descriptions * Test sub-project loading * Update tests to account for extra job in TestWithFilledProject Making some effort to avoid magic numbers --------- Co-authored-by: pyiron-runner <pyiron@mpie.de> Co-authored-by: Marvin Poul <poul@mpie.de>
- Loading branch information
1 parent
0bba2c6
commit ca75ea1
Showing
8 changed files
with
349 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
# coding: utf-8 | ||
# Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department | ||
# Distributed under the terms of "New BSD License", see the LICENSE file. | ||
""" | ||
A helper class to be assigned to the project, which facilitates tab-completion when | ||
loading jobs. | ||
""" | ||
from __future__ import annotations | ||
|
||
from abc import ABC, abstractmethod | ||
from typing import TYPE_CHECKING | ||
|
||
import numpy as np | ||
|
||
from pyiron_base.state import state | ||
from pyiron_base.database.jobtable import get_job_id | ||
from pyiron_base.jobs.job.util import _get_safe_job_name | ||
|
||
if TYPE_CHECKING: | ||
from pyiron_base.jobs.job.generic import GenericJob | ||
from pyiron_base.jobs.job.path import JobPath | ||
from pyiron_base.project.generic import Project | ||
|
||
|
||
class _JobByAttribute(ABC): | ||
""" | ||
A parent class for accessing project jobs by a call and a job specifier, or by tab | ||
completion. | ||
""" | ||
|
||
def __init__(self, project: Project): | ||
self._project = project | ||
|
||
@property | ||
def _job_table(self): | ||
return self._project.job_table(columns=["job"]) | ||
|
||
@property | ||
def _job_names(self): | ||
return self._job_table["job"].values | ||
|
||
def __dir__(self): | ||
return self._job_names | ||
|
||
def _id_from_name(self, name): | ||
return self._job_table.loc[self._job_names == name, "id"].values[0] | ||
|
||
def __getattr__(self, item): | ||
return self._project.load_from_jobpath( | ||
job_id=self._id_from_name(item), convert_to_object=self.convert_to_object | ||
) | ||
|
||
def __getitem__(self, item): | ||
return self.__getattr__(item) | ||
|
||
def __call__(self, job_specifier, convert_to_object=None): | ||
if self._project.sql_query is not None: | ||
state.logger.warning( | ||
f"SQL filter '{self._project.sql_query}' is active (may exclude job)" | ||
) | ||
if not isinstance(job_specifier, (int, np.integer)): | ||
job_specifier = _get_safe_job_name(name=job_specifier) | ||
job_id = get_job_id( | ||
database=self._project.db, | ||
sql_query=self._project.sql_query, | ||
user=self._project.user, | ||
project_path=self._project.project_path, | ||
job_specifier=job_specifier, | ||
) | ||
if job_id is None: | ||
state.logger.warning( | ||
f"Job '{job_specifier}' does not exist and cannot be loaded" | ||
) | ||
return None | ||
return self._project.load_from_jobpath( | ||
job_id=job_id, | ||
convert_to_object=convert_to_object | ||
if convert_to_object is not None | ||
else self.convert_to_object, | ||
) | ||
|
||
@property | ||
@abstractmethod | ||
def convert_to_object(self): | ||
pass | ||
|
||
|
||
class JobLoader(_JobByAttribute): | ||
""" | ||
Load an existing pyiron object - most commonly a job - from the database | ||
Args: | ||
job_specifier (str, int): name of the job or job ID | ||
Returns: | ||
GenericJob, JobCore: Either the full GenericJob object or just a reduced JobCore object | ||
""" | ||
|
||
convert_to_object = True | ||
|
||
def __call__(self, job_specifier, convert_to_object=None) -> GenericJob: | ||
return super().__call__(job_specifier, convert_to_object=convert_to_object) | ||
|
||
|
||
class JobInspector(_JobByAttribute): | ||
""" | ||
Inspect an existing pyiron object - most commonly a job - from the database | ||
Args: | ||
job_specifier (str, int): name of the job or job ID | ||
Returns: | ||
JobCore: Access to the HDF5 object - not a GenericJob object - use :meth:`~.Project.load()` | ||
instead. | ||
""" | ||
|
||
convert_to_object = False | ||
|
||
def __call__(self, job_specifier) -> JobPath: | ||
return super().__call__(job_specifier) |
Oops, something went wrong.