def create_activity_record(self, record: ActivityRecord) -> ActivityRecord: """Method to write an activity record and its details to the git log and detaildb Args: record(ActivityRecord): A populated activity record Returns: ActivityRecord """ # If there isn't a linked commit, generate a UUID to uniquely ID the data in levelDB that will never # collide with the actual git hash space by making it 32 char vs. 40 for git if not record.linked_commit: record.linked_commit = uuid.uuid4().hex # Write all ActivityDetailObjects to the datastore with record.inspect_detail_objects() as details: for idx, detail in enumerate(details): updated_detail = self.put_detail_record(detail) record.update_detail_object(updated_detail, idx) # Add everything in the repo activity/log directory self.repository.git.add_all(self.detaildb.root_path) # Commit changes and update record commit = self.repository.git.commit(record.log_str) record.commit = commit.hexsha # Update record with username and email record.username = self.repository.git.author.name record.email = self.repository.git.author.email logger.debug(f"Successfully created ActivityRecord {commit.hexsha}") return record
def test_add_detail_object(self): """Test adding values to the detail object""" ar = ActivityRecord(ActivityType.CODE, show=True, message="added some code", importance=50, linked_commit='aaaaaaaa') adr = ActivityDetailRecord(ActivityDetailType.CODE) adr.add_value("text/plain", "this is some data") ar.add_detail_object(adr) assert len(ar._detail_objects) == 1 assert ar._detail_objects[0][0] is True assert ar._detail_objects[0][1] == ActivityDetailType.CODE.value assert ar._detail_objects[0][2] == 0 assert ar._detail_objects[0][3] == adr
def get_activity_record(self, commit: str) -> ActivityRecord: """Method to get a single ActivityRecord Args: commit(str): The commit hash of the activity record Returns: ActivityRecord """ entry = self.repository.git.log_entry(commit) m = self.note_regex.match(entry["message"]) if m: ar = ActivityRecord.from_log_str(m.group(0), commit, entry['committed_on'], username=entry['author']['name'], email=entry['author']['email']) return ar else: raise ValueError( "Activity data not found in commit {}".format(commit))
def test_from_log_str(self): """Test the creating from a log string""" test_str = """_GTM_ACTIVITY_START_** msg:added some code** metadata:{"show":true,"importance":50,"type":2,"linked_commit":"aaaaaaaa","tags":["test"]}** details:** 4,1,255,my_fake_detail_key,0** 2,0,0,my_fake_detail_key2,3** _GTM_ACTIVITY_END_""" ar = ActivityRecord.from_log_str(test_str, "bbbbbb", datetime.datetime.utcnow()) assert type(ar) == ActivityRecord assert ar.type == ActivityType.CODE assert ar.show is True assert ar.importance == 50 assert ar.linked_commit == "aaaaaaaa" assert ar.commit == "bbbbbb" assert ar.tags == ['test'] assert len(ar._detail_objects) == 2 assert type(ar._detail_objects[0][3]) == ActivityDetailRecord assert ar._detail_objects[0][3].type == ActivityDetailType.CODE assert ar._detail_objects[0][3].action == ActivityAction.NOACTION assert ar._detail_objects[0][3].key == "my_fake_detail_key" assert ar._detail_objects[0][3].show is True assert ar._detail_objects[0][3].importance == 255 assert ar._detail_objects[0][3].tags == [] assert ar._detail_objects[0][3].is_loaded is False assert type(ar._detail_objects[1][3]) == ActivityDetailRecord assert ar._detail_objects[1][3].type == ActivityDetailType.RESULT assert ar._detail_objects[1][3].action == ActivityAction.DELETE assert ar._detail_objects[1][3].key == "my_fake_detail_key2" assert ar._detail_objects[1][3].show is False assert ar._detail_objects[1][3].importance == 0 assert ar._detail_objects[1][3].tags == [] assert ar._detail_objects[1][3].is_loaded is False
def get_activity_records( self, after: Optional[str] = None, first: Optional[int] = None) -> List[Optional[ActivityRecord]]: """Method to get a list of activity records, with forward paging supported Args: after(str): Commit hash to page after first(int): Number of records to get Returns: List[ActivityRecord] """ # Get data from the git log log_data = self._get_log_records(after=after, first=first) if log_data: if after: # If the "after" record is included. Remove it due to standards on how relay paging works log_data = log_data[1:] # If first value provided, check for the right amount of data if first: if len(log_data) > first: # Need to prune due to padding sent into self._get_log_records() log_data = log_data[:first] if log_data: return [ ActivityRecord.from_log_str(x[0], x[1], x[2], username=x[3], email=x[4]) for x in log_data ] else: return []
def test_log_str_prop_errors(self): """Test the log string property""" ar = ActivityRecord(ActivityType.CODE, show=True, importance=50, linked_commit='aaaaaaaa') with pytest.raises(ValueError): # Missing message _ = ar.log_str ar = ActivityRecord(ActivityType.CODE, show=True, message="added some code", importance=50, linked_commit='aaaaaaaa') adr = ActivityDetailRecord(ActivityDetailType.CODE) adr.add_value("text/plain", "this is some data") ar.add_detail_object(adr) with pytest.raises(ValueError): # Missing detail key for detail record ar.log_str
def test_add_detail_objects_sort(self): """Test adding values to the detail object""" ar = ActivityRecord(ActivityType.CODE, show=True, message="added some code", importance=50, linked_commit='aaaaaaaa') adr = ActivityDetailRecord(ActivityDetailType.CODE) adr.show = True adr.importance = 100 adr.add_value("text/plain", "second") ar.add_detail_object(adr) adr = ActivityDetailRecord(ActivityDetailType.CODE) adr.show = True adr.importance = 200 adr.add_value("text/plain", "first") ar.add_detail_object(adr) adr = ActivityDetailRecord(ActivityDetailType.CODE) adr.show = False adr.importance = 0 adr.add_value("text/plain", "sixth") ar.add_detail_object(adr) adr = ActivityDetailRecord(ActivityDetailType.OUTPUT_DATA) adr.show = True adr.importance = 201 adr.add_value("text/plain", "forth") ar.add_detail_object(adr) adr = ActivityDetailRecord(ActivityDetailType.RESULT) adr.show = True adr.importance = 201 adr.add_value("text/plain", "third") ar.add_detail_object(adr) adr = ActivityDetailRecord(ActivityDetailType.INPUT_DATA) adr.show = False adr.importance = 201 adr.add_value("text/plain", "fifth") ar.add_detail_object(adr) assert len(ar._detail_objects) == 6 assert ar._detail_objects[0][3].data['text/plain'] == 'first' assert ar._detail_objects[1][3].data['text/plain'] == 'second' assert ar._detail_objects[2][3].data['text/plain'] == 'third' assert ar._detail_objects[3][3].data['text/plain'] == 'forth' assert ar._detail_objects[4][3].data['text/plain'] == 'fifth' assert ar._detail_objects[5][3].data['text/plain'] == 'sixth'
def test_trim_detail_objects(self): """""" ar = ActivityRecord(ActivityType.CODE, show=True, message="added some code", importance=50, linked_commit='aaaaaaaa') adr1 = ActivityDetailRecord(ActivityDetailType.CODE) adr1.show = True adr1.importance = 100 adr1.add_value("text/plain", "first") ar.add_detail_object(adr1) adr2 = ActivityDetailRecord(ActivityDetailType.CODE) adr2.show = True adr2.importance = 0 adr2.add_value("text/plain", "second") ar.add_detail_object(adr2) adr3 = ActivityDetailRecord(ActivityDetailType.CODE) adr3.show = True adr3.importance = 0 adr3.add_value("text/plain", "third") ar.add_detail_object(adr3) assert len(ar._detail_objects) == 3 assert ar._detail_objects[0][3].data['text/plain'] == 'first' assert ar._detail_objects[1][3].data['text/plain'] == 'second' assert ar._detail_objects[2][3].data['text/plain'] == 'third' with ar.inspect_detail_objects(): ar.trim_detail_objects(2) assert len(ar._detail_objects) == 2 assert ar._detail_objects[0][3].data['text/plain'] == 'first' assert ar._detail_objects[1][3].data['text/plain'] == 'second' with pytest.raises(ValueError): with ar.inspect_detail_objects(): ar.trim_detail_objects(0)
def test_get_activity_records_with_intermediate_commits(self, mock_config_with_activitystore): """Method to test creating and getting a bunch of activity records with intermediate commits made""" linked_commit = helper_create_labbook_change(mock_config_with_activitystore[1], 1) ar = ActivityRecord(ActivityType.CODE, show=True, message="added some code 1", importance=50, linked_commit=linked_commit.hexsha) record1 = mock_config_with_activitystore[0].create_activity_record(ar) # Add some intermediate commits for cnt in range(10): helper_create_labbook_change(mock_config_with_activitystore[1], cnt) linked_commit = helper_create_labbook_change(mock_config_with_activitystore[1], 1) ar = ActivityRecord(ActivityType.CODE, show=True, message="added some code 2", importance=50, linked_commit=linked_commit.hexsha) record2 = mock_config_with_activitystore[0].create_activity_record(ar) linked_commit = helper_create_labbook_change(mock_config_with_activitystore[1], 1) ar = ActivityRecord(ActivityType.CODE, show=True, message="added some code 3", importance=50, linked_commit=linked_commit.hexsha) record3 = mock_config_with_activitystore[0].create_activity_record(ar) # add a bunch of non-activity record commits, which previously would prevent activity from coming back for cnt in range(20): helper_create_labbook_change(mock_config_with_activitystore[1], cnt) activity_records = mock_config_with_activitystore[0].get_activity_records() assert len(activity_records) == 3 assert activity_records[0].commit == record3.commit assert activity_records[0].linked_commit == record3.linked_commit assert activity_records[0].message == record3.message assert activity_records[1].commit == record2.commit assert activity_records[1].linked_commit == record2.linked_commit assert activity_records[1].message == record2.message assert activity_records[2].commit == record1.commit assert activity_records[2].linked_commit == record1.linked_commit assert activity_records[2].message == record1.message assert activity_records[2].username == 'default' assert activity_records[2].email == '*****@*****.**' activity_records = mock_config_with_activitystore[0].get_activity_records(first=6) assert len(activity_records) == 3 assert activity_records[0].commit == record3.commit assert activity_records[0].linked_commit == record3.linked_commit assert activity_records[0].message == record3.message assert activity_records[1].commit == record2.commit assert activity_records[1].linked_commit == record2.linked_commit assert activity_records[1].message == record2.message assert activity_records[2].commit == record1.commit assert activity_records[2].linked_commit == record1.linked_commit assert activity_records[2].message == record1.message assert activity_records[2].username == 'default' assert activity_records[2].email == '*****@*****.**' activity_records = mock_config_with_activitystore[0].get_activity_records(first=20) assert len(activity_records) == 3 activity_records = mock_config_with_activitystore[0].get_activity_records(first=2) assert len(activity_records) == 2 # Verify the timestamp is getting set properly assert type(activity_records[0].timestamp) == datetime assert activity_records[0].timestamp < datetime.now(timezone.utc) assert activity_records[0].timestamp > datetime.now(timezone.utc) - timedelta(seconds=10) activity_records = mock_config_with_activitystore[0].get_activity_records(first=1) assert len(activity_records) == 1 assert activity_records[0].commit == record3.commit assert activity_records[0].linked_commit == record3.linked_commit assert activity_records[0].message == record3.message activity_records = mock_config_with_activitystore[0].get_activity_records(after=record2.commit) assert len(activity_records) == 1 assert activity_records[0].commit == record1.commit assert activity_records[0].linked_commit == record1.linked_commit assert activity_records[0].message == record1.message activity_records = mock_config_with_activitystore[0].get_activity_records(after=record3.commit, first=1) assert len(activity_records) == 1 assert activity_records[0].commit == record2.commit assert activity_records[0].linked_commit == record2.linked_commit assert activity_records[0].message == record2.message activity_records = mock_config_with_activitystore[0].get_activity_records(after=record3.commit, first=20) assert len(activity_records) == 2 assert activity_records[0].commit == record2.commit assert activity_records[0].linked_commit == record2.linked_commit assert activity_records[0].message == record2.message
def test_get_activity_records(self, mock_config_with_activitystore): """Method to test creating and getting a bunch of activity records""" linked_commit = helper_create_labbook_change(mock_config_with_activitystore[1], 1) ar = ActivityRecord(ActivityType.CODE, show=True, message="added some code 1", importance=50, linked_commit=linked_commit.hexsha) record1 = mock_config_with_activitystore[0].create_activity_record(ar) linked_commit = helper_create_labbook_change(mock_config_with_activitystore[1], 1) ar = ActivityRecord(ActivityType.CODE, show=True, message="added some code 2", importance=50, linked_commit=linked_commit.hexsha) record2 = mock_config_with_activitystore[0].create_activity_record(ar) linked_commit = helper_create_labbook_change(mock_config_with_activitystore[1], 1) ar = ActivityRecord(ActivityType.CODE, show=True, message="added some code 3", importance=50, linked_commit=linked_commit.hexsha) record3 = mock_config_with_activitystore[0].create_activity_record(ar) activity_records = mock_config_with_activitystore[0].get_activity_records() assert len(activity_records) == 3 assert activity_records[0].commit == record3.commit assert activity_records[0].linked_commit == record3.linked_commit assert activity_records[0].message == record3.message assert activity_records[1].commit == record2.commit assert activity_records[1].linked_commit == record2.linked_commit assert activity_records[1].message == record2.message assert activity_records[2].commit == record1.commit assert activity_records[2].linked_commit == record1.linked_commit assert activity_records[2].message == record1.message assert activity_records[2].username == 'default' assert activity_records[2].email == '*****@*****.**' activity_records = mock_config_with_activitystore[0].get_activity_records(first=20) assert len(activity_records) == 3 assert activity_records[0].commit == record3.commit assert activity_records[0].linked_commit == record3.linked_commit assert activity_records[0].message == record3.message assert activity_records[1].commit == record2.commit assert activity_records[1].linked_commit == record2.linked_commit assert activity_records[1].message == record2.message assert activity_records[2].commit == record1.commit assert activity_records[2].linked_commit == record1.linked_commit assert activity_records[2].message == record1.message assert activity_records[2].username == 'default' assert activity_records[2].email == '*****@*****.**' # Verify the timestamp is getting set properly assert type(activity_records[0].timestamp) == datetime assert activity_records[0].timestamp < datetime.now(timezone.utc) assert activity_records[0].timestamp > datetime.now(timezone.utc) - timedelta(seconds=10) activity_records = mock_config_with_activitystore[0].get_activity_records(first=1) assert len(activity_records) == 1 assert activity_records[0].commit == record3.commit assert activity_records[0].linked_commit == record3.linked_commit assert activity_records[0].message == record3.message activity_records = mock_config_with_activitystore[0].get_activity_records(after=record2.commit) assert len(activity_records) == 1 assert activity_records[0].commit == record1.commit assert activity_records[0].linked_commit == record1.linked_commit assert activity_records[0].message == record1.message activity_records = mock_config_with_activitystore[0].get_activity_records(after=record3.commit, first=1) assert len(activity_records) == 1 assert activity_records[0].commit == record2.commit assert activity_records[0].linked_commit == record2.linked_commit assert activity_records[0].message == record2.message activity_records = mock_config_with_activitystore[0].get_activity_records(after=record3.commit, first=20) assert len(activity_records) == 2 assert activity_records[0].commit == record2.commit assert activity_records[0].linked_commit == record2.linked_commit assert activity_records[0].message == record2.message