Skip to content

Commit

Permalink
feat: adds data name patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
jtyoung84 committed May 8, 2024
1 parent cf120e4 commit 4ba8ca6
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 13 deletions.
45 changes: 42 additions & 3 deletions src/aind_data_schema_models/data_name_patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,57 @@ class Group(str, Enum):


def datetime_to_name_string(dt: datetime) -> str:
"""Take a date and time object, format it as a string"""
"""
Take a datetime object, format it as a string
Parameters
----------
dt : datetime
For example, datetime(2020, 12, 29, 10, 04, 59)
Returns
-------
str
For example, '2020-12-29_10-04-59'
"""
return dt.strftime("%Y-%m-%d_%H-%M-%S")


def datetime_from_name_string(d: str, t: str) -> datetime:
"""Take date and time strings, generate date and time objects"""
"""
Take date and time strings, generate datetime object
Parameters
----------
d : str
Date string formatted as %Y-%m-%d
t : str
Time string formatted as %H-%M-%S
Returns
-------
datetime
"""
d = datetime.strptime(d, "%Y-%m-%d").date()
t = datetime.strptime(t, "%H-%M-%S").time()
return datetime.combine(d, t)


def build_data_name(label: str, creation_datetime: datetime) -> str:
"""Construct a valid data description name"""
"""
Construct a data description name from a label and datetime object
Parameters
----------
label : str
For example, 'ecephys_123456'
creation_datetime : datetime
For example, datetime(2020, 12, 29, 10, 04, 59)
Returns
-------
str
For example, 'ecephys_123456_2020-12-29_10-04-59'
"""
dt_str = datetime_to_name_string(creation_datetime)
return f"{label}_{dt_str}"
97 changes: 87 additions & 10 deletions tests/test_data_name_patterns.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
"""Tests classes in data_name_patterns module"""

import unittest
from datetime import datetime, timezone

from aind_data_schema_models.data_name_patterns import (
datetime_to_name_string,
datetime_from_name_string,
build_data_name,
RegexParts,
DataRegex,
DataLevel,
Group,
RegexParts,
build_data_name,
datetime_from_name_string,
datetime_to_name_string,
)


Expand All @@ -28,11 +27,89 @@ def test_patterns_success(self):
def test_patterns_fail(self):
"""Tests that the regex patterns match unsuccessfully."""

deformed_date = "10/19/2020"
deformed_time = "8:30:59"
malformed_date = "10/19/2020"
malformed_time = "8:30:59"

self.assertNotRegex(malformed_date, RegexParts.DATE)
self.assertNotRegex(malformed_time, RegexParts.TIME)


class TestDataRegex(unittest.TestCase):
"""Tests methods in DataRegex class"""

def test_patterns_success(self):
"""Tests that the regex patterns match successfully."""

data = "ecephys_2020-10-19_08-30-59"
raw = "ecephys_123455_2020-10-19_08-30-59"
derived = "ecephys_123455_2020-10-19_08-30-59_sorted_2020-11-21_09-31-58"
analyzed = "ecephys_123455_2020-10-19_08-30-59_sorted_2020-11-21_09-31-58"
no_underscores = "abc-123<something>"
no_special_chars = "abc-123"
no_special_chars_except_space = "abc efg - 123"

self.assertRegex(data, DataRegex.DATA)
self.assertRegex(raw, DataRegex.RAW)
self.assertRegex(derived, DataRegex.DERIVED)
self.assertRegex(analyzed, DataRegex.ANALYZED)
self.assertRegex(no_underscores, DataRegex.NO_UNDERSCORES)
self.assertRegex(no_special_chars, DataRegex.NO_SPECIAL_CHARS)
self.assertRegex(no_special_chars_except_space, DataRegex.NO_SPECIAL_CHARS_EXCEPT_SPACE)

def test_patterns_fail(self):
"""Tests that the regex patterns match unsuccessfully."""

malformed_data = "ecephys_2020-10-19_08:30:59"
malformed_raw = "ecephys_123455_2020-10-19_08-30-59_test"
malformed_derived = "ecephys_123455_2020-10-19_08-30-59_sorted_2020-11-21_09:31:58"
malformed_analyzed = "ecephys_123455_2020-10-19_08-30-59_sorted_2020-11-21_09-31-58_test"
malformed_no_underscores = "abc_123<something>"
malformed_no_special_chars = "abc-123<something>"
malformed_no_special_chars_except_space = "abc efg - 123 <something>"

self.assertNotRegex(malformed_data, DataRegex.DATA)
self.assertNotRegex(malformed_raw, DataRegex.RAW)
self.assertNotRegex(malformed_derived, DataRegex.DERIVED)
self.assertNotRegex(malformed_analyzed, DataRegex.ANALYZED)
self.assertNotRegex(malformed_no_underscores, DataRegex.NO_UNDERSCORES)
self.assertNotRegex(malformed_no_special_chars, DataRegex.NO_SPECIAL_CHARS)
self.assertNotRegex(malformed_no_special_chars_except_space, DataRegex.NO_SPECIAL_CHARS_EXCEPT_SPACE)


class TestDataNamePatternsMethods(unittest.TestCase):
"""Tests methods in data_name_patterns module"""

def test_datetime_to_name_string(self):
"""Tests datetime object is converted to string"""

dt = datetime(2020, 12, 29, 1, 10, 50)
actual_output = datetime_to_name_string(dt)
self.assertEqual("2020-12-29_01-10-50", actual_output)

def test_datetime_with_tz_to_name_string(self):
"""Tests datetime object with timezone is converted to string"""

dt = datetime(2020, 12, 29, 1, 10, 50, tzinfo=timezone.utc)
actual_output = datetime_to_name_string(dt)
self.assertEqual("2020-12-29_01-10-50", actual_output)

def test_datetime_from_name_string(self):
"""Tests date and time strings are converted to datetime object"""

input_date_str = "2020-12-29"
input_time_str = "01-10-50"
actual_output = datetime_from_name_string(d=input_date_str, t=input_time_str)
dt = datetime(2020, 12, 29, 1, 10, 50)
self.assertEqual(dt, actual_output)

def test_build_data_name(self):
"""Tests datetime object is converted to string and attached to label"""

label = "ecephys_123456"
dt = datetime(2020, 12, 29, 1, 10, 50)
actual_output = build_data_name(label=label, creation_datetime=dt)

self.assertNotRegex(deformed_date, RegexParts.DATE)
self.assertNotRegex(deformed_time, RegexParts.TIME)
self.assertEqual("ecephys_123456_2020-12-29_01-10-50", actual_output)


if __name__ == "__main__":
Expand Down

0 comments on commit 4ba8ca6

Please sign in to comment.