Skip to content

Commit 562335c

Browse files
authored
Merge branch 'fix_min_epoch_time' of 'https://github.com/sduenas/sortinghat-eclipse-foundation'
Merges #1 Closes #1
2 parents be1de1b + 146817d commit 562335c

3 files changed

Lines changed: 80 additions & 19 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
title: Minimum value for 'from_date' error
3+
category: fixed
4+
author: Santiago Dueñas <sduenas@bitergia.com>
5+
issue: null
6+
notes: >
7+
EclipseFoundation API only allows to fetch identities
8+
updated since the last year. The backend allowed dates
9+
before that but the server raised BadRequest error.

sortinghat/core/importer/backends/eclipse.py

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import logging
1919

20+
import dateutil.relativedelta
2021
import requests
2122

2223
from django.conf import settings
@@ -27,7 +28,10 @@
2728
OAuth2Client
2829
)
2930

30-
from grimoirelab_toolkit.datetime import str_to_datetime
31+
from grimoirelab_toolkit.datetime import (
32+
str_to_datetime,
33+
datetime_utcnow
34+
)
3135
from sortinghat.core.importer.backend import IdentitiesImporter
3236
from sortinghat.core.importer.models import (
3337
Individual,
@@ -53,24 +57,43 @@ class EclipseFoundationAccountsImporter(IdentitiesImporter):
5357
5458
The importer fetches and stores in the database identities
5559
created or updated after the given date (`from_date`) parameter.
56-
When no date is given, it will import all the identities available
57-
in the platform.
60+
Currently, it can only import identities updated since a year ago.
61+
When no date is given, it will import all the identities updated
62+
since last year.
5863
5964
Each individual created after importing will have two identities:
6065
one with source set as 'eclipsefdn' that includes their name, email
6166
and username as it comes from the platform, and a second one with
6267
source 'github' only when the github user was set by the identity
6368
on the Eclipse profile.
69+
70+
:param ctx: SortingHat context
71+
:param url: not used on this importer
72+
:param from_date: start fetching identities updated from this date
73+
74+
:raises ValueError: when the date is older than one year ago
6475
"""
6576
NAME = "EclipseFoundation"
6677

6778
def __init__(self, ctx, url, from_date=None):
6879
super().__init__(ctx, url)
6980

70-
if isinstance(from_date, str):
71-
from_date = str_to_datetime(from_date)
81+
min_date = datetime_utcnow() - dateutil.relativedelta.relativedelta(years=1)
7282

73-
self.from_date = from_date
83+
if not from_date:
84+
self.from_date = min_date
85+
elif isinstance(from_date, str):
86+
self.from_date = str_to_datetime(from_date)
87+
else:
88+
self.from_date = from_date
89+
90+
if self.from_date < min_date:
91+
msg = (
92+
"Invalid 'from_date' value. It can only import identities updated since a year ago."
93+
"from_date=" + from_date
94+
)
95+
logger.error(msg)
96+
raise ValueError(msg)
7497

7598
def get_individuals(self):
7699
"""Get the individuals from the Eclipse Foundation platform."""
@@ -81,7 +104,7 @@ def get_individuals(self):
81104
client = EclipseFoundationAPIClient()
82105
client.login(user_id, password)
83106

84-
epoch = int(self.from_date.timestamp()) if self.from_date else 1
107+
epoch = int(self.from_date.timestamp())
85108

86109
# Fetch accounts pages
87110
for account in client.fetch_accounts(epoch=epoch):

tests/test_eclipse.py

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from unittest.mock import patch
55

66
import httpretty
7+
8+
from dateutil.relativedelta import relativedelta
79
from dateutil.tz import tzutc
810
from django.test import TestCase
911
from django.contrib.auth import get_user_model
@@ -20,6 +22,9 @@
2022
OAUTH_TOKEN_ENDPOINT = "https://accounts.eclipse.org/oauth2/token"
2123

2224

25+
MOCK_DATETIME_NOW = datetime.datetime(2025, 1, 1, tzinfo=tzutc())
26+
27+
2328
def read_file(filename, mode='r'):
2429
with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), filename), mode) as f:
2530
content = f.read()
@@ -95,38 +100,59 @@ def setUp(self):
95100
self.user = get_user_model().objects.create(username='test')
96101
self.ctx = SortingHatContext(self.user)
97102

98-
def test_initialization(self):
103+
@patch('sortinghat.core.importer.backends.eclipse.datetime_utcnow', return_value=MOCK_DATETIME_NOW)
104+
def test_initialization(self, mock_datetime_now):
99105
"""Test whether attributes are initialized"""
100106

101107
url = "https://test-url.com/"
102108

103-
importer = EclipseFoundationAccountsImporter(ctx=self.ctx,
104-
url=url)
109+
importer = EclipseFoundationAccountsImporter(
110+
ctx=self.ctx,
111+
url=url
112+
)
105113

106114
self.assertEqual(importer.url, url)
107115
self.assertEqual(importer.ctx, self.ctx)
108116
self.assertEqual(importer.NAME, "EclipseFoundation")
109-
self.assertIsNone(importer.from_date)
117+
118+
# 'from_date' is 1 year before the current date (MOCK_DATETIME_NOW)
119+
self.assertEqual(importer.from_date, mock_datetime_now.return_value - relativedelta(years=1))
120+
121+
@patch('sortinghat.core.importer.backends.eclipse.datetime_utcnow', return_value=MOCK_DATETIME_NOW)
122+
def test_parse_from_date(self, mock_datetime_now):
123+
"""Check if from_date parameter is parsed correctly"""
110124

111125
# Check from_date is parsed correctly
112126
importer = EclipseFoundationAccountsImporter(
113127
ctx=self.ctx,
114-
url=url,
115-
from_date="2023-12-01"
128+
url="https://test-url.com/",
129+
from_date="2025-12-01"
116130
)
117-
self.assertEqual(importer.from_date, datetime.datetime(year=2023,
131+
self.assertEqual(importer.from_date, datetime.datetime(year=2025,
118132
month=12,
119133
day=1,
120134
tzinfo=tzutc()))
121135

136+
@patch('sortinghat.core.importer.backends.eclipse.datetime_utcnow', return_value=MOCK_DATETIME_NOW)
137+
def test_from_date_older_than_one_year(self, mock_datetime_now):
138+
"""Check if an error is raised when the from_date is invalid"""
139+
140+
with self.assertRaises(ValueError):
141+
_ = EclipseFoundationAccountsImporter(
142+
ctx=self.ctx,
143+
url="https://test-url.com/",
144+
from_date="2000-01-01"
145+
)
146+
122147
def test_backend_name(self):
123148
"""Test whether the NAME of the backend is right"""
124149

125150
self.assertEqual(EclipseFoundationAccountsImporter.NAME, "EclipseFoundation")
126151

127152
@httpretty.activate
128153
@patch('sortinghat.core.importer.backends.eclipse.EclipseFoundationAPIClient.login', return_value="mocked_login")
129-
def test_import_identities(self, mock_login):
154+
@patch('sortinghat.core.importer.backends.eclipse.datetime_utcnow', return_value=MOCK_DATETIME_NOW)
155+
def test_import_identities(self, mock_login, mock_datetime_now):
130156

131157
# Set up a mock HTTP server
132158
requests, bodies = setup_mock_server()
@@ -194,14 +220,15 @@ def test_import_identities(self, mock_login):
194220

195221
@httpretty.activate
196222
@patch('sortinghat.core.importer.backends.eclipse.EclipseFoundationAPIClient.login', return_value="mocked_login")
197-
def test_import_no_identities(self, mock_login):
223+
@patch('sortinghat.core.importer.backends.eclipse.datetime_utcnow', return_value=MOCK_DATETIME_NOW)
224+
def test_import_no_identities(self, mock_login, mock_datetime_now):
198225
# Set up a mock HTTP server
199226
requests, bodies = setup_mock_server()
200227

201228
importer = EclipseFoundationAccountsImporter(
202229
ctx=self.ctx,
203230
url=None,
204-
from_date=datetime.datetime(2100, 1, 1, 0, 0, 0, tzinfo=tzutc())
231+
from_date="2100-1-1"
205232
)
206233

207234
n = importer.import_identities()
@@ -211,7 +238,8 @@ def test_import_no_identities(self, mock_login):
211238

212239
@httpretty.activate
213240
@patch('sortinghat.core.importer.backends.eclipse.EclipseFoundationAPIClient.login', return_value="mocked_login")
214-
def test_import_merge_identities(self, mock_login):
241+
@patch('sortinghat.core.importer.backends.eclipse.datetime_utcnow', return_value=MOCK_DATETIME_NOW)
242+
def test_import_merge_identities(self, mock_login, mock_datetime_now):
215243

216244
# Add individuals that share email and github handle
217245
api.add_identity(self.ctx, source='github', username='jsmith')
@@ -231,7 +259,8 @@ def test_import_merge_identities(self, mock_login):
231259

232260
@httpretty.activate
233261
@patch('sortinghat.core.importer.backends.eclipse.EclipseFoundationAPIClient.login', return_value="mocked_login")
234-
def test_import_enrollments(self, mock_login):
262+
@patch('sortinghat.core.importer.backends.eclipse.datetime_utcnow', return_value=MOCK_DATETIME_NOW)
263+
def test_import_enrollments(self, mock_login, mock_datetime_now):
235264

236265
# Set up a mock HTTP server
237266
setup_mock_server()

0 commit comments

Comments
 (0)