Skip to content
This repository has been archived by the owner on May 28, 2022. It is now read-only.

Commit

Permalink
- Update presentation start time and end time to use hh:mm ap format
Browse files Browse the repository at this point in the history
- Add database scheme upgrade function from 310 to 315

- Update presentation constructor to use empty string default values
  • Loading branch information
Stephen Romansky committed Dec 29, 2014
1 parent cb1a71e commit 9a42835
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 69 deletions.
2 changes: 1 addition & 1 deletion src/freeseer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

NAME = 'freeseer'
__version__ = '3.0.9999'
SCHEMA_VERSION = 310
SCHEMA_VERSION = 315
__author__ = "Free and Open Source Software Learning Center"
__email__ = "[email protected]"
URL = 'http://github.com/Freeseer/freeseer'
Expand Down
73 changes: 46 additions & 27 deletions src/freeseer/framework/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@
Time timestamp,
UNIQUE (Speaker, Title) ON CONFLICT IGNORE)'''

# The SQLITE timestamp field corresponds to the DateTime object. The Date column in the database can be created from
# a DateTime.date() call.
# The SQLITE timestamp field corresponds to the QDate and QTime object.
PRESENTATIONS_SCHEMA_310 = '''CREATE TABLE IF NOT EXISTS presentations
(Id INTEGER PRIMARY KEY,
Title varchar(255),
Expand All @@ -63,15 +62,7 @@
EndTime timestamp,
UNIQUE (Speaker, Title) ON CONFLICT IGNORE)'''

# TODO: Make PRESENTATIONS_SCHEMA_315 the default schema when the presentation table is created
# TODO: Make an upgrade method from PRESENTATIONS_SCHEMA_310 to PRESENTATIONS_SCHEMA_315
# TODO: Update the SCHEMA_VERSION to 315
# TODO: Integrate new database scheme with importers/exporter functions
# TODO: Force Presentation.Date to be a QDate
# TODO: Figure out what the types should be for Presentation.StartTime/EndTime e.g. QTime
# TODO: Enforce the default database values in the CSV/RSS importer
# TODO: Enforce the default database values in Presentation.__init__
# TODO: Enforce the default database values in db.insert_presentation()
# TODO: Check what format the csv and rss sample files are in. For instance, do the rss files use 'None' instead of ''
# for missing fields?
# TODO: Update _helper_presentation_exists() and get_presentation_id() to use the new schema such that they no longer
Expand Down Expand Up @@ -182,17 +173,44 @@ def update_30to31():
FROM presentations_old""")
QtSql.QSqlQuery('DROP TABLE presentations_old')

def update_31to315():
"""Performs incremental update of database from 3.1 and older to 3.15."""
QtSql.QSqlQuery('ALTER TABLE presentations RENAME TO presentations_old')
self._create_presentations_table(PRESENTATIONS_SCHEMA_315)

old_presentations = QtSql.QSqlQuery('SELECT * FROM presentations_old')
# Convert old presentation values, specifically startTime and endTime, to new format
while old_presentations.next():
presentation_date = unicode(old_presentations.value(7).toDate().toString(QtCore.Qt.ISODate))
presentation_startTime = unicode(QtCore.QTime.fromString(old_presentations.value(8).toString(),
'mm:hh:ss').toString('hh:mm ap'))
presentation_endTime = unicode(QtCore.QTime.fromString(old_presentations.value(9).toString(),
'mm:hh:ss').toString('hh:mm ap'))

QtSql.QSqlQuery('''
INSERT INTO
presentations(Id, Title, Speaker, Description, Category, Event, Room, Date, StartTime, EndTime)
VALUES ('{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}');
'''.format(
unicode(old_presentations.value(0).toString()), unicode(old_presentations.value(1).toString()),
unicode(old_presentations.value(2).toString()), unicode(old_presentations.value(3).toString()),
unicode(old_presentations.value(4).toString()), unicode(old_presentations.value(5).toString()),
unicode(old_presentations.value(6).toString()), presentation_date, presentation_startTime,
presentation_endTime
))
QtSql.QSqlQuery('DROP TABLE presentations_old')

#
# Perform the upgrade
#
updaters = [update_2xto30, update_30to31]
updaters = [update_2xto30, update_30to31, update_31to315]
for updater in updaters:
updater()

QtSql.QSqlQuery('PRAGMA user_version = {}'.format(SCHEMA_VERSION))
log.info('Upgraded presentations database from version %d to %d', db_version, SCHEMA_VERSION)

def _create_presentations_table(self, schema=PRESENTATIONS_SCHEMA_310):
def _create_presentations_table(self, schema=PRESENTATIONS_SCHEMA_315):
"""Creates the presentations table in the database. Should be used to initialize a new table."""
log.info("table created")
QtSql.QSqlQuery(schema)
Expand All @@ -215,7 +233,7 @@ def get_talks_by_room(self, room):

def get_talks_by_room_and_time(self, room):
"""Returns the talks hosted in a specified room, starting from the current date and time"""
current_time = QtCore.QDateTime.currentDateTime()
current_time = QtCore.QTime.currentTime().toString('hh:mm ap')
current_date = QtCore.QDate.currentDate()
query = QtSql.QSqlQuery()
query.prepare('''
Expand All @@ -240,8 +258,8 @@ def get_presentation(self, talk_id):
event=unicode(result.value(5).toString()),
room=unicode(result.value(6).toString()),
date=result.value(7).toDate(),
startTime=result.value(8).toDateTime(),
endTime=result.value(9).toDateTime())
startTime=unicode(result.value(8).toString()),
endTime=unicode(result.value(9).toString()))
else:
return None

Expand Down Expand Up @@ -294,7 +312,7 @@ def _helper_presentation_exists(self, presentation):
FROM presentations
WHERE Title=:title AND Speaker=:speaker AND Description=:description AND Category=:category AND
Event=:event AND
(Date=date(:date) OR Date is NULL) AND
(Date=:date OR Date is NULL) AND
(Room=:room OR Room is NULL) AND
(StartTime=:startTime OR StartTime is NULL) AND
(EndTime=:endTime OR EndTime is NULL)
Expand Down Expand Up @@ -322,9 +340,9 @@ def insert_presentation(self, presentation):
"""Inserts a passed Presentation into the database."""
# The data comes from user input. Use prepare statement to sanitize it.
query = QtSql.QSqlQuery()
assert query.prepare('''
query.prepare('''
INSERT INTO presentations(Title, Speaker, Description, Category, Event, Room, Date, StartTime, EndTime)
VALUES (:title, :speaker, :description, :category, :event, :room, date(:date), :startTime, :endTime)
VALUES (:title, :speaker, :description, :category, :event, :room, :date, :startTime, :endTime)
''')
query.bindValue(':title', presentation.title)
query.bindValue(':speaker', presentation.speaker)
Expand Down Expand Up @@ -454,7 +472,7 @@ def get_talk_between_dates(self, event, room, startDate, endDate):
#
def isodate_string_to_qtime(self, date):
"""Converts ISODate format strings to times. Example, 2014-01-01T15:32 -> 3:32 pm"""
return QtCore.QDateTime.fromString(date, 'yyyy-MM-ddThh:mm').time().toString('hh:mm ap')
return QtCore.QDateTime.fromString(date, 'yyyy-MM-ddThh:mm').time()

def add_talks_from_rss(self, feed_url):
"""Adds talks from an rss feed."""
Expand All @@ -465,7 +483,8 @@ def add_talks_from_rss(self, feed_url):
if presentations:
for presentation in presentations:
# TODO: The presentation['Time'] field should never be None. This can be removed after defaults are
# added and the csv/rss impoters are fixed to handle Date, StartTime, and EndTime.
# added and the rss impoter are fixed to handle Date, StartTime, and EndTime.
# TODO2: Does the code that creates the RSS feeds handle Date, StartTime, and EndTime values?
if not presentation["Time"]:
presentation["Time"] = ''
talk = Presentation(title=presentation["Title"],
Expand All @@ -475,7 +494,7 @@ def add_talks_from_rss(self, feed_url):
event=presentation["Event"],
room=presentation["Room"],
date=QtCore.QDate.fromString(presentation["Time"], QtCore.Qt.ISODate),
startTime=QtCore.QDateTime.fromString(presentation["Time"], 'yyyy-MM-ddThh:mm'))
startTime=QtCore.QDateTime.fromString(presentation["Time"], 'yyyy-MM-ddThh:mm').time().toString('hh:mm ap'))
self.insert_presentation(talk)

else:
Expand All @@ -500,17 +519,17 @@ def add_talks_from_csv(self, fname):
presentation["Event"],
presentation["Room"],
QtCore.QDate.fromString(presentation["Time"], QtCore.Qt.ISODate),
self.isodate_string_to_qtime(presentation["Time"])) # Presentation using legacy time field
self.isodate_string_to_qtime(presentation["Time"]).toString('hh:mm ap')) # Presentation using legacy time field
else:
talk = Presentation(presentation["Title"],
presentation["Speaker"],
presentation["Abstract"], # Description
presentation["Level"],
presentation["Event"],
presentation["Room"],
QtCore.QDate.fromString(presentation["Time"], QtCore.Qt.ISODate),
self.isodate_string_to_qtime(presentation["StartTime"]),
self.isodate_string_to_qtime(presentation["EndTime"]))
QtCore.QDate.fromString(presentation["Date"], QtCore.Qt.ISODate),
QtCore.QTime.fromString(presentation["StartTime"]).toString('hh:mm ap'),
QtCore.QTime.fromString(presentation["EndTime"]).toString('hh:mm ap'))
self.insert_presentation(talk)

else:
Expand Down Expand Up @@ -542,8 +561,8 @@ def export_talks_to_csv(self, fname):
'Event': unicode(result.value(5).toString()),
'Room': unicode(result.value(6).toString()),
'Date': unicode(result.value(7).toDate().toString(QtCore.Qt.ISODate)),
'StartTime': unicode(result.value(8).toDateTime().toString(QtCore.Qt.ISODate)),
'EndTime': unicode(result.value(9).toDateTime().toString(QtCore.Qt.ISODate))})
'StartTime': unicode(QtCore.QTime.fromString(result.value(8).toString(), 'hh:mm ap').toString()),
'EndTime': unicode(QtCore.QTime.fromString(result.value(9).toString(), 'hh:mm ap').toString())})

def export_reports_to_csv(self, fname):
fieldNames = ('Title',
Expand Down
32 changes: 13 additions & 19 deletions src/freeseer/framework/presentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from os import path

from PyQt4.QtCore import QDate
from PyQt4.QtCore import QDateTime
from PyQt4.QtCore import QTime


# TODO: Add a print presentation method? print self.__dict__
Expand All @@ -36,38 +36,32 @@ class Presentation(object):
and its database related operations
'''

# TODO: Are Default variable necessary if they are all empty-string values?
DEFAULT_ROOM = ''
DEFAULT_DATE = ''
DEFAULT_TIME = ''

# TODO: Confirm Presentation.date is or is not a QDate object.
# TODO: Confirm Presentation.startTime should store a QDateTime object or a QTime object.
# TODO: Confirm Presentation.endTime should store a QDateTime object or a QTime object.
def __init__(self, title, speaker='', description='', category='', event='', room='',
date='', startTime='', endTime=''):
'''
Initialize a presentation instance
'''
self.title = title
self.speaker = speaker
self.description = description
self.category = category
self.event = event
self.room = room
self.date = date
self.startTime = startTime
self.endTime = endTime

if not self.room:
self.room = self.DEFAULT_ROOM
self.title = title if title else ''
self.speaker = speaker if speaker else ''
self.description = description if description else ''
self.category = category if category else ''
self.event = event if event else ''
self.room = room if room else ''
self.date = date if date else '' # QDate ISODate format string
self.startTime = startTime if startTime else '' # QTime string with format 'hh:mm ap'
self.endTime = endTime if endTime else '' # QTime string with format 'hh:mm ap'

# Set the date, startTime, or endTime if they are null timestamp values
# occurs when an invalid timestamp is parsed by fromString() for the QDate or QTime object.
if self.date == QDate():
self.date = self.DEFAULT_DATE
if self.startTime == QDateTime():
if self.startTime == QTime():
self.startTime = self.DEFAULT_TIME
if self.endTime == QDateTime():
if self.endTime == QTime():
self.endTime = self.DEFAULT_TIME

def __eq__(self, obj):
Expand Down
3 changes: 0 additions & 3 deletions src/freeseer/frontend/talkeditor/talkeditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,6 @@ def retranslate(self):

def load_presentations_model(self):
# Load Presentation Model
# FIXME: The raw databse values are being loaded into the view. This means the date, startTime, and
# endTime are showing the raw QDate(Time) values. There should be a layer that converts between the
# frontend values and the backend.
self.presentationModel = self.db.get_presentations_model()
self.proxy = QSortFilterProxyModel()
self.proxy.setSourceModel(self.presentationModel)
Expand Down
15 changes: 7 additions & 8 deletions src/freeseer/tests/framework/database/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ def db(tmpdir):
def fake_presentation():
"""Returns a presentation object with fake data. Also demonstrates how to construct time values for presentations"""
today = QtCore.QDate().currentDate() # today
# TODO: The currentDateTime object sets milliseconds. Convert it back to a string then to a QDateTime object again
# to get rid of milliseconds. There has got to be a better solution...
current_time = QtCore.QDateTime.fromString(QtCore.QDateTime().currentDateTime().toString()) # yyyy-mm-ddThh:mm:ss
current_time = QtCore.QTime.fromString(QtCore.QTime.currentTime().toString('hh:mm:ss')) # format removes mseconds
return Presentation(
title='MITM presentation attacks',
speaker='Alice and Eve',
Expand All @@ -51,8 +49,8 @@ def fake_presentation():
event='testing event',
room='1300',
date=today,
startTime=current_time.addSecs(60 * 5),
endTime=current_time.addSecs(60 * 10)
startTime=current_time.addSecs(60 * 5).toString('hh:mm ap'),
endTime=current_time.addSecs(60 * 10).toString('hh:mm ap')
)


Expand All @@ -70,7 +68,7 @@ def presentation_sc2010():
event='Summercamp2010',
room='Rom AB113',
date=QtCore.QDate.fromString('2010-05-14T10:45', QtCore.Qt.ISODate),
startTime=QtCore.QDateTime.fromString('2010-05-14T10:45', 'yyyy-MM-ddThh:mm')
startTime=QtCore.QDateTime.fromString('2010-05-14T10:45', 'yyyy-MM-ddThh:mm').time().toString('hh:mm ap')
)


Expand All @@ -93,7 +91,7 @@ def presentation_sc2011_maxwell_rss():
category='Beginner',
room='',
date=QtCore.QDate.fromString('2011-08-17T20:29', QtCore.Qt.ISODate),
startTime=QtCore.QDateTime.fromString('2011-08-17T20:29', 'yyyy-MM-ddThh:mm')
startTime=QtCore.QDateTime.fromString('2011-08-17T20:29', 'yyyy-MM-ddThh:mm').time().toString('hh:mm ap')
)


Expand All @@ -116,7 +114,8 @@ def presentation_sc2011_maxwell_csv():
category='Beginner',
room='None',
date=QtCore.QDate.fromString('2011-08-17T20:29', QtCore.Qt.ISODate),
startTime=QtCore.QDateTime.fromString('2011-08-17T20:29', 'yyyy-MM-ddThh:mm').time().toString('hh:mm ap')
startTime=QtCore.QDateTime.fromString('2011-08-17T20:29', 'yyyy-MM-ddThh:mm').time().toString('hh:mm ap'),
endTime=''
)


Expand Down
16 changes: 8 additions & 8 deletions src/freeseer/tests/framework/database/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ def helper_presentation_record_to_presentation(query, record):
event=unicode(query.value(record.indexOf('event')).toString()),
room=unicode(query.value(record.indexOf('room')).toString()),
date=query.value(record.indexOf('date')).toDate(),
startTime=query.value(record.indexOf('startTime')).toDateTime(),
endTime=query.value(record.indexOf('endTime')).toDateTime()
startTime=unicode(query.value(record.indexOf('startTime')).toString()),
endTime=unicode(query.value(record.indexOf('endTime')).toString())
)


Expand Down Expand Up @@ -88,11 +88,11 @@ def test_export_talks_to_csv(db, tmpdir):

expected_csv_lines = [
'Title,Speaker,Abstract,Category,Event,Room,Date,StartTime,EndTime\r\n',
'Managing map data in a database,Andrew Ross,,,Default,Default,{},{},{}\r\n'.format(
'Managing map data in a database,Andrew Ross,,,,,{},{},{}\r\n'.format(
Presentation.DEFAULT_DATE, Presentation.DEFAULT_TIME, Presentation.DEFAULT_TIME),
'Building NetBSD,David Maxwell,,,Default,Default,{},{},{}\r\n'.format(
'Building NetBSD,David Maxwell,,,,,{},{},{}\r\n'.format(
Presentation.DEFAULT_DATE, Presentation.DEFAULT_TIME, Presentation.DEFAULT_TIME),
'Faking it till you make it,John Doe,,,Default,Default,{},{},{}\r\n'.format(
'Faking it till you make it,John Doe,,,,,{},{},{}\r\n'.format(
Presentation.DEFAULT_DATE, Presentation.DEFAULT_TIME, Presentation.DEFAULT_TIME)
]

Expand Down Expand Up @@ -233,7 +233,7 @@ def test_get_talks_by_room_and_time(db, fake_presentation):
"""Assert that presentations starting after the current date can be retrieved from the database given a room"""
db.insert_presentation(fake_presentation)
old_presentation = copy.deepcopy(fake_presentation)
old_presentation.startTime = QtCore.QDateTime().addSecs(60 * -100)
old_presentation.startTime = QtCore.QTime().addSecs(60 * -100).toString('hh:mm ap')
db.insert_presentation(old_presentation)

# fake_presentation should be returned because it starts later than the current date.
Expand Down Expand Up @@ -415,8 +415,8 @@ def test_upgrade_database(db, monkeypatch):
event='Winter conference',
room='12',
date=QtCore.QVariant('2002-10-05T00:00').toDate(),
startTime=QtCore.QVariant('2002-10-05T10:45').toDateTime(),
endTime=QtCore.QVariant('2002-10-05T10:45').toDateTime()
startTime=QtCore.QTime.fromString('2002-10-05T10:45', 'yyyy-MM-ddTmm:hh').toString('hh:mm ap'),
endTime=QtCore.QTime.fromString('2002-10-05T10:45', 'yyyy-MM-ddTmm:hh').toString('hh:mm ap')
)

# Mock out the db schema version to a 2x version.
Expand Down
Loading

0 comments on commit 9a42835

Please sign in to comment.