Skip to content
This repository was archived by the owner on Oct 9, 2023. It is now read-only.

Made datetime attribute insert and match time-zone invariant #301

Merged
merged 19 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
937d72a
Added implementations to the set-timezone step, fixed attribute and v…
shiladitya-mukherjee Jun 21, 2023
59c877e
Fixed datetime insert and match time-zone bug, Implementated set-time…
shiladitya-mukherjee Jun 21, 2023
bad0eb3
Fixed spacing
shiladitya-mukherjee Jun 21, 2023
2446f45
Fixed spacing
shiladitya-mukherjee Jun 21, 2023
e2029b3
changed dependency temporarily: to be pointed to main repo later
shiladitya-mukherjee Jun 21, 2023
010f80b
Fixed indents
shiladitya-mukherjee Jun 21, 2023
652e1b4
added sudo get apt in match-core
shiladitya-mukherjee Jun 21, 2023
e67ae30
Added exception handling for timezone aware object being passed into …
shiladitya-mukherjee Jun 21, 2023
354f443
Added exception handling for timezone aware object being passed into …
shiladitya-mukherjee Jun 21, 2023
b814dc9
Fixed capialization
shiladitya-mukherjee Jun 21, 2023
b502e73
fixed review issues
shiladitya-mukherjee Jun 23, 2023
9e22dac
Made datetime parsing consistent to TypeQL format
shiladitya-mukherjee Jun 23, 2023
c838a5e
fixed parsing of dates|
shiladitya-mukherjee Jun 23, 2023
b0880d6
shifted set time-zone information to util-steps for greater generality
shiladitya-mukherjee Jun 26, 2023
2be873a
Fixed PR issues
shiladitya-mukherjee Jun 26, 2023
0735e4c
fixed PR issues
shiladitya-mukherjee Jun 30, 2023
bbf2caf
fixed PR issues
shiladitya-mukherjee Jun 30, 2023
a39b8c4
Factory test
shiladitya-mukherjee Jun 30, 2023
1d5cadf
added Vaticle dependency
shiladitya-mukherjee Jun 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .factory/automation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ build:
type: foreground
command: |
export PATH="$HOME/.local/bin:$PATH"
sudo apt-get update
sudo apt install python3-pip -y
python3 -m pip install -U pip
python3 -m pip install -r requirements_dev.txt
Expand Down
3 changes: 2 additions & 1 deletion dependencies/vaticle/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ def vaticle_typedb_behaviour():
git_repository(
name = "vaticle_typedb_behaviour",
remote = "https://github.com/vaticle/typedb-behaviour",
commit = "767bf98fef7383addf42a1ae6e97a44874bb4f0b" # sync-marker: do not remove this comment, this is used for sync-dependencies by @vaticle_typedb_behaviour
commit = "90b4addcd71a398e9e52e322021c49310e66a47a" # sync-marker: do not remove this comment, this is used for sync-dependencies by @vaticle_typedb_behaviour
)

2 changes: 1 addition & 1 deletion tests/behaviour/concept/serialization/json/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ typedb_behaviour_py_test(
"//tests/behaviour/connection:steps",
"//tests/behaviour/connection/database:steps",
"//tests/behaviour/connection/session:steps",
"//tests/behaviour/connection/transaction:steps",
"//tests/behaviour/connection/transaction:steps"
],
deps = [
"//:client_python",
Expand Down
1 change: 1 addition & 0 deletions tests/behaviour/concept/thing/attribute/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ typedb_behaviour_py_test(
"//tests/behaviour/connection/database:steps",
"//tests/behaviour/connection/session:steps",
"//tests/behaviour/connection/transaction:steps",
"//tests/behaviour/util:util_steps"
],
deps = [
"//:client_python",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,4 @@ def step_impl(context: Context, var: str, value: str):
@step("attribute {var:Var} has datetime value: {value:DateTime}")
def step_impl(context: Context, var: str, value: datetime):
assert_that(context.get(var).as_attribute().get_value(), is_(value))

11 changes: 9 additions & 2 deletions tests/behaviour/config/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,18 @@ def parseWords(text):


@parse.with_pattern(r"\d\d\d\d-\d\d-\d\d(?: \d\d:\d\d:\d\d)?")
def parse_datetime_pattern(text: str) -> datetime:
return parse_datetime(str)


def parse_datetime(text: str) -> datetime:
try:
return datetime.strptime(text, "%Y-%m-%d %H:%M:%S")
return datetime.strptime(text, "%Y-%m-%dT%H:%M:%S")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this won't ever run right? Because the regex above doesn't accept a T ever. Let's discuss why you made this change tomorrow

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function was called also from inside the Python client, on top of it being called by Cucumber.

except ValueError:
return datetime.strptime(text, "%Y-%m-%d")
try:
return datetime.strptime(text, "%Y-%m-%d %H:%M:%S")
except ValueError:
return datetime.strptime(text, "%Y-%m-%d")


register_type(DateTime=parse_datetime)
Expand Down
1 change: 1 addition & 0 deletions tests/behaviour/typeql/language/insert/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ typedb_behaviour_py_test(
"//tests/behaviour/connection/session:steps",
"//tests/behaviour/connection/transaction:steps",
"//tests/behaviour/typeql:steps",
"//tests/behaviour/util:util_steps"
],
deps = [
"//:client_python",
Expand Down
4 changes: 2 additions & 2 deletions tests/behaviour/typeql/typeql_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ class AttributeMatcher(ConceptMatcher, ABC):

def __init__(self, type_and_value: str):
self.type_and_value = type_and_value
s = type_and_value.split(":")
s = type_and_value.split(":", 1)
assert_that(s, has_length(2),
"[%s] is not a valid attribute identifier. It should have format \"type_label:value\"." % type_and_value)
self.type_label, self.value_string = s
Expand Down Expand Up @@ -284,7 +284,7 @@ class ValueMatcher(ConceptMatcher):

def __init__(self, value_type_and_value: str):
self.value_type_and_value = value_type_and_value
s = value_type_and_value.split(":")
s = value_type_and_value.split(":", 1)
assert_that(s, has_length(2),
"[%s] is not a valid identifier. It should have format \"value_type:value\"." % value_type_and_value)
self.value_type_name, self.value_string = s
Expand Down
7 changes: 7 additions & 0 deletions tests/behaviour/util/util_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@

from tests.behaviour.context import Context

import os
import time

@step("set time-zone is: {time_zone_label}")
def step_impl(context: Context, time_zone_label: str):
os.environ["TZ"] = time_zone_label
time.tzset()

@step("wait {seconds} seconds")
def step_impl(context: Context, seconds: str):
Expand Down
2 changes: 1 addition & 1 deletion tool/behave_rule.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def _rule_implementation(ctx):
cmd += " && rm -rf " + steps_out_dir
cmd += " && mkdir " + steps_out_dir + " && "
cmd += " && ".join(["cp %s %s" % (step_file.path, steps_out_dir) for step_file in ctx.files.steps])
cmd += " && behave %s --no-capture -D port=$PORT && export RESULT=0 || export RESULT=1" % feats_dir
cmd += " && python3 -m behave %s --no-capture -D port=$PORT && export RESULT=0 || export RESULT=1" % feats_dir
cmd += """
echo Tests concluded with exit value $RESULT
echo Stopping server.
Expand Down
2 changes: 1 addition & 1 deletion typedb/common/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def __init__(self, code: int, message: str):
NONEXISTENT_EXPLAINABLE_CONCEPT = ConceptErrorMessage(10, "The concept identified by '%s' is not explainable.")
NONEXISTENT_EXPLAINABLE_OWNERSHIP = ConceptErrorMessage(11, "The ownership by owner '%s' of attribute '%s' is not explainable.")
GET_HAS_WITH_MULTIPLE_FILTERS = ConceptErrorMessage(12, "Only one filter can be applied at a time to get_has. The possible filters are: [attribute_type, attribute_types, annotations]")

UNSUPPORTED_TIMEZONE_INFORMATION = ConceptErrorMessage(13, "A date-time attribute cannot accept timezone aware datetime objects.")

class QueryErrorMessage(ErrorMessage):

Expand Down
4 changes: 3 additions & 1 deletion typedb/concept/proto/concept_proto_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from typedb.api.concept.type.role_type import RoleType
from typedb.api.concept.type.thing_type import ThingType, Annotations, Annotation
from typedb.api.concept.type.type import Type
from typedb.common.exception import TypeDBClientException, BAD_ENCODING, BAD_ANNOTATION
from typedb.common.exception import TypeDBClientException, BAD_ENCODING, BAD_ANNOTATION, UNSUPPORTED_TIMEZONE_INFORMATION
from typedb.common.rpc.request_builder import proto_role_type, proto_thing_type, byte_string


Expand Down Expand Up @@ -83,6 +83,8 @@ def string_value(value: str):


def datetime_value(value: datetime):
if value.tzinfo is not None:
raise TypeDBClientException.of(UNSUPPORTED_TIMEZONE_INFORMATION)
value_proto = concept_proto.ConceptValue()
value_proto.date_time = int((value - datetime(1970, 1, 1)).total_seconds() * 1000)
return value_proto
Expand Down
2 changes: 1 addition & 1 deletion typedb/concept/thing/attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def __init__(self, iid: str, is_inferred: bool, type_: DateTimeAttributeType, va

@staticmethod
def of(thing_proto: concept_proto.Thing):
return _DateTimeAttribute(concept_proto_reader.iid(thing_proto.iid), thing_proto.inferred, concept_proto_reader.attribute_type(thing_proto.type), datetime.fromtimestamp(float(thing_proto.value.date_time) / 1000.0))
return _DateTimeAttribute(concept_proto_reader.iid(thing_proto.iid), thing_proto.inferred, concept_proto_reader.attribute_type(thing_proto.type), datetime.utcfromtimestamp(float(thing_proto.value.date_time) / 1000.0))

def get_type(self) -> "DateTimeAttributeType":
return self._type
Expand Down
2 changes: 1 addition & 1 deletion typedb/concept/value/value.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def __init__(self, value: datetime):

@staticmethod
def of(value_proto: concept_proto.Value):
return _DateTimeValue(datetime.fromtimestamp(float(value_proto.value.date_time) / 1000.0))
return _DateTimeValue(datetime.utcfromtimestamp(float(value_proto.value.date_time) / 1000.0))

def get_value(self):
return self._value
Expand Down