Skip to content

Commit

Permalink
fix(core): fix Plan.invalidated_at datetime not being timezone aware (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Panaetius committed Apr 11, 2022
1 parent c61384b commit df82f9f
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 11 deletions.
13 changes: 13 additions & 0 deletions renku/command/schema/plan.py
Expand Up @@ -17,6 +17,8 @@
# limitations under the License.
"""Represent run templates."""

from datetime import timezone

import marshmallow

from renku.command.schema.calamus import JsonLDSchema, Nested, fields, prov, renku, schema
Expand Down Expand Up @@ -49,3 +51,14 @@ class Meta:
outputs = Nested(renku.hasOutputs, CommandOutputSchema, many=True, missing=None)
parameters = Nested(renku.hasArguments, CommandParameterSchema, many=True, missing=None)
success_codes = fields.List(renku.successCodes, fields.Integer(), missing=[0])

@marshmallow.pre_dump
def _pre_dump(self, in_data, **kwargs):
"""Fix data on dumping."""
if in_data.invalidated_at is not None and in_data.invalidated_at.tzinfo is None:
# NOTE: There was a bug that caused invalidated_at to be set without timezone (as UTC time)
# so we patch in the timezone here
in_data.unfreeze()
in_data.invalidated_at = in_data.invalidated_at.replace(microsecond=0).astimezone(timezone.utc)
in_data.freeze()
return in_data
3 changes: 1 addition & 2 deletions renku/command/workflow.py
Expand Up @@ -21,7 +21,6 @@
import itertools
import re
from collections import defaultdict
from datetime import datetime
from functools import reduce
from pathlib import Path
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union, cast
Expand Down Expand Up @@ -133,7 +132,7 @@ def _remove_workflow(name: str, force: bool, plan_gateway: IPlanGateway):

plan = plan or workflows[name]
plan.unfreeze()
plan.invalidated_at = datetime.utcnow()
plan.invalidated_at = local_now()
plan.freeze()


Expand Down
27 changes: 18 additions & 9 deletions renku/data/shacl_shape.json
Expand Up @@ -102,7 +102,8 @@
"@id": "xsd:string"
},
"minCount": 1,
"maxCount": 1
"maxCount": 1,
"sh:pattern": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2}"
},
{
"nodeKind": "sh:Literal",
Expand Down Expand Up @@ -385,7 +386,8 @@
"datatype": {
"@id": "xsd:string"
},
"maxCount": 1
"maxCount": 1,
"sh:pattern": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2}"
},
{
"nodeKind": "sh:Literal",
Expand All @@ -396,15 +398,17 @@
"maxCount": 1,
"sh:moreThanOrEquals": {
"@id": "schema:dateCreated"
}
},
"sh:pattern": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2}"
},
{
"nodeKind": "sh:Literal",
"path": "schema:datePublished",
"datatype": {
"@id": "xsd:string"
},
"maxCount": 1
"maxCount": 1,
"sh:pattern": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2}"
},
{
"nodeKind": "sh:Literal",
Expand Down Expand Up @@ -724,7 +728,8 @@
"@id": "xsd:string"
},
"minCount": 1,
"maxCount": 1
"maxCount": 1,
"sh:pattern": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2}"
},
{
"nodeKind": "sh:Literal",
Expand All @@ -735,7 +740,8 @@
"maxCount": 1,
"sh:moreThanOrEquals": {
"@id": "schema:dateCreated"
}
},
"sh:pattern": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2}"
},
{
"path": "prov:entity",
Expand Down Expand Up @@ -1044,7 +1050,8 @@
"@id": "xsd:string"
},
"minCount": 1,
"maxCount": 1
"maxCount": 1,
"sh:pattern": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2}"
},
{
"nodeKind": "sh:Literal",
Expand All @@ -1055,7 +1062,8 @@
"maxCount": 1,
"sh:moreThanOrEquals": {
"@id": "schema:dateCreated"
}
},
"sh:pattern": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2}"
}
]
},
Expand Down Expand Up @@ -1455,7 +1463,8 @@
"datatype": {
"@id": "xsd:string"
},
"maxCount": 1
"maxCount": 1,
"sh:pattern": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2}"
}
]
},
Expand Down
14 changes: 14 additions & 0 deletions tests/core/commands/test_workflow.py
Expand Up @@ -19,13 +19,16 @@


from contextlib import nullcontext
from datetime import datetime

import pytest

from renku.command.schema.plan import PlanSchema
from renku.core import errors
from renku.core.workflow.concrete_execution_graph import ExecutionGraph
from renku.core.workflow.value_resolution import CompositePlanValueResolver
from renku.domain_model.workflow.composite_plan import CompositePlan
from renku.domain_model.workflow.plan import Plan


def _get_nested_actual_values(run):
Expand Down Expand Up @@ -501,3 +504,14 @@ def test_composite_plan_auto_links(composite_plan, mappings, defaults, links, ra
with maybe_raises:
for virtual_link in graph.virtual_links:
grouped.add_link(virtual_link[0], [virtual_link[1]])


def test_plan_invalidated_at_datetime_export():
"""The invalidated_at has a timezone on export."""
plan = Plan(id=Plan.generate_id(), name="p1", command="/bin/sh")
plan.invalidated_at = datetime.utcnow()

dumped = PlanSchema().dump(plan)

date = datetime.fromisoformat(dumped["http://www.w3.org/ns/prov#invalidatedAtTime"])
assert date.tzinfo is not None

0 comments on commit df82f9f

Please sign in to comment.