Skip to content

Commit 45b12e2

Browse files
author
Phil Varner
authored
cleanup workdir correctly (#70)
* cleanup workdir correctly
1 parent cbf9d00 commit 45b12e2

File tree

4 files changed

+54
-38
lines changed

4 files changed

+54
-38
lines changed

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,17 @@ repos:
1616
args: [--ignore-words=.codespellignore]
1717
types_or: [jupyter, markdown, python, shell]
1818
- repo: https://github.com/psf/black
19-
rev: 23.9.1
19+
rev: 23.12.0
2020
hooks:
2121
- id: black
2222
- repo: https://github.com/pre-commit/mirrors-mypy
23-
rev: v1.6.0
23+
rev: v1.7.1
2424
hooks:
2525
- id: mypy
2626
additional_dependencies:
2727
- pytest
2828
- types-setuptools == 65.7.0.3
2929
- repo: https://github.com/astral-sh/ruff-pre-commit
30-
rev: v0.0.292
30+
rev: v0.1.8
3131
hooks:
3232
- id: ruff

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## Unreleased - TBD
9+
10+
### Changed
11+
12+
- handler now explicitly calls performs workdir cleanup
13+
- workdir cleanup is correctly defensive and logs errors
14+
815
## [v0.2.0] - 2023-11-16
916

1017
### Changed

stactask/task.py

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import itertools
44
import json
55
import logging
6+
import os
67
import sys
78
import warnings
89
from abc import ABC, abstractmethod
@@ -64,13 +65,9 @@ def __init__(
6465
skip_upload: bool = False,
6566
skip_validation: bool = False,
6667
):
67-
# set up logger
6868
self.logger = logging.getLogger(self.name)
6969

70-
# set this to avoid confusion in destructor if called during validation
71-
self._save_workdir = True
72-
73-
# validate input payload...or not
70+
# validate input payload... or not
7471
if not skip_validation:
7572
if not self.validate(payload):
7673
raise FailedValidation()
@@ -90,12 +87,6 @@ def __init__(
9087
# if a workdir was specified we don't want to rm by default
9188
self._save_workdir = save_workdir if save_workdir is not None else True
9289

93-
def __del__(self) -> None:
94-
# remove work directory if not running locally
95-
if not self._save_workdir:
96-
self.logger.debug("Removing work directory %s", self._workdir)
97-
rmtree(self._workdir)
98-
9990
@property
10091
def process_definition(self) -> Dict[str, Any]:
10192
process = self._payload.get("process", {})
@@ -198,6 +189,21 @@ def add_software_version_to_item(cls, item: Dict[str, Any]) -> Dict[str, Any]:
198189
item["properties"]["processing:software"] = {cls.name: cls.version}
199190
return item
200191

192+
def cleanup_workdir(self) -> None:
193+
"""Remove work directory if configured not to save it"""
194+
try:
195+
if (
196+
not self._save_workdir
197+
and self._workdir
198+
and os.path.exists(self._workdir)
199+
):
200+
self.logger.debug("Removing work directory %s", self._workdir)
201+
rmtree(self._workdir)
202+
except Exception as e:
203+
self.logger.warning(
204+
"Failed removing work directory %s: %s", self._workdir, e
205+
)
206+
201207
def assign_collections(self) -> None:
202208
"""Assigns new collection names based on"""
203209
for i, (coll, expr) in itertools.product(
@@ -305,24 +311,27 @@ def post_process_item(self, item: Dict[str, Any]) -> Dict[str, Any]:
305311

306312
@classmethod
307313
def handler(cls, payload: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]:
308-
if "href" in payload or "url" in payload:
309-
# read input
310-
with fsspec.open(payload.get("href", payload.get("url"))) as f:
311-
payload = json.loads(f.read())
312-
313-
task = cls(payload, **kwargs)
314314
try:
315-
items = list()
316-
for item in task.process(**task.parameters):
317-
items.append(task.post_process_item(item))
318-
319-
task._payload["features"] = items
320-
task.assign_collections()
321-
322-
return task._payload
323-
except Exception as err:
324-
task.logger.error(err, exc_info=True)
325-
raise err
315+
if "href" in payload or "url" in payload:
316+
# read input
317+
with fsspec.open(payload.get("href", payload.get("url"))) as f:
318+
payload = json.loads(f.read())
319+
320+
task = cls(payload, **kwargs)
321+
try:
322+
items = list()
323+
for item in task.process(**task.parameters):
324+
items.append(task.post_process_item(item))
325+
326+
task._payload["features"] = items
327+
task.assign_collections()
328+
329+
return task._payload
330+
except Exception as err:
331+
task.logger.error(err, exc_info=True)
332+
raise err
333+
finally:
334+
task.cleanup_workdir()
326335

327336
@classmethod
328337
def parse_args(cls, args: List[str]) -> Dict[str, Any]:

tests/test_task.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ def test_edit_items2(nothing_task: Task) -> None:
5656

5757
@pytest.mark.parametrize("save_workdir", [False, True, None])
5858
def test_tmp_workdir(items: Dict[str, Any], save_workdir: Optional[bool]) -> None:
59-
nothing_task = NothingTask(items, save_workdir=save_workdir)
59+
t = NothingTask(items, save_workdir=save_workdir)
6060
expected = save_workdir if save_workdir is not None else False
61-
assert nothing_task._save_workdir is expected
62-
workdir = nothing_task._workdir
61+
assert t._save_workdir is expected
62+
workdir = t._workdir
6363
assert workdir.parts[-1].startswith("tmp")
6464
assert workdir.is_absolute() is True
6565
assert workdir.is_dir() is True
66-
del nothing_task
67-
assert workdir.is_dir() is expected
66+
t.cleanup_workdir()
67+
assert workdir.exists() is expected
6868

6969

7070
@pytest.mark.parametrize("save_workdir", [False, True, None])
@@ -80,8 +80,8 @@ def test_workdir(
8080
assert workdir.parts[-1] == "test_task"
8181
assert workdir.is_absolute() is True
8282
assert workdir.is_dir() is True
83-
del t
84-
assert workdir.is_dir() is expected
83+
t.cleanup_workdir()
84+
assert workdir.exists() is expected
8585

8686

8787
def test_parameters(items: Dict[str, Any]) -> None:

0 commit comments

Comments
 (0)