Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion app/config.py.example
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ VALID_FILE_EXTENSION = (".txt", ".csv", ".ics") # Can import only these files.
EVENT_VALID_YEARS = 20
EVENT_HEADER_NOT_EMPTY = 1 # 1- for not empty, 0- for empty.
EVENT_HEADER_LIMIT = 50 # Max characters for event header.
EVENT_CONTENT_LIMIT = 500 # Max characters for event characters.
EVENT_CONTENT_LIMIT = 500 # Max characters for event content.
MAX_EVENTS_START_DATE = 10 # Max Events with the same start date.
LOCATION_LIMIT = 50 # Max characters for Location.
EVENT_DURATION_LIMIT = 2 # the max duration in days for an event.

# PATHS
STATIC_ABS_PATH = os.path.abspath("static")
Expand Down
79 changes: 67 additions & 12 deletions app/internal/import_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@

from app.config import (
EVENT_CONTENT_LIMIT,
EVENT_DURATION_LIMIT,
EVENT_HEADER_LIMIT,
EVENT_HEADER_NOT_EMPTY,
EVENT_VALID_YEARS,
LOCATION_LIMIT,
MAX_EVENTS_START_DATE,
MAX_FILE_SIZE_MB,
VALID_FILE_EXTENSION
Expand All @@ -22,12 +24,22 @@


DATE_FORMAT = "%m-%d-%Y"
DATE_FORMAT2 = "%m-%d-%Y %H:%M"
DESC_EVENT = "VEVENT"
EVENT_PATTERN = re.compile(r"^(\w{" + str(EVENT_HEADER_NOT_EMPTY) + "," +
str(EVENT_HEADER_LIMIT) + r"}),\s(\w{0," +
str(EVENT_CONTENT_LIMIT) +
r"}),\s(\d{2}-\d{2}-\d{4})," +
r"\s(\d{2}-\d{2}-\d{4})$")
r"\s(\d{2}-\d{2}-\d{4})(?:,\s([\w\s-]{0," +
str(LOCATION_LIMIT) +
r"}))?$")
EVENT_PATTERN2 = re.compile(r"^(\w{" + str(EVENT_HEADER_NOT_EMPTY) + "," +
str(EVENT_HEADER_LIMIT) + r"}),\s(\w{0," +
str(EVENT_CONTENT_LIMIT) +
r"}),\s(\d{2}-\d{2}-\d{4}\s\d{2}:\d{2})," +
r"\s(\d{2}-\d{2}-\d{4}\s\d{2}:\d{2})" +
r"(?:,\s([\w\s-]{0," + str(LOCATION_LIMIT) +
r"}))?$")


def is_file_size_valid(file: str, max_size: int = MAX_FILE_SIZE_MB) -> bool:
Expand All @@ -45,26 +57,54 @@ def is_file_exist(file: str) -> bool:
return Path(file).is_file()


def change_string_to_date(date: str) -> Union[datetime.datetime, bool]:
try:
if re.search(r":", date):
date1 = datetime.datetime.strptime(date, DATE_FORMAT2)
else:
date1 = datetime.datetime.strptime(date, DATE_FORMAT)
except ValueError:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of the except here?

Copy link
Contributor Author

@Nir-P Nir-P Feb 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the string is not a valid date datetime.strptime will fail to transform the string to date and we want to catch it.

return False
return date1


def is_date_in_range(date: Union[str, datetime.datetime],
valid_dates: int = EVENT_VALID_YEARS) -> bool:
"""
check if date is valid and in the range according to the rule we have set
"""
now_year = datetime.datetime.now().year
if isinstance(date, str):
try:
check_date = datetime.datetime.strptime(date, DATE_FORMAT)
except ValueError:
check_date = change_string_to_date(date)
if check_date is False:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer == False

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed it to not if this is ok.

return False
else:
check_date = date
return now_year - valid_dates < check_date.year < now_year + valid_dates


def is_start_day_before_end_date(start: Union[datetime.datetime, str],
end: Union[datetime.datetime, str]) -> bool:
if isinstance(start, str):
start = change_string_to_date(start)
end = change_string_to_date(end)
return start <= end


def is_event_valid_duration(start: Union[datetime.datetime, str],
end: Union[datetime.datetime, str],
max_duration: int = EVENT_DURATION_LIMIT) -> bool:
if isinstance(start, str):
start = change_string_to_date(start)
end = change_string_to_date(end)
return (end - start).days < max_duration


def is_event_text_valid(row: str) -> bool:
"""Check if the row contains valid data"""
get_values = EVENT_PATTERN.search(row)
return get_values is not None
get_values2 = EVENT_PATTERN2.search(row)
return get_values is not None or get_values2 is not None


def is_file_valid_to_import(file: str) -> bool:
Expand Down Expand Up @@ -100,17 +140,29 @@ def open_txt_file(txt_file: str) -> Generator[str, None, None]:

def save_calendar_content_txt(event: str, calendar_content: List) -> bool:
"""populate calendar with event content"""
head, content, start_date, end_date = event.split(", ")
if len(event.split(", ")) == 5:
head, content, start_date, end_date, location = event.split(", ")
location = location.replace("\n", "")
else:
head, content, start_date, end_date = event.split(", ")
end_date = end_date.replace("\n", "")
location = None
if (not is_date_in_range(start_date) or
not is_date_in_range(end_date.replace("\n", ""))):
not is_date_in_range(end_date) or
not is_start_day_before_end_date(start_date, end_date) or
not is_event_valid_duration(start_date, end_date)):
return False
start_date = datetime.datetime.strptime(start_date, DATE_FORMAT)
end_date = datetime.datetime.strptime(end_date.replace("\n", ""),
DATE_FORMAT)
if re.search(r":", start_date) and re.search(r":", start_date):
start_date = datetime.datetime.strptime(start_date, DATE_FORMAT2)
end_date = datetime.datetime.strptime(end_date, DATE_FORMAT2)
else:
start_date = datetime.datetime.strptime(start_date, DATE_FORMAT)
end_date = datetime.datetime.strptime(end_date, DATE_FORMAT)
calendar_content.append({"Head": head,
"Content": content,
"S_Date": start_date,
"E_Date": end_date})
"E_Date": end_date,
"Location": location})
return True


Expand Down Expand Up @@ -149,7 +201,8 @@ def save_calendar_content_ics(component, calendar_content) -> None:
"S_Date": component.get('dtstart').dt
.replace(tzinfo=None),
"E_Date": component.get('dtend').dt
.replace(tzinfo=None)
.replace(tzinfo=None),
"Location": str(component.get('location'))
})


Expand All @@ -175,12 +228,14 @@ def save_events_to_database(events: List[Dict[str, Union[str, Any]]],
content = event["Content"]
start = event["S_Date"]
end = event["E_Date"]
location = event["Location"]
owner_id = user_id
create_event(db=session,
title=title,
content=content,
start=start,
end=end,
location=location,
owner_id=owner_id)


Expand Down
4 changes: 2 additions & 2 deletions tests/files_for_import_file_tests/sample.ics
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ BEGIN:VEVENT
SUMMARY:HeadA
DTSTART;TZID=America/New_York:20190802T103400
DTEND;TZID=America/New_York:20190802T110400
LOCATION:1000 Broadway Ave.\, Brooklyn
LOCATION:Tel-Aviv
DESCRIPTION:Content1
STATUS:CONFIRMED
SEQUENCE:3
Expand All @@ -19,7 +19,7 @@ BEGIN:VEVENT
SUMMARY:HeadB
DTSTART;TZID=America/New_York:20190802T200000
DTEND;TZID=America/New_York:20190802T203000
LOCATION:900 Jay St.\, Brooklyn
LOCATION:Tel-Aviv
DESCRIPTION:Content2
STATUS:CONFIRMED
SEQUENCE:3
Expand Down
4 changes: 2 additions & 2 deletions tests/files_for_import_file_tests/sample2.ics
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ CALSCALE:GREGORIAN
SUMMARY:HeadA
DTSTART;TZID=America/New_York:20190802T103400
DTEND;TZID=America/New_York:20190802T110400
LOCATION:1000 Broadway Ave.\, Brooklyn
LOCATION:Tel-Aviv
DESCRIPTION:Content1
STATUS:CONFIRMED
SEQUENCE:3
Expand All @@ -19,7 +19,7 @@ BEGIN:VEVENT
SUMMARY:HeadB
DTSTART;TZID=America/New_York:20190802T200000
DTEND;TZID=America/New_York:20190802T203000
LOCATION:900 Jay St.\, Brooklyn
LOCATION:Tel-Aviv
DESCRIPTION:Content2
STATUS:CONFIRMED
SEQUENCE:3
Expand Down
4 changes: 2 additions & 2 deletions tests/files_for_import_file_tests/sample3.ics
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ BEGIN:VEVENT



LOCATION:1000 Broadway Ave.\, Brooklyn
LOCATION:Tel-Aviv
DESCRIPTION:Content1
STATUS:CONFIRMED
SEQUENCE:3
Expand All @@ -19,7 +19,7 @@ BEGIN:VEVENT
SUMMARY:HeadB
DTSTART;TZID=America/New_York:20190802T200000
DTEND;TZID=America/New_York:20190802T203000
LOCATION:900 Jay St.\, Brooklyn
LOCATION:Tel-Aviv
DESCRIPTION:Content2
STATUS:CONFIRMED
SEQUENCE:3
Expand Down
3 changes: 3 additions & 0 deletions tests/files_for_import_file_tests/sample_date2_ver.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Option1, Content1, 05-21-2019 10:30, 05-21-2019 11:30
Option2, Content2, 01-11-2010 11:30, 01-11-2010 12:30
Option3, Content3, 02-02-2022 13:00, 02-02-2022 13:05
3 changes: 3 additions & 0 deletions tests/files_for_import_file_tests/sample_date_mix.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Option1, Content1, 05-21-2019, 05-21-2019 11:30
Option2, Content2, 01-11-2010 11:30, 01-11-2010 12:30
Option3, Content3, 02-02-2022 13:00, 02-02-2022 13:05
3 changes: 3 additions & 0 deletions tests/files_for_import_file_tests/‏‏sample_loc_ver.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Option1, Content1, 05-21-2019 10:30, 05-21-2019 11:30, aaa
Option2, Content2, 01-11-2010 11:30, 01-11-2010 12:30, bbb
Option3, Content3, 02-02-2022 13:00, 02-02-2022 13:05, ccc
Loading