Skip to content

Commit

Permalink
python: fix date parsing by ensuring timezone-aware datetime objects …
Browse files Browse the repository at this point in the history
…(github-ci)

- Ensured all datetime objects are timezone-aware in UTC
- Fixed date parsing issues encountered in GitHub CI

Signed-off-by: Abhishek Gaikwad <[email protected]>
  • Loading branch information
gaikwadabhishek committed Sep 19, 2024
1 parent a8a5c1e commit 9baf63a
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
go-version: ['1.22.x']
os: [ubuntu-latest]
os: [ubuntu-latest, macos-latest]
python-version: ['3.8','3.9','3.10','3.11']
runs-on: ${{ matrix.os }}
steps:
Expand Down
40 changes: 21 additions & 19 deletions python/aistore/sdk/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,41 +236,43 @@ def start(
)
return resp.text

def _parse_iso_datetime(self, dt_str):
# Remove 'Z' timezone designator if present
if dt_str.endswith("Z"):
dt_str = dt_str[:-1]
# Handle fractional seconds (nanoseconds) by truncating to microseconds
if "." in dt_str:
date_part, frac_part = dt_str.split(".")
# Truncate or pad the fractional part to 6 digits (microseconds)
frac_part = (frac_part + "000000")[:6]
dt_str = f"{date_part}.{frac_part}"
return datetime.strptime(dt_str, "%Y-%m-%dT%H:%M:%S.%f")
return datetime.strptime(dt_str, "%Y-%m-%dT%H:%M:%S")

def get_within_timeframe(
self, start_time: datetime.time, end_time: datetime.time
self, start_time: datetime.datetime, end_time: datetime.datetime
) -> List[JobSnapshot]:
"""
Checks for jobs that started and finished within a specified timeframe
Checks for jobs that started and finished within a specified timeframe.
Args:
start_time (datetime.time): The start of the timeframe for monitoring jobs
end_time (datetime.time): The end of the timeframe for monitoring jobs
start_time (datetime.datetime): The start of the timeframe for monitoring jobs.
end_time (datetime.datetime): The end of the timeframe for monitoring jobs.
Returns:
list: A list of jobs that have finished within the specified timeframe
List[JobSnapshot]: A list of jobs that have finished within the specified timeframe.
Raises:
requests.RequestException: "There was an ambiguous exception that occurred while handling..."
requests.ConnectionError: Connection error
requests.ConnectionTimeout: Timed out connecting to AIStore
requests.ReadTimeout: Timed out waiting response from AIStore
errors.Timeout: Timeout while waiting for the job to finish
errors.JobInfoNotFound: Raised when information on a job's status could not be found on the AIS cluster
JobInfoNotFound: Raised when information on a job's status could not be found.
"""

snapshots = self._query_job_snapshots()
jobs_found = []
for snapshot in snapshots:
if snapshot.id == self.job_id or snapshot.kind == self.job_kind:
snapshot_start_time = datetime.fromisoformat(
snapshot.start_time[:26]
).time()
snapshot_end_time = datetime.fromisoformat(
snapshot.end_time[:26]
).time()
snapshot_start_time = self._parse_iso_datetime(snapshot.start_time)
snapshot_end_time = self._parse_iso_datetime(snapshot.end_time)
if snapshot_start_time >= start_time and snapshot_end_time <= end_time:
jobs_found.append(snapshot)
print(snapshot)
if len(jobs_found) == 0:
raise JobInfoNotFound("No relevant job info found")
return jobs_found
Expand Down
4 changes: 2 additions & 2 deletions python/tests/integration/sdk/test_job_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ def test_job_wait_single_node(self):
self._validate_objects_cached(objects, True)

def test_get_within_timeframe(self):
start_time = datetime.now().time()
start_time = datetime.now()
job_id = self.client.job(job_kind="lru").start()
self.client.job(job_id=job_id).wait()
end_time = datetime.now().time()
end_time = datetime.now()
self.assertNotEqual(job_id, "")
jobs_list = self.client.job(job_id=job_id).get_within_timeframe(
start_time=start_time, end_time=end_time
Expand Down
8 changes: 4 additions & 4 deletions python/tests/integration/sdk/test_object_group_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ def test_prefetch_blob_download(self):
self.obj_names.extend(obj_names)
obj_group = self.bucket.objects(obj_names=obj_names)
self._evict_all_objects(num_obj=OBJECT_COUNT + 1)
start_time = datetime.now().time()
start_time = datetime.now()
job_id = obj_group.prefetch(blob_threshold=2 * MIB)
self.client.job(job_id=job_id).wait(timeout=TEST_TIMEOUT * 2)
end_time = datetime.now().time()
end_time = datetime.now()
jobs_list = self.client.job(job_kind="blob-download").get_within_timeframe(
start_time=start_time, end_time=end_time
)
Expand All @@ -113,10 +113,10 @@ def test_prefetch_without_blob_download(self):
self.obj_names.extend(obj_names)
obj_group = self.bucket.objects(obj_names=obj_names)
self._evict_all_objects(num_obj=OBJECT_COUNT + 1)
start_time = datetime.now().time()
start_time = datetime.now()
job_id = obj_group.prefetch(blob_threshold=2 * SMALL_FILE_SIZE)
self.client.job(job_id=job_id).wait(timeout=TEST_TIMEOUT * 2)
end_time = datetime.now().time()
end_time = datetime.now()

with self.assertRaises(JobInfoNotFound):
self.client.job(job_kind="blob-download").get_within_timeframe(
Expand Down
4 changes: 2 additions & 2 deletions python/tests/integration/sdk/test_object_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def test_get_blob_download(self, testcase):
self.client.job(evict_job_id).wait(timeout=TEST_TIMEOUT)

for obj_name, content in objects.items():
start_time = datetime.now().time()
start_time = datetime.now()
blob_download_settings = BlobDownloadSettings(
chunk_size=testcase, num_workers="4"
)
Expand All @@ -216,7 +216,7 @@ def test_get_blob_download(self, testcase):
.read_all()
)
self.assertEqual(content, resp)
end_time = datetime.now().time()
end_time = datetime.now()
jobs_list = self.client.job(job_kind="blob-download").get_within_timeframe(
start_time=start_time, end_time=end_time
)
Expand Down
4 changes: 2 additions & 2 deletions python/tests/unit/sdk/test_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def test_get_within_timeframe_found_jobs(self):

self.mock_client.request_deserialize.return_value = {"key": mock_snapshots}

found_jobs = self.job.get_within_timeframe(start_time.time(), end_time.time())
found_jobs = self.job.get_within_timeframe(start_time, end_time)

self.assertEqual(len(found_jobs), len(mock_snapshots))
for found_job, expected_snapshot in zip(found_jobs, mock_snapshots):
Expand All @@ -326,4 +326,4 @@ def test_get_within_timeframe_no_jobs_found(self):
self.mock_client.request_deserialize.return_value = {}

with self.assertRaises(JobInfoNotFound):
self.job.get_within_timeframe(start_time.time(), end_time.time())
self.job.get_within_timeframe(start_time, end_time)

0 comments on commit 9baf63a

Please sign in to comment.