Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: LockException #1276

Merged
merged 12 commits into from May 10, 2022
14 changes: 14 additions & 0 deletions snakemake/exceptions.py
Expand Up @@ -532,3 +532,17 @@ def __init__(self, rule, targetfile):

class CacheMissException(Exception):
pass


class LockException(WorkflowError):
def __init__(self):
super().__init__(
"Error: Directory cannot be locked. Please make "
"sure that no other Snakemake process is trying to create "
"the same files in the following directory:\n{}\n"
"If you are sure that no other "
"instances of snakemake are running on this directory, "
"the remaining lock was likely caused by a kill signal or "
"a power loss. It can be removed with "
"the --unlock argument.".format(os.getcwd())
)
3 changes: 2 additions & 1 deletion snakemake/persistence.py
Expand Up @@ -15,6 +15,7 @@
from itertools import filterfalse, count
from pathlib import Path

import snakemake.exceptions
from snakemake.logging import logger
from snakemake.jobs import jobfiles
from snakemake.utils import listfiles
Expand Down Expand Up @@ -167,7 +168,7 @@ def lock_warn_only(self):

def lock(self):
if self.locked:
raise IOError("Another snakemake process " "has locked this directory.")
raise snakemake.exceptions.LockException()
self._lock(self.all_inputfiles(), "input")
self._lock(self.all_outputfiles(), "output")

Expand Down
15 changes: 1 addition & 14 deletions snakemake/workflow.py
Expand Up @@ -776,20 +776,7 @@ def files(items):
dag.update_checkpoint_dependencies()
dag.check_dynamic()

try:
self.persistence.lock()
except IOError:
logger.error(
"Error: Directory cannot be locked. Please make "
"sure that no other Snakemake process is trying to create "
"the same files in the following directory:\n{}\n"
"If you are sure that no other "
"instances of snakemake are running on this directory, "
"the remaining lock was likely caused by a kill signal or "
"a power loss. It can be removed with "
"the --unlock argument.".format(os.getcwd())
)
return False
self.persistence.lock()

if cleanup_shadow:
self.persistence.cleanup_shadow()
Expand Down
15 changes: 15 additions & 0 deletions tests/testapi.py
Expand Up @@ -57,3 +57,18 @@ async def main():
async_run(main())
else:
asyncio.run(main())


def test_lockexception():
from snakemake.persistence import Persistence
from snakemake.exceptions import LockException

persistence = Persistence()
persistence.all_inputfiles = lambda: ["A.txt"]
persistence.all_outputfiles = lambda: ["B.txt"]
persistence.lock()
try:
persistence.lock()
except LockException as e:
return True
assert False