Keep only one current affiliation

In OpenStackID user may specify multiple current affiliations. While it
can be true, Stackalytics still need to choose only one. Keep the latest
as current and update ends for all others.

Change-Id: I99c3c134e4f6fab9bc252ef8f381a928fa0c88ae
This commit is contained in:
Ilya Shakhat 2017-08-25 13:54:49 +02:00
parent fd2ba43994
commit 243df5911d
2 changed files with 123 additions and 1 deletions

View File

@ -46,6 +46,27 @@ def _openstack_profile_by_email(email):
Interval = collections.namedtuple('Interval', ['start', 'end', 'value'])
def _cut_open_ended_intervals(intervals):
"""Keep only one open interval
If there are multiple open intervals keep only the latest open;
cut others so they no longer intersect each other.
:param intervals: [Interval]
:return: processed intervals: [Interval]
"""
filtered_intervals = []
cut = 0
for interval in reversed(intervals):
if not interval.end:
new_interval = Interval(interval.start, cut, interval.value)
filtered_intervals.append(new_interval)
cut = interval.start
else:
filtered_intervals.append(interval)
return list(reversed(filtered_intervals))
def _iterate_intervals(intervals, threshold=INTERVAL_GAP_THRESHOLD):
"""Iterate intervals and fill gaps around of them
@ -56,6 +77,7 @@ def _iterate_intervals(intervals, threshold=INTERVAL_GAP_THRESHOLD):
yield Interval(0, 0, None)
else:
intervals.sort(key=lambda x: x.start)
intervals = _cut_open_ended_intervals(intervals)
prev_start = 0

View File

@ -23,7 +23,6 @@ USER_PROFILE = {
"id": 5555,
"first_name": "John",
"last_name": "Smith",
"pic": "https://www.openstack.org/profile_images/members/5555",
"affiliations": [
{
"start_date": 1193875200,
@ -108,6 +107,53 @@ USER_PROFILE_MULTIPLE_RECORDS = {
}
]
}
USER_PROFILE_NO_CURRENT = {
"total": 1,
"data": [
{
"id": 5555,
"first_name": "John",
"last_name": "Smith",
"affiliations": [
{
"start_date": 1193875200,
"end_date": 1496188800,
"organization": {
"name": "Mirantis"
}
}
]
}
]
}
USER_PROFILE_MULTIPLE_CURRENT = {
"total": 1,
"data": [
{
"id": 1111,
"first_name": "John",
"last_name": "Smith",
"affiliations": [
{
"start_date": 1378339200,
"end_date": None,
"is_current": True,
"organization": {
"name": "NTT"
}
},
{
"start_date": 1442880000,
"end_date": None,
"is_current": True,
"organization": {
"name": "NTT DATA"
}
}
]
}
]
}
class TestOpenStackIDUtils(testtools.TestCase):
@ -253,3 +299,57 @@ class TestOpenStackIDUtils(testtools.TestCase):
reader_mock.assert_called_once_with(
ou.OSID_URI % email, session=ou._openstackid_session)
self.assertEqual(expected, observed)
@mock.patch('stackalytics.processor.utils.read_json_from_uri')
def test_user_profile_by_email_no_current(self, reader_mock):
reader_mock.return_value = USER_PROFILE_NO_CURRENT
email = 'dummy@dummy.org'
expected = {
'openstack_id': 5555,
'user_name': 'John Smith',
'emails': [email],
'companies': [{
'company_name': '*independent',
'end_date': 1193875200
}, {
'company_name': 'Mirantis',
'end_date': 1496188800
}, {
'company_name': '*independent',
'end_date': 0
}]
}
observed = ou.user_profile_by_email(email)
reader_mock.assert_called_once_with(
ou.OSID_URI % email, session=ou._openstackid_session)
self.assertEqual(expected, observed)
@mock.patch('stackalytics.processor.utils.read_json_from_uri')
def test_user_profile_by_email_multiple_current(self, reader_mock):
reader_mock.return_value = USER_PROFILE_MULTIPLE_CURRENT
email = 'dummy@dummy.org'
expected = {
'openstack_id': 1111,
'user_name': 'John Smith',
'emails': [email],
'companies': [{
'company_name': '*independent',
'end_date': 1378339200
}, {
'company_name': 'NTT',
'end_date': 1442880000
}, {
'company_name': 'NTT DATA',
'end_date': 0
}]
}
observed = ou.user_profile_by_email(email)
reader_mock.assert_called_once_with(
ou.OSID_URI % email, session=ou._openstackid_session)
self.assertEqual(expected, observed)