Skip to content

Commit

Permalink
Additional deprecations (#685)
Browse files Browse the repository at this point in the history
* Remove some unnecessary code in project.py.

* Make notes on possible deprecations/changes in job.py.

* Replace all DeprecationWarnings with FutureWarnings.

* Deprecate or makes on potentially unnecessary schema APIs.

* Deprecate unnecessary utility module.

* Some notes.

* Revert "Replace all DeprecationWarnings with FutureWarnings."

This reverts commit 102ef00.

* Update comment.

* Minor fixes.

* Add new path properties and deprecate Project.root_directory, Job.ws, and Job.workspace.

* Deprecate Job.reset_statepoint.

* Add version guards for deprecated functionality.

* Deprecate ProjectSchema.detect.

* Deprecate ProjectSchema.__call__.

* Address various minor comments.

* Address most PR comments.

* Add the --path parameter and deprecate --workspace.

* Address PR comments.

* Correctly update internal variable.

* Address PR comments.

* PR comments.

* Fix deprecation import.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Remove cached_property TODOs.

Co-authored-by: Bradley Dice <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Apr 12, 2022
1 parent 1135390 commit aca1315
Show file tree
Hide file tree
Showing 14 changed files with 324 additions and 248 deletions.
26 changes: 22 additions & 4 deletions signac/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ def find_with_filter(args):

def main_project(args):
"""Handle project subcommand."""
warnings.warn(
"The `project` command is deprecated as of version 1.8 and will be removed in "
"version 2.0.",
FutureWarning,
)
project = get_project()
if args.access:
fn = project.create_access_module()
Expand All @@ -258,7 +263,7 @@ def main_project(args):
print(json.dumps(doc))
return
if args.workspace:
print(project.workspace())
print(project.workspace)
else:
print(project)

Expand All @@ -279,7 +284,14 @@ def main_job(args):
if args.create:
job.init()
if args.workspace:
print(job.workspace())
warnings.warn(
"The `-w/--workspace` parameter is deprecated as of version 1.8 and will be removed in "
"version 2.0. Use -p/--path instead",
FutureWarning,
)
args.path = True
if args.path:
print(job.path)
else:
print(job)

Expand Down Expand Up @@ -658,7 +670,7 @@ def _main_import_interactive(project, origin, args):
project_id=project.get_id(),
job_banner="",
root_path=project.root_directory(),
workspace_path=project.workspace(),
workspace_path=project.workspace,
size=len(project),
origin=args.origin,
),
Expand Down Expand Up @@ -1169,7 +1181,7 @@ def write_history_file():
project_id=project.id,
job_banner=f"\nJob:\t\t{job.id}" if job is not None else "",
root_path=project.root_directory(),
workspace_path=project.workspace(),
workspace_path=project.workspace,
size=len(project),
),
)
Expand Down Expand Up @@ -1244,6 +1256,12 @@ def main():
action="store_true",
help="Print the job's workspace path instead of the job id.",
)
parser_job.add_argument(
"-p",
"--path",
action="store_true",
help="Print the job's path instead of the job id.",
)
parser_job.add_argument(
"-c",
"--create",
Expand Down
5 changes: 5 additions & 0 deletions signac/cite.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
from .common.deprecation import deprecated
from .version import __version__

"""
THIS MODULE IS DEPRECATED!
"""


ARXIV_BIBTEX = """@online{signac,
author = {Carl S. Adorf and Paul M. Dodd and Sharon C. Glotzer},
title = {signac - A Simple Data Management Framework},
Expand Down
14 changes: 7 additions & 7 deletions signac/contrib/import_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ def _export_jobs(jobs, path, copytree):
# path_function is checked for uniqueness inside _make_path_function

# Determine export path for each job.
paths = {job.workspace(): path_function(job) for job in jobs}
paths = {job.path: path_function(job) for job in jobs}

# Check leaf/node consistency
_check_directory_structure_validity(paths.values())
Expand Down Expand Up @@ -758,14 +758,14 @@ def _crawl_directory_data_space(root, project, schema_function):
"""
# We compare paths to the 'realpath' of the project workspace to catch loops.
workspace_real_path = os.path.realpath(project.workspace())
workspace_real_path = os.path.realpath(project.workspace)

for path, dirs, _ in os.walk(root):
sp = schema_function(path)
if sp is not None:
del dirs[:] # skip sub-directories
job = project.open_job(sp)
dst = job.workspace()
dst = job.path
if os.path.realpath(path) == os.path.realpath(dst):
continue # skip (already part of the data space)
elif os.path.realpath(path).startswith(workspace_real_path):
Expand All @@ -792,7 +792,7 @@ def _copy_to_job_workspace(src, job, copytree):
Destination filename.
"""
dst = job.workspace()
dst = job.path
try:
copytree(src, dst)
except OSError as error:
Expand Down Expand Up @@ -913,7 +913,7 @@ def __call__(self, copytree=None):
_mkdir_p(os.path.dirname(fn_dst))
with open(fn_dst, "wb") as dst:
dst.write(self.zipfile.read(name))
return self.job.workspace()
return self.job.path

def __str__(self):
return f"{type(self).__name__}({self.root} -> {self.job})"
Expand Down Expand Up @@ -998,7 +998,7 @@ def read_sp_manifest_file(path):
sp = schema_function(name)
if sp is not None:
job = project.open_job(sp)
if os.path.exists(job.workspace()):
if os.path.exists(job.path):
raise DestinationExistsError(job)
mappings[name] = job
skip_subdirs.add(name)
Expand Down Expand Up @@ -1145,7 +1145,7 @@ def read_sp_manifest_file(path):
sp = schema_function(name)
if sp is not None:
job = project.open_job(sp)
if os.path.exists(job.workspace()):
if os.path.exists(job.path):
raise DestinationExistsError(job)
mappings[name] = job
skip_subdirs.add(name)
Expand Down
2 changes: 1 addition & 1 deletion signac/contrib/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ class SignacProjectCrawler(RegexFileCrawler):
def __init__(self, root):
from .project import get_project

root = get_project(root=root).workspace()
root = get_project(root=root).workspace
self._statepoints = {}
return super().__init__(root=root)

Expand Down
107 changes: 68 additions & 39 deletions signac/contrib/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ def _save(self):
# Move the state point to an intermediate location as a backup.
os.replace(self.filename, tmp_statepoint_file)
try:
new_workspace = os.path.join(job._project.workspace(), new_id)
os.replace(job.workspace(), new_workspace)
new_workspace = os.path.join(job._project.workspace, new_id)
os.replace(job.path, new_workspace)
except OSError as error:
os.replace(tmp_statepoint_file, self.filename) # rollback
if error.errno in (errno.EEXIST, errno.ENOTEMPTY, errno.EACCES):
Expand Down Expand Up @@ -281,7 +281,7 @@ def __init__(self, project, statepoint=None, _id=None):
def _initialize_lazy_properties(self):
"""Initialize all properties that are designed to be loaded lazily."""
with self._lock:
self._wd = None
self._path = None
self._document = None
self._stores = None
self._cwd = []
Expand Down Expand Up @@ -321,9 +321,9 @@ def __hash__(self):
def __eq__(self, other):
if not isinstance(other, type(self)):
return NotImplemented
return self.id == other.id and os.path.realpath(
self.workspace()
) == os.path.realpath(other.workspace())
return self.id == other.id and os.path.realpath(self.path) == os.path.realpath(
other.path
)

def __str__(self):
"""Return the job's id."""
Expand All @@ -334,35 +334,54 @@ def __repr__(self):
self.__class__.__name__, repr(self._project), self.statepoint
)

@deprecated(
deprecated_in="1.8",
removed_in="2.0",
current_version=__version__,
details="Use Job.path instead.",
)
def workspace(self):
"""Return the job's unique workspace directory.
See :ref:`signac job -w <signac-cli-job>` for the command line equivalent.
Returns
-------
str
The path to the job's workspace directory.
"""
if self._wd is None:
# We can rely on the project workspace to be well-formed, so just
# use str.join with os.sep instead of os.path.join for speed.
self._wd = os.sep.join((self._project.workspace(), self.id))
return self._wd
"""Alias for :attr:`~Job.path`."""
return self.path

@property
def _statepoint_filename(self):
"""Get the path of the state point file for this job."""
# We can rely on the job workspace to be well-formed, so just
# use str.join with os.sep instead of os.path.join for speed.
return os.sep.join((self.workspace(), self.FN_MANIFEST))
return os.sep.join((self.path, self.FN_MANIFEST))

@property
# Tell mypy to ignore type checking of the decorator because decorated
# properties aren't supported: https://github.com/python/mypy/issues/1362
@property # type: ignore
@deprecated(
deprecated_in="1.8",
removed_in="2.0",
current_version=__version__,
details="Use Job.path instead.",
)
def ws(self):
"""Alias for :meth:`~Job.workspace`."""
return self.workspace()
"""Alias for :attr:`~Job.path`."""
return self.path

@property
def path(self):
"""str: The path to the job directory.
See :ref:`signac job -w <signac-cli-job>` for the command line equivalent.
"""
if self._path is None:
# We can rely on the project workspace to be well-formed, so just
# use str.join with os.sep instead of os.path.join for speed.
self._path = os.sep.join((self._project.workspace, self.id))
return self._path

@deprecated(
deprecated_in="1.8",
removed_in="2.0",
current_version=__version__,
details="Use job.statepoint = new_statepoint instead.",
)
def reset_statepoint(self, new_statepoint):
"""Overwrite the state point of this job while preserving job data.
Expand Down Expand Up @@ -447,7 +466,13 @@ def update_statepoint(self, update, overwrite=False):

@property
def statepoint(self):
"""Get the job's state point.
"""Get or set the job's state point.
Setting the state point to a different value will change the job id.
For more information, see
`Modifying the State Point
<https://docs.signac.io/en/latest/jobs.html#modifying-the-state-point>`_.
.. warning::
Expand All @@ -462,11 +487,16 @@ def statepoint(self):
See :ref:`signac statepoint <signac-cli-statepoint>` for the command line equivalent.
.. danger::
Use this function with caution! Resetting a job's state point
may sometimes be necessary, but can possibly lead to incoherent
data spaces.
Returns
-------
dict
Returns the job's state point.
"""
with self._lock:
if self._statepoint_requires_init:
Expand All @@ -490,7 +520,6 @@ def statepoint(self, new_statepoint):
----------
new_statepoint : dict
The new state point to be assigned.
"""
self.reset_statepoint(new_statepoint)

Expand Down Expand Up @@ -529,7 +558,7 @@ def document(self):
with self._lock:
if self._document is None:
self.init()
fn_doc = os.path.join(self.workspace(), self.FN_DOCUMENT)
fn_doc = os.path.join(self.path, self.FN_DOCUMENT)
self._document = BufferedJSONAttrDict(
filename=fn_doc, write_concern=True
)
Expand Down Expand Up @@ -610,7 +639,7 @@ def stores(self):
with self._lock:
if self._stores is None:
self.init()
self._stores = H5StoreManager(self.workspace())
self._stores = H5StoreManager(self.path)
return self.init()._stores

@property
Expand Down Expand Up @@ -686,7 +715,7 @@ def init(self, force=False):

# Create the workspace directory if it does not exist.
try:
_mkdir_p(self.workspace())
_mkdir_p(self.path)
except OSError:
logger.error(
"Error occurred while trying to create "
Expand Down Expand Up @@ -719,10 +748,10 @@ def clear(self):
"""
try:
for fn in os.listdir(self.workspace()):
for fn in os.listdir(self.path):
if fn in (self.FN_MANIFEST, self.FN_DOCUMENT):
continue
path = os.path.join(self.workspace(), fn)
path = os.path.join(self.path, fn)
if os.path.isfile(path):
os.remove(path)
elif os.path.isdir(path):
Expand Down Expand Up @@ -753,7 +782,7 @@ def remove(self):
"""
with self._lock:
try:
shutil.rmtree(self.workspace())
shutil.rmtree(self.path)
except OSError as error:
if error.errno != errno.ENOENT:
raise
Expand Down Expand Up @@ -784,9 +813,9 @@ def move(self, project):
with self._lock:
statepoint = self.statepoint()
dst = project.open_job(statepoint)
_mkdir_p(project.workspace())
_mkdir_p(project.workspace)
try:
os.replace(self.workspace(), dst.workspace())
os.replace(self.path, dst.path)
except OSError as error:
if error.errno == errno.ENOENT:
raise RuntimeError(
Expand Down Expand Up @@ -872,7 +901,7 @@ def fn(self, filename):
The full workspace path of the file.
"""
return os.path.join(self.workspace(), filename)
return os.path.join(self.path, filename)

def isfile(self, filename):
"""Return True if file exists in the job's workspace.
Expand Down Expand Up @@ -906,8 +935,8 @@ def open(self):
"""
self._cwd.append(os.getcwd())
self.init()
logger.info(f"Enter workspace '{self.workspace()}'.")
os.chdir(self.workspace())
logger.info(f"Enter workspace '{self.path}'.")
os.chdir(self.path)

def close(self):
"""Close the job and switch to the previous working directory."""
Expand Down
4 changes: 2 additions & 2 deletions signac/contrib/linked_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ def create_linked_view(project, prefix=None, job_ids=None, index=None, path=None
links = {}
for job in jobs:
paths = os.path.join(path_function(job), "job")
links[paths] = job.workspace()
links[paths] = job.path
if not links: # data space contains less than two elements
for job in project.find_jobs():
links["./job"] = job.workspace()
links["./job"] = job.path
assert len(links) < 2
_check_directory_structure_validity(links.keys())
_update_view(prefix, links)
Expand Down
Loading

0 comments on commit aca1315

Please sign in to comment.