Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
payno
workflow_concepts
Commits
7fc82c0d
Commit
7fc82c0d
authored
Jun 12, 2021
by
Wout De Nolf
Browse files
esrftaskgraph: refactor exist/available to has_value, has_runtime_value and has_persistent_value
parent
53b5dbea
Changes
4
Expand all
Hide whitespace changes
Inline
Side-by-side
esrftaskgraph/esrftaskgraph/task.py
View file @
7fc82c0d
...
...
@@ -179,31 +179,31 @@ class Task(Registered, hashing.UniversalHashable, register=False):
@
property
def
done
(
self
):
"""Completed (with or without exception)"""
return
self
.
failed
or
self
.
_outputs
.
availabl
e
return
self
.
failed
or
self
.
_outputs
.
has_valu
e
@
property
def
failed
(
self
):
return
self
.
_exception
is
not
None
def
_
unavailable_input
s
(
self
):
def
_
iter_missing_input_value
s
(
self
):
for
iname
in
self
.
_INPUT_NAMES
:
i
var
=
self
.
_inputs
.
get
(
iname
)
if
i
var
is
None
or
not
i
var
.
availabl
e
:
var
=
self
.
_inputs
.
get
(
iname
)
if
var
is
None
or
not
var
.
has_valu
e
:
yield
iname
@
property
def
is_ready_to_execute
(
self
):
try
:
next
(
iter
(
self
.
_
unavailable_input
s
()))
next
(
iter
(
self
.
_
iter_missing_input_value
s
()))
except
StopIteration
:
return
True
return
False
def
assert_ready_to_execute
(
self
):
unavailable
=
list
(
self
.
_
unavailable_input
s
())
if
unavailable
:
lst
=
list
(
self
.
_
iter_missing_input_value
s
())
if
lst
:
raise
TaskInputError
(
"The following inputs could not be loaded: "
+
str
(
unavailable
)
"The following inputs could not be loaded: "
+
str
(
lst
)
)
def
execute
(
self
,
force_rerun
=
False
,
raise_on_error
=
True
):
...
...
esrftaskgraph/esrftaskgraph/variable.py
View file @
7fc82c0d
...
...
@@ -46,17 +46,16 @@ def atomic_write(filename):
class
Variable
(
hashing
.
UniversalHashable
):
"""Has a runtime representation (python object) and a persistent
representation (JSON).
"""Has a runtime value (python object) and a persistent value (JSON).
TODO: make abstraction of persistent
representation
TODO: make abstraction of persistent
medium
"""
def
__init__
(
self
,
value
=
hashing
.
UniversalHashable
.
MISSING_DATA
,
varinfo
=
None
,
**
kw
):
"""
:param value: the runtime
representation
:param value: the runtime
value
:param dict varinfo:
:param **kw: see `UniversalHashable`
"""
...
...
@@ -66,16 +65,16 @@ class Variable(hashing.UniversalHashable):
raise
TypeError
(
varinfo
,
type
(
varinfo
))
self
.
_root_uri
=
varinfo
.
get
(
"root_uri"
)
self
.
_disable_persistency
=
not
self
.
_root_uri
self
.
_runtime_
representation
=
self
.
MISSING_DATA
self
.
_runtime_
value
=
self
.
MISSING_DATA
super
().
__init__
(
**
kw
)
self
.
value
=
value
def
_uhash_data
(
self
):
"""The runtime
representation of the
value is used."""
"""The runtime value is used."""
if
self
.
_disable_persistency
:
return
super
().
_uhash_data
()
else
:
return
self
.
_runtime_
representation
return
self
.
_runtime_
value
def
__eq__
(
self
,
other
):
if
isinstance
(
other
,
hashing
.
UniversalHashable
):
...
...
@@ -85,17 +84,17 @@ class Variable(hashing.UniversalHashable):
@
property
def
value
(
self
):
if
self
.
_runtime_
representation
is
self
.
MISSING_DATA
:
self
.
value
=
self
.
load
(
raise_error
=
False
)
return
self
.
_runtime_
representation
if
self
.
_runtime_
value
is
self
.
MISSING_DATA
:
self
.
load
(
raise_error
=
False
)
return
self
.
_runtime_
value
@
value
.
setter
def
value
(
self
,
v
):
self
.
_runtime_
representation
=
v
self
.
_runtime_
value
=
v
@
property
def
uri
(
self
):
"""uri of the persistent
representation
"""uri of the persistent
value
:returns str or None: returns None when uhash is None
"""
...
...
@@ -108,93 +107,88 @@ class Variable(hashing.UniversalHashable):
return
filename
def
dump
(
self
):
"""From runtime to persistent
representation
(never overwrite).
Creating the persistent
representation
needs to be atomic.
"""From runtime to persistent
value
(never overwrite).
Creating the persistent
value
needs to be atomic.
This silently returns when:
- persistency is disabled
- already persisted
- data
i
s not av
ailabl
e (MISSING_DATA)
- data
doe
s not
h
av
e a runtime valu
e (MISSING_DATA)
- non value URI can be constructed
"""
if
self
.
_disable_persistency
or
self
.
exists
or
not
self
.
available
:
if
(
self
.
_disable_persistency
or
self
.
has_persistent_value
or
not
self
.
has_runtime_value
):
return
filename
=
self
.
uri
if
not
filename
:
return
data
=
self
.
value
with
atomic_write
(
filename
)
as
f
:
json
.
dump
(
self
.
serialize
(
data
),
f
)
json
.
dump
(
self
.
_
serialize
(
data
),
f
)
def
load
(
self
,
raise_error
=
True
):
"""From persistent to runtime representation
"""From persistent to runtime value. This is called when
try to get the value (lazy loading).
This silently returns when:
- persistency is disabled
- uri is None (i.e. uhash is None)
- raise_error=False
"""
if
self
.
_disable_persistency
:
return
self
.
_runtime_representation
return
filename
=
self
.
uri
if
not
filename
:
return
self
.
_runtime_representation
return
try
:
with
open
(
filename
,
mode
=
"r"
)
as
f
:
return
self
.
deserialize
(
json
.
load
(
f
))
self
.
_runtime_value
=
self
.
_
deserialize
(
json
.
load
(
f
))
except
FileNotFoundError
as
e
:
if
raise_error
:
raise
UriNotFoundError
(
filename
)
from
e
else
:
return
self
.
_runtime_representation
except
Exception
as
e
:
if
raise_error
:
raise
PersistencyError
(
filename
)
from
e
else
:
return
self
.
_runtime_representation
def
serialize
(
self
,
value
):
def
_
serialize
(
self
,
value
):
"""Before runtime to persistent"""
return
value
def
deserialize
(
self
,
value
):
def
_
deserialize
(
self
,
value
):
"""Before persistent to runtime"""
return
value
@
property
def
exists
(
self
):
"""Has a persistent representation"""
return
self
.
_exists
()
def
has_persistent_value
(
self
):
return
self
.
_has_persistent_value
()
@
property
def
available
(
self
):
"""Has a runtime representation"""
def
has_runtime_value
(
self
):
try
:
return
self
.
_
availabl
e
()
return
self
.
_
has_runtime_valu
e
()
except
PersistencyError
:
# Lazy loading failed
return
False
def
_exists
(
self
):
"""Has a persistent representation"""
@
property
def
has_value
(
self
):
return
self
.
has_runtime_value
or
self
.
has_persistent_value
def
_has_persistent_value
(
self
):
filename
=
self
.
uri
if
filename
:
return
os
.
path
.
isfile
(
filename
)
else
:
return
False
def
_available
(
self
):
"""Has a runtime representation"""
return
self
.
value
is
not
self
.
MISSING_DATA
def
validate
(
self
):
if
not
self
.
exists
:
raise
RuntimeError
(
"Has no persistent representation"
)
if
not
self
.
available
:
raise
RuntimeError
(
"Has no runtime representation"
)
return
self
.
value
==
self
.
load
()
def
_has_runtime_value
(
self
):
return
self
.
_runtime_value
is
not
self
.
MISSING_DATA
def
force_non_existing
(
self
):
while
self
.
exists
:
while
self
.
has_persistent_value
:
self
.
uhash_randomize
()
...
...
@@ -258,7 +252,10 @@ class VariableContainer(Mapping, Variable):
return
Variable
(
**
varparams
)
def
_initialize_container
(
self
):
if
not
self
.
container_available
and
not
self
.
container_exists
:
if
(
not
self
.
container_has_runtime_value
and
not
self
.
container_has_persistent_value
):
self
.
value
=
dict
()
def
__iter__
(
self
):
...
...
@@ -275,10 +272,10 @@ class VariableContainer(Mapping, Variable):
else
:
return
0
def
serialize
(
self
,
value
):
def
_
serialize
(
self
,
value
):
return
{
k
:
str
(
v
.
uhash
)
for
k
,
v
in
self
.
items
()}
def
deserialize
(
self
,
value
):
def
_
deserialize
(
self
,
value
):
adict
=
dict
()
varparams
=
dict
(
self
.
__varparams
)
varparams
[
"uhash_nonce"
]
=
None
...
...
@@ -293,26 +290,22 @@ class VariableContainer(Mapping, Variable):
super
().
dump
()
@
property
def
container_
exists
(
self
):
return
super
().
_
exists
()
def
container_
has_persistent_value
(
self
):
return
super
().
_
has_persistent_value
()
def
_
exists
(
self
):
if
self
.
container_
exists
:
return
all
(
v
.
exists
for
v
in
self
.
values
())
def
_
has_persistent_value
(
self
):
if
self
.
container_
has_persistent_value
:
return
all
(
v
.
has_persistent_value
for
v
in
self
.
values
())
else
:
return
False
@
property
def
container_available
(
self
):
try
:
return
super
().
_available
()
except
PersistencyError
:
# Lazy loading failed
return
False
def
container_has_runtime_value
(
self
):
return
super
().
_has_runtime_value
()
def
_
availabl
e
(
self
):
if
self
.
container_
availabl
e
:
return
all
(
v
.
availabl
e
for
v
in
self
.
values
())
def
_
has_runtime_valu
e
(
self
):
if
self
.
container_
has_runtime_valu
e
:
return
all
(
v
.
has_runtime_valu
e
for
v
in
self
.
values
())
else
:
return
False
...
...
@@ -323,7 +316,7 @@ class VariableContainer(Mapping, Variable):
@
property
def
variable_uhashes
(
self
):
return
self
.
serialize
(
self
.
value
)
return
self
.
_
serialize
(
self
.
value
)
@
property
def
variable_values
(
self
):
...
...
esrftaskgraph/tests/test_variable.py
View file @
7fc82c0d
...
...
@@ -7,16 +7,18 @@ VALUES = [None, True, 10, "string", 10.1, [1, 2, 3], {"1": 1, "2": {"2": [10, 20
def
test_variable_missing_data
(
varinfo
):
v
=
Variable
(
varinfo
=
varinfo
)
assert
not
v
.
availabl
e
assert
not
v
.
exists
assert
not
v
.
has_runtime_valu
e
assert
not
v
.
has_persistent_value
assert
not
v
.
value
assert
not
v
.
uri
v
.
dump
()
v
.
load
()
assert
not
v
.
availabl
e
assert
not
v
.
exists
assert
not
v
.
has_runtime_valu
e
assert
not
v
.
has_persistent_value
assert
not
v
.
value
assert
not
v
.
uri
assert
v
.
value
is
v
.
MISSING_DATA
assert
v
.
value
==
v
.
MISSING_DATA
def
test_variable_none_uhash
():
...
...
@@ -96,8 +98,8 @@ def test_variable_chain(varinfo):
v1
.
value
+=
1
assert
v1
==
v2
assert
v1
.
value
!=
v2
.
value
with
pytest
.
raises
(
RuntimeError
):
v2
.
validate
()
assert
not
v2
.
has_persistent_value
assert
v2
.
has_runtime_value
def
test_variable_persistency
(
varinfo
):
...
...
@@ -107,28 +109,30 @@ def test_variable_persistency(varinfo):
v3
=
Variable
(
uhash
=
v1
.
uhash
,
varinfo
=
varinfo
)
v4
=
Variable
(
uhash
=
v2
,
varinfo
=
varinfo
)
assert
not
v1
.
exists
assert
not
v2
.
exists
assert
not
v3
.
exists
assert
not
v4
.
exists
assert
v1
.
available
assert
v2
.
available
assert
not
v3
.
available
assert
not
v4
.
available
for
v
in
(
v1
,
v2
):
assert
not
v
.
has_persistent_value
assert
v
.
has_runtime_value
for
v
in
(
v3
,
v4
):
assert
not
v
.
has_persistent_value
assert
not
v
.
has_runtime_value
v1
.
dump
()
assert
v1
.
exists
assert
v2
.
exists
assert
v3
.
exists
assert
v4
.
exists
assert
v1
.
available
assert
v2
.
available
assert
v3
.
available
assert
v4
.
available
v1
.
validate
()
v2
.
validate
()
v3
.
validate
()
v4
.
validate
()
for
v
in
(
v1
,
v2
):
assert
v
.
has_persistent_value
assert
v
.
has_runtime_value
for
v
in
(
v3
,
v4
):
assert
v
.
has_persistent_value
assert
not
v
.
has_runtime_value
v3
.
load
()
v4
.
load
()
for
v
in
(
v3
,
v4
):
assert
v
.
has_persistent_value
assert
v
.
has_runtime_value
def
test_variable_container_uhash
(
varinfo
):
...
...
@@ -178,13 +182,19 @@ def test_variable_container_persistency(tmpdir, varinfo):
assert
v
.
uhash
!=
v1
.
uhash
for
k
in
v1
:
assert
v1
[
k
]
is
v2
[
k
]
assert
v1
.
available
assert
v2
.
available
assert
not
v3
.
available
assert
not
v1
.
exists
assert
not
v2
.
exists
assert
not
v3
.
exists
assert
not
v4
.
exists
for
v
in
(
v1
,
v2
):
assert
v
.
container_has_runtime_value
assert
v
.
has_runtime_value
assert
not
v
.
container_has_persistent_value
assert
not
v
.
has_persistent_value
for
v
in
(
v3
,
v4
):
assert
not
v
.
container_has_runtime_value
assert
not
v
.
has_runtime_value
assert
not
v
.
container_has_persistent_value
assert
not
v
.
has_persistent_value
assert
len
(
v1
)
==
len
(
values
)
assert
len
(
v2
)
==
len
(
values
)
assert
len
(
v3
)
==
0
...
...
@@ -196,14 +206,20 @@ def test_variable_container_persistency(tmpdir, varinfo):
v1
.
dump
()
assert
len
(
tmpdir
.
listdir
())
==
len
(
values
)
+
1
assert
v1
.
available
assert
v2
.
available
assert
v3
.
available
assert
v4
.
available
assert
v1
.
exists
assert
v2
.
exists
assert
v3
.
exists
assert
v4
.
exists
for
v
in
(
v1
,
v2
):
assert
v
.
container_has_runtime_value
assert
v
.
has_runtime_value
assert
v
.
container_has_persistent_value
assert
v
.
has_persistent_value
for
v
in
(
v3
,
v4
):
assert
not
v
.
container_has_runtime_value
assert
not
v
.
has_runtime_value
assert
v
.
container_has_persistent_value
assert
v
.
has_persistent_value
# calls load
assert
v
.
container_has_runtime_value
assert
len
(
v1
)
==
len
(
values
)
assert
len
(
v2
)
==
len
(
values
)
assert
len
(
v3
)
==
len
(
values
)
...
...
examples/taskgraph_representation.ipynb
View file @
7fc82c0d
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment