Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rating implementation #55

Merged
merged 2 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
2 changes: 1 addition & 1 deletion tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ def test_entities_fix_keys_and_values_can_be_retrieved(self):
e = create_event(dt.datetime.now(), dt.datetime.now() + dt.timedelta(days=1), "Patrick", other_attr="asd",
other_attr2=123)
keys = list(sorted(e.fixed_attributes().keys()))
self.assertListEqual(sorted(['author', 'products', 'start', 'stop', 'tags', 'uuid']), keys)
self.assertListEqual(sorted(['author', 'products', 'start', 'stop', 'tags', 'uuid', 'rating']), keys)

keys = list(sorted(e.variable_attributes().keys()))
self.assertListEqual(sorted(['other_attr', 'other_attr2']), keys)
Expand Down
29 changes: 28 additions & 1 deletion tests/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def test_constructor_various_combinations_all_ok(self, start, stop, author, uuid
tags = re.escape(str(tags))
products = re.escape(str(products))
r = r'^Event\(start=.*, stop=.*, author=' + author + r', uuid=[0-9a-f-]{36}, tags=' + tags \
+ r', products=' + products + r'\) attributes\(' + attr_repr + r'\)$'
+ r', products=' + products + r', rating=None\) attributes\(' + attr_repr + r'\)$'

self.assertRegex(f'{e}', r)

Expand Down Expand Up @@ -102,3 +102,30 @@ def test_constructor_with_dynamic_attribute_manual_access(self):
self.assertEqual(e.field_str, "string-test")
self.assertEqual(e.field_bool, True)
self.assertEqual(e.field_dt, dt_val)

def test_event_rating(self):
Copy link
Member

Choose a reason for hiding this comment

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

Should be split in two data driven tests.

t1, t2 = dt.datetime.now(), dt.datetime.now() + dt.timedelta(days=1)

e = create_event(t1, t2, "Patrick")
self.assertEqual(e.rating, None)

e.rating = 1
self.assertEqual(e.rating, 1)

e.rating = 5
self.assertEqual(e.rating, 5)

e.rating = None
self.assertEqual(e.rating, None)

with self.assertRaises(ValueError):
e.rating = -1

with self.assertRaises(ValueError):
e.rating = 0

with self.assertRaises(ValueError):
e.rating = 1.5

with self.assertRaises(ValueError):
e.rating = 11
19 changes: 14 additions & 5 deletions tscat/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def backend() -> orm_sqlalchemy.Backend:


def _listify(v) -> Union[List, Tuple]:
if type(v) in [list, tuple]:
if isinstance(v, (list, tuple)):
return v
else:
return [v]
Expand Down Expand Up @@ -144,13 +144,14 @@ def is_removed(self) -> bool:
return self._removed

class _Event(_BackendBasedEntity):
_fixed_keys = ['start', 'stop', 'author', 'uuid', 'tags', 'products']
_fixed_keys = ['start', 'stop', 'author', 'uuid', 'tags', 'products', 'rating']

def __init__(self, start: dt.datetime, stop: dt.datetime,
author: str,
uuid: Optional[str] = None,
tags: Iterable[str] = [],
products: Iterable[str] = [],
rating: Optional[int] = None,
_insert: bool = True,
**kwargs):
self._in_ctor = True
Expand All @@ -161,6 +162,7 @@ def __init__(self, start: dt.datetime, stop: dt.datetime,
self.author = author
self.tags = list(tags)
self.products = list(products)
self.rating = rating

if not uuid:
self.uuid = str(uuid4())
Expand All @@ -178,6 +180,7 @@ def __init__(self, start: dt.datetime, stop: dt.datetime,
'uuid': self.uuid,
'tags': self.tags,
'products': self.products,
'rating': self.rating,
'attributes': kwargs,
})

Expand All @@ -193,10 +196,16 @@ def __setattr__(self, key, value):
if value < self.start:
raise ValueError("stop date has to be after start date")
elif key in ['tags', 'products']:
if any(type(v) != str for v in value):
if any(not isinstance(v, str) for v in value):
jeandet marked this conversation as resolved.
Show resolved Hide resolved
raise ValueError("a tag has to be a string")
if any(',' in v for v in value):
raise ValueError("a string-list value shall not contain a comma")
elif key == 'rating':
if value is not None:
if not isinstance(value, int):
raise ValueError("rating has to be an integer value")
if value < 1 or value > 10:
raise ValueError("rating has to be between 1 and 10")

super(_Event, self).__setattr__(key, value)

Expand Down Expand Up @@ -253,7 +262,7 @@ def __setattr__(self, key, value):
if not value:
raise ValueError('Catalogue name cannot be emtpy.')
elif key == 'tags':
if any(type(v) != str for v in value):
if any(not isinstance(v, str) for v in value):
raise ValueError("a tag has to be a string")
if any(',' in v for v in value):
raise ValueError("a string-list value shall not contain a comma")
Expand Down Expand Up @@ -325,7 +334,7 @@ def get_events(base: Union[Predicate, _Catalogue, None] = None,

events = []
for ev in backend().get_events(base_dict):
e = _Event(ev['start'], ev['stop'], ev['author'], ev['uuid'], ev['tags'], ev['products'],
e = _Event(ev['start'], ev['stop'], ev['author'], ev['uuid'], ev['tags'], ev['products'], ev['rating'],
**ev['attributes'], _insert=False)
e._removed = removed_items
e._backend_entity = ev['entity']
Expand Down
4 changes: 4 additions & 0 deletions tscat/import_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ def __init__(self, attrs: Dict[str, str], tscat_name: Optional[str] = None) -> N
__VOTableTSCatFieldSpecialDateTime({'name': "Start Time", 'ID': "TimeIntervalStart", 'ucd': "time.start"}, 'start'),
__VOTableTSCatFieldSpecialDateTime({'name': "Stop Time", 'ID': "TimeIntervalStop", 'ucd': "time.end"}, 'stop'),
__VOTableTSCatFieldSpecialDateTime({}),
__VOTableTSCatField(int, {'datatype': 'long'},
lambda x: 0 if x is None else x,
lambda x: None if x == 0 else x, 'rating'),
__VOTableTSCatField(int, {'datatype': 'long'}, int, int),
__VOTableTSCatField(float, {'datatype': 'double'}, float, float),
__VOTableTSCatField(bool, {'datatype': 'boolean'}, bool, bool),
Expand Down Expand Up @@ -246,6 +249,7 @@ def export_votable(catalogues: Union[List[_Catalogue], _Catalogue]) -> VOTableFi
('uuid', __vo_table_field_from(str)),
('tags', __vo_table_field_from(list)),
('products', __vo_table_field_from(list)),
('rating', __vo_table_field_from('rating')),
]

events = get_events(catalogue)
Expand Down
3 changes: 3 additions & 0 deletions tscat/orm_sqlalchemy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ def add_event(self, event: Dict) -> orm.Event:
event['uuid'],
event['tags'],
event['products'],
event['rating'],
event['attributes'])

def add_events_to_catalogue(self, catalogue: orm.Catalogue, events: List[orm.Event]) -> None:
Expand Down Expand Up @@ -248,6 +249,7 @@ def get_events(self, base: Dict = {}) -> List[Dict]:
"uuid": e.uuid,
"tags": e.tags,
"products": e.products,
"rating": e.rating,
"attributes": e.attributes,
"entity": e}
events.append(event)
Expand All @@ -264,6 +266,7 @@ def get_events_by_uuid_list(self, uuids: List[str]) -> Dict[str, Dict]:
"uuid": e.uuid,
"tags": e.tags,
"products": e.products,
"rating": e.rating,
"attributes": e.attributes,
"entity": e}

Expand Down
4 changes: 3 additions & 1 deletion tscat/orm_sqlalchemy/orm.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,20 @@ class Event(Base):

tags: List[str] = Column(ScalarListType(str), default=[], info={"type": (list, "string_list")})
products: List[str] = Column(ScalarListType(str), default=[], info={"type": (list, "string_list")})
rating: int = Column(Integer, default=None, nullable=True)

removed: bool = Column(Boolean, default=False, nullable=False)

attributes: Dict[str, Any] = Column(MutableDict.as_mutable(JSON))

def __init__(self, start, stop, author, uuid, tags, products, attributes):
def __init__(self, start, stop, author, uuid, tags, products, rating, attributes):
self.start = start
self.stop = stop
self.author = author
self.uuid = uuid
self.tags = tags
self.products = products
self.rating = rating
self.attributes = attributes

def __repr__(self): # pragma: no cover
jeandet marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Loading