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

Commit cbc4588

Browse files
author
Alex Walker
authored
Add more BDD infrastructure and support more features (#150)
## What is the goal of this PR? Our previous BDD infrastructure only supported a very limited set of features. We expanded it to include more features, such as the Concept API. ## What are the changes implemented in this PR? - Finish implementing Connection steps - Implement Concept API steps - Add Concept API tests - Fix bugs exposed by Concept tests
1 parent be0b861 commit cbc4588

File tree

38 files changed

+2456
-104
lines changed

38 files changed

+2456
-104
lines changed

dependencies/graknlabs/repositories.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,5 @@ def graknlabs_behaviour():
3737
git_repository(
3838
name = "graknlabs_behaviour",
3939
remote = "https://github.com/graknlabs/behaviour",
40-
commit = "7088622b9f4a3bd99cf4fb278130ad76ff35af6b" # sync-marker: do not remove this comment, this is used for sync-dependencies by @graknlabs_behaviour
40+
commit = "2279d3a284d53fdd989885c06f3c50f00f930a63" # sync-marker: do not remove this comment, this is used for sync-dependencies by @graknlabs_behaviour
4141
)

grakn/concept/concept_manager.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def put_entity_type(self, label: str):
5252

5353
def get_entity_type(self, label: str):
5454
_type = self._get_thing_type(label)
55-
return _type if _type.is_entity_type() else None
55+
return _type if _type and _type.is_entity_type() else None
5656

5757
def put_relation_type(self, label: str):
5858
req = concept_proto.ConceptManager.Req()
@@ -64,7 +64,7 @@ def put_relation_type(self, label: str):
6464

6565
def get_relation_type(self, label: str):
6666
_type = self._get_thing_type(label)
67-
return _type if _type.is_relation_type() else None
67+
return _type if _type and _type.is_relation_type() else None
6868

6969
def put_attribute_type(self, label: str, value_type):
7070
req = concept_proto.ConceptManager.Req()
@@ -77,7 +77,7 @@ def put_attribute_type(self, label: str, value_type):
7777

7878
def get_attribute_type(self, label: str):
7979
_type = self._get_thing_type(label)
80-
return _type if _type.is_attribute_type() else None
80+
return _type if _type and _type.is_attribute_type() else None
8181

8282
def get_thing(self, iid: str):
8383
req = concept_proto.ConceptManager.Req()

grakn/concept/thing/thing.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def get_plays(self):
9999
req.thing_get_plays_req.CopyFrom(concept_proto.Thing.GetPlays.Req())
100100
return self._type_stream(req, lambda res: res.thing_get_plays_res.role_types)
101101

102-
def get_relations(self, role_types=None):
102+
def get_relations(self, role_types: list = None):
103103
if not role_types:
104104
role_types = []
105105
method = concept_proto.Thing.Req()
@@ -124,7 +124,7 @@ def unset_has(self, attribute):
124124

125125
def delete(self):
126126
method = concept_proto.Thing.Req()
127-
method.thing_delete_req.CopyFrom(method.concept_proto.Thing.Delete.Req())
127+
method.thing_delete_req.CopyFrom(concept_proto.Thing.Delete.Req())
128128
self._execute(method)
129129

130130
def is_deleted(self):

grakn/concept/type/attribute_type.py

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
#
1919

2020
from datetime import datetime
21+
from typing import Optional
2122

2223
import graknprotocol.protobuf.concept_pb2 as concept_proto
2324

25+
from grakn.common.exception import GraknClientException
2426
from grakn.concept.proto import concept_proto_builder, concept_proto_reader
2527
from grakn.concept.type.thing_type import ThingType, RemoteThingType
2628
from grakn.concept.type.value_type import ValueType
@@ -32,6 +34,8 @@ def is_keyable(value_type: ValueType):
3234

3335
class AttributeType(ThingType):
3436

37+
ROOT_LABEL = "attribute"
38+
3539
def as_remote(self, transaction):
3640
return RemoteAttributeType(transaction, self.get_label(), self.is_root())
3741

@@ -59,11 +63,36 @@ def is_string(self):
5963
def is_datetime(self):
6064
return False
6165

66+
def as_boolean(self):
67+
if self.is_root():
68+
return BooleanAttributeType(self.ROOT_LABEL, is_root=True)
69+
raise GraknClientException("Invalid conversion to " + BooleanAttributeType.__name__)
70+
71+
def as_long(self):
72+
if self.is_root():
73+
return LongAttributeType(self.ROOT_LABEL, is_root=True)
74+
raise GraknClientException("Invalid conversion to " + LongAttributeType.__name__)
75+
76+
def as_double(self):
77+
if self.is_root():
78+
return DoubleAttributeType(self.ROOT_LABEL, is_root=True)
79+
raise GraknClientException("Invalid conversion to " + DoubleAttributeType.__name__)
80+
81+
def as_string(self):
82+
if self.is_root():
83+
return StringAttributeType(self.ROOT_LABEL, is_root=True)
84+
raise GraknClientException("Invalid conversion to " + StringAttributeType.__name__)
85+
86+
def as_datetime(self):
87+
if self.is_root():
88+
return DateTimeAttributeType(self.ROOT_LABEL, is_root=True)
89+
raise GraknClientException("Invalid conversion to " + DateTimeAttributeType.__name__)
90+
6291
def __eq__(self, other):
6392
if other is self:
6493
return True
6594
# root "attribute" should always be equal to itself regardless of which value class it holds
66-
if not other or not isinstance(AttributeType, other):
95+
if not other or not isinstance(other, AttributeType):
6796
return False
6897
return self.get_label() == other.get_label()
6998

@@ -73,6 +102,8 @@ def __hash__(self):
73102

74103
class RemoteAttributeType(RemoteThingType):
75104

105+
ROOT_LABEL = "attribute"
106+
76107
def get_value_type(self):
77108
return ValueType.OBJECT
78109

@@ -82,6 +113,13 @@ def is_keyable(self):
82113
def as_remote(self, transaction):
83114
return RemoteAttributeType(transaction, self.get_label(), self.is_root())
84115

116+
def get_subtypes(self):
117+
stream = super(RemoteAttributeType, self).get_subtypes()
118+
if self.is_root() and self.get_value_type() is not ValueType.OBJECT:
119+
return [subtype for subtype in stream if subtype.get_value_type() is self.get_value_type() or subtype.get_label() == self.get_label()]
120+
else:
121+
return stream
122+
85123
def get_owners(self, only_key=False):
86124
method = concept_proto.Type.Req()
87125
get_owners_req = concept_proto.AttributeType.GetOwners.Req()
@@ -122,6 +160,31 @@ def is_string(self):
122160
def is_datetime(self):
123161
return False
124162

163+
def as_boolean(self):
164+
if self.is_root():
165+
return BooleanAttributeType(self.ROOT_LABEL, is_root=True)
166+
raise GraknClientException("Invalid conversion to " + BooleanAttributeType.__name__)
167+
168+
def as_long(self):
169+
if self.is_root():
170+
return LongAttributeType(self.ROOT_LABEL, is_root=True)
171+
raise GraknClientException("Invalid conversion to " + LongAttributeType.__name__)
172+
173+
def as_double(self):
174+
if self.is_root():
175+
return DoubleAttributeType(self.ROOT_LABEL, is_root=True)
176+
raise GraknClientException("Invalid conversion to " + DoubleAttributeType.__name__)
177+
178+
def as_string(self):
179+
if self.is_root():
180+
return StringAttributeType(self.ROOT_LABEL, is_root=True)
181+
raise GraknClientException("Invalid conversion to " + StringAttributeType.__name__)
182+
183+
def as_datetime(self):
184+
if self.is_root():
185+
return DateTimeAttributeType(self.ROOT_LABEL, is_root=True)
186+
raise GraknClientException("Invalid conversion to " + DateTimeAttributeType.__name__)
187+
125188
def __eq__(self, other):
126189
if other is self:
127190
return True
@@ -148,6 +211,9 @@ def as_remote(self, transaction):
148211
def is_boolean(self):
149212
return True
150213

214+
def as_boolean(self):
215+
return self
216+
151217

152218
class RemoteBooleanAttributeType(RemoteAttributeType):
153219

@@ -166,6 +232,9 @@ def get(self, value: bool):
166232
def is_boolean(self):
167233
return True
168234

235+
def as_boolean(self):
236+
return self
237+
169238

170239
class LongAttributeType(AttributeType):
171240

@@ -182,6 +251,9 @@ def as_remote(self, transaction):
182251
def is_long(self):
183252
return True
184253

254+
def as_long(self):
255+
return self
256+
185257

186258
class RemoteLongAttributeType(RemoteAttributeType):
187259

@@ -200,6 +272,9 @@ def get(self, value: int):
200272
def is_long(self):
201273
return True
202274

275+
def as_long(self):
276+
return self
277+
203278

204279
class DoubleAttributeType(AttributeType):
205280

@@ -216,6 +291,9 @@ def as_remote(self, transaction):
216291
def is_double(self):
217292
return True
218293

294+
def as_double(self):
295+
return self
296+
219297

220298
class RemoteDoubleAttributeType(RemoteAttributeType):
221299

@@ -234,6 +312,9 @@ def get(self, value: float):
234312
def is_double(self):
235313
return True
236314

315+
def as_double(self):
316+
return self
317+
237318

238319
class StringAttributeType(AttributeType):
239320

@@ -250,6 +331,9 @@ def as_remote(self, transaction):
250331
def is_string(self):
251332
return True
252333

334+
def as_string(self):
335+
return self
336+
253337

254338
class RemoteStringAttributeType(RemoteAttributeType):
255339

@@ -272,7 +356,9 @@ def get_regex(self):
272356
regex = self._execute(method).attribute_type_get_regex_res.regex
273357
return None if len(regex) == 0 else regex
274358

275-
def set_regex(self, regex: str):
359+
def set_regex(self, regex: Optional[str]):
360+
if regex is None:
361+
regex = ""
276362
method = concept_proto.Type.Req()
277363
set_regex_req = concept_proto.AttributeType.SetRegex.Req()
278364
set_regex_req.regex = regex
@@ -282,6 +368,9 @@ def set_regex(self, regex: str):
282368
def is_string(self):
283369
return True
284370

371+
def as_string(self):
372+
return self
373+
285374

286375
class DateTimeAttributeType(AttributeType):
287376

@@ -298,6 +387,9 @@ def as_remote(self, transaction):
298387
def is_datetime(self):
299388
return True
300389

390+
def as_datetime(self):
391+
return self
392+
301393

302394
class RemoteDateTimeAttributeType(RemoteAttributeType):
303395

@@ -315,3 +407,6 @@ def get(self, value: datetime):
315407

316408
def is_datetime(self):
317409
return True
410+
411+
def as_datetime(self):
412+
return self

grakn/rpc/database_manager.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919

2020
from graknprotocol.protobuf.grakn_pb2_grpc import GraknStub
2121
import graknprotocol.protobuf.database_pb2 as database_proto
22-
from grpc import Channel
22+
from grpc import Channel, RpcError
23+
24+
from grakn.common.exception import GraknClientException
2325

2426

2527
class DatabaseManager(object):
@@ -30,17 +32,29 @@ def __init__(self, channel: Channel):
3032
def contains(self, name: str):
3133
request = database_proto.Database.Contains.Req()
3234
request.name = name
33-
return self._grpc_stub.database_contains(request).contains
35+
try:
36+
return self._grpc_stub.database_contains(request).contains
37+
except RpcError as e:
38+
raise GraknClientException(e)
3439

3540
def create(self, name: str):
3641
request = database_proto.Database.Create.Req()
3742
request.name = name
38-
self._grpc_stub.database_create(request)
43+
try:
44+
self._grpc_stub.database_create(request)
45+
except RpcError as e:
46+
raise GraknClientException(e)
3947

4048
def delete(self, name: str):
4149
request = database_proto.Database.Delete.Req()
4250
request.name = name
43-
self._grpc_stub.database_delete(request)
51+
try:
52+
self._grpc_stub.database_delete(request)
53+
except RpcError as e:
54+
raise GraknClientException(e)
4455

4556
def all(self):
46-
return list(self._grpc_stub.database_all(database_proto.Database.All.Req()).names)
57+
try:
58+
return list(self._grpc_stub.database_all(database_proto.Database.All.Req()).names)
59+
except RpcError as e:
60+
raise GraknClientException(e)

grakn/rpc/session.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424
import graknprotocol.protobuf.session_pb2 as session_proto
2525
import enum
2626

27+
from grpc import RpcError
28+
2729
from grakn import grakn_proto_builder
30+
from grakn.common.exception import GraknClientException
2831
from grakn.options import GraknOptions
2932
from grakn.rpc.transaction import Transaction, TransactionType
3033

@@ -71,7 +74,10 @@ def close(self):
7174
self._scheduler.empty()
7275
req = session_proto.Session.Close.Req()
7376
req.session_id = self._session_id
74-
self._grpc_stub.session_close(req)
77+
try:
78+
self._grpc_stub.session_close(req)
79+
except RpcError as e:
80+
raise GraknClientException(e)
7581

7682
def database(self): return self._database
7783

requirements.txt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,3 @@ graknprotocol==2.0.0a5
2828
grpcio==1.33.2
2929
protobuf==3.6.1
3030
six>=1.11.0
31-
32-
33-
# Dev dependencies (not required to use the grakn-client package, but necessary for its development)
34-
35-
behave==1.2.6
36-
PyHamcrest==2.0.2

requirements_dev.txt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one
3+
# or more contributor license agreements. See the NOTICE file
4+
# distributed with this work for additional information
5+
# regarding copyright ownership. The ASF licenses this file
6+
# to you under the Apache License, Version 2.0 (the
7+
# "License"); you may not use this file except in compliance
8+
# with the License. You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing,
13+
# software distributed under the License is distributed on an
14+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
# KIND, either express or implied. See the License for the
16+
# specific language governing permissions and limitations
17+
# under the License.
18+
#
19+
20+
## Configuration options
21+
22+
# --extra-index-url https://repo.grakn.ai/repository/pypi-snapshot/simple # Allow importing of snapshots
23+
24+
25+
## Dependencies
26+
27+
graknprotocol==2.0.0a5
28+
grpcio==1.33.2
29+
protobuf==3.6.1
30+
six>=1.11.0
31+
32+
33+
# Dev dependencies (not required to use the grakn-client package, but necessary for its development)
34+
35+
behave==1.2.6
36+
PyHamcrest==2.0.2

0 commit comments

Comments
 (0)