def setUp(self): self.ddbb = DDBB() main = Mock() main.ddbb = self.ddbb main.profile = Profile() main.ddbb.connect() main.ddbb.create_tables(add_default=True) # We need a sport self.uc = UC() self.uc.set_us(False) self.service = ActivityService(pytrainer_main=main) records_table = DeclarativeBase.metadata.tables['records'] self.ddbb.session.execute( records_table.insert({ 'distance': 46.18, 'maxspeed': 44.6695617695, 'maxpace': 1.2, 'title': u'test activity', 'unegative': 564.08076273, 'upositive': 553.05993673, 'average': 22.3882142185, 'date_time_local': u'2016-07-24 12:58:23+0300', 'calories': 1462, 'beats': 115.0, 'comments': u'test comment', 'pace': 2.4, 'date_time_utc': u'2016-07-24T09:58:23Z', 'date': datetime.date(2016, 7, 24), 'duration': 7426, 'sport': 1, 'maxbeats': 120.0 })) laps_table = DeclarativeBase.metadata.tables['laps'] self.ddbb.session.execute( laps_table.insert({ 'distance': 46181.9, 'lap_number': 0, 'calories': 1462, 'elapsed_time': u'7426.0', 'record': 1, 'intensity': u'active', 'avg_hr': 136, 'max_hr': 173, 'laptrigger': u'manual' })) self.activity = self.service.get_activity(1)
def setUp(self): self.ddbb = DDBB() self.ddbb.connect() self.ddbb.create_tables(add_default=True) self.main = mock.Mock() self.main.ddbb = self.ddbb self.main.activitypool = ActivityService(pytrainer_main=self.main) self.main.profile.gpxdir = '/nonexistent' self.record = Record(SportService(self.ddbb), parent=self.main) time = 7426 distance = 46.18 speed = distance * 3600 / time time_hhmmss = [time // 3600, (time / 60) % 60, time % 60] self.summary = {} self.summary['rcd_gpxfile'] = u'/nonexistent' self.summary['rcd_sport'] = u"Run" self.summary['rcd_date'] = u'2016-07-24' self.summary['rcd_calories'] = 1462 self.summary['rcd_comments'] = u'test comment' self.summary['rcd_title'] = u'test 1' self.summary['rcd_time'] = time_hhmmss self.summary['rcd_distance'] = "%0.2f" % distance self.summary['rcd_pace'] = "%d.%02d" % ((3600 / speed) / 60, (3600 / speed) % 60) self.summary['rcd_maxpace'] = "%d.%02d" % ((3600 / 72) / 60, (3600 / 72) % 60) self.summary['rcd_average'] = speed self.summary['rcd_maxvel'] = 72 self.summary['rcd_beats'] = 115.0 self.summary['rcd_maxbeats'] = 120 self.summary['rcd_upositive'] = 553.1 self.summary['rcd_unegative'] = 564.1 self.summary['date_time_local'] = u'2016-07-24 12:58:23+03:00' self.summary['date_time_utc'] = u'2016-07-24T09:58:23Z' self.laps = [{ 'distance': 46181.9, 'lap_number': 0, 'calories': 1462, 'elapsed_time': u'7426.0', 'intensity': u'active', 'avg_hr': 136, 'max_hr': 173, 'laptrigger': u'manual' }]
def setUp(self): self.ddbb = DDBB() main = Mock() main.ddbb = self.ddbb main.profile = Profile() main.ddbb.connect() main.ddbb.create_tables(add_default=True) # We need a sport self.uc = UC() self.uc.set_us(False) self.service = ActivityService(pytrainer_main=main) records_table = DeclarativeBase.metadata.tables['records'] self.ddbb.session.execute(records_table.insert({'distance': 46.18, 'maxspeed': 44.6695617695, 'maxpace': 1.2, 'title': u'test activity', 'unegative': 564.08076273, 'upositive': 553.05993673, 'average': 22.3882142185, 'date_time_local': u'2016-07-24 12:58:23+0300', 'calories': 1462, 'beats': 115.0, 'comments': u'test comment', 'pace': 2.4, 'date_time_utc': u'2016-07-24T09:58:23Z', 'date': datetime.date(2016, 7, 24), 'duration': 7426, 'sport': 1, 'maxbeats': 120.0})) laps_table = DeclarativeBase.metadata.tables['laps'] self.ddbb.session.execute(laps_table.insert({'distance': 46181.9, 'lap_number': 0, 'calories': 1462, 'elapsed_time': u'7426.0', 'record': 1, 'intensity': u'active', 'avg_hr': 136, 'max_hr': 173, 'laptrigger': u'manual'})) self.activity = self.service.get_activity(1)
def __init__(self, filename=None, data_path=None): # Based on Django's approach -> http://code.djangoproject.com/svn/django/trunk/django/__init__.py self.version = __import__('pytrainer').get_version() #Process command line options self.startup_options = self.get_options() #Setup logging self.environment = Environment(self.startup_options.conf_dir, data_path) self.environment.create_directories() self.environment.clear_temp_dir() self.set_logging(self.startup_options.log_level, self.startup_options.log_type) logging.debug('>>') logging.info("pytrainer version %s" % (self.version)) self.data_path = data_path # Checking profile logging.debug('Checking configuration and profile...') self.profile = Profile() # Write the default config to disk self.profile.saveProfile() self.uc = UC() self.profilewindow = None self.ddbb = DDBB(self.profile.sqlalchemy_url) logging.debug('connecting to DDBB') self.ddbb.connect() logging.info('Checking if some upgrade action is needed...') initialize_data(self.ddbb, self.environment.conf_dir) # Loading shared services logging.debug('Loading sport service...') self._sport_service = SportService(self.ddbb) logging.debug('Loading record service...') self.record = Record(self._sport_service, data_path, self) logging.debug('Loading athlete service...') self.athlete = Athlete(data_path, self) logging.debug('Loading stats service...') self.stats = Stats(self) logging.debug('Initializing activity pool...') pool_size = self.profile.getIntValue("pytraining", "activitypool_size", default=1) self.activitypool = ActivityService(self, size=pool_size) #Loading main window self.windowmain = None logging.debug('Loading main window...') self.windowmain = Main(self._sport_service, data_path, self, self.version, gpxDir=self.profile.gpxdir) # Select initial date depending on user's preference self.selectInitialDate() logging.debug('Loading waypoint service...') self.waypoint = WaypointService(data_path, self) logging.debug('Loading extension service...') self.extension = Extension(data_path, self) logging.debug('Loading plugins service...') self.plugins = Plugins(data_path, self) self.importdata = Importdata(self._sport_service, data_path, self, self.profile) logging.debug('Loading plugins...') self.loadPlugins() logging.debug('Loading extensions...') self.loadExtensions() logging.debug('Setting values for graphs, maps and waypoint editor...') self.windowmain.setup() self.windowmain.on_calendar_selected(None) logging.debug('Refreshing sport list... is this needed?') self.refreshMainSportList() logging.debug('Launching main window...') self.windowmain.run() logging.debug('<<')
class pyTrainer: def __init__(self, filename=None, data_path=None): # Based on Django's approach -> http://code.djangoproject.com/svn/django/trunk/django/__init__.py self.version = __import__('pytrainer').get_version() #Process command line options self.startup_options = self.get_options() #Setup logging self.environment = Environment(self.startup_options.conf_dir, data_path) self.environment.create_directories() self.environment.clear_temp_dir() self.set_logging(self.startup_options.log_level, self.startup_options.log_type) logging.debug('>>') logging.info("pytrainer version %s" % (self.version)) self.data_path = data_path # Checking profile logging.debug('Checking configuration and profile...') self.profile = Profile() # Write the default config to disk self.profile.saveProfile() self.uc = UC() self.profilewindow = None self.ddbb = DDBB(self.profile.sqlalchemy_url) logging.debug('connecting to DDBB') self.ddbb.connect() logging.info('Checking if some upgrade action is needed...') initialize_data(self.ddbb, self.environment.conf_dir) # Loading shared services logging.debug('Loading sport service...') self._sport_service = SportService(self.ddbb) logging.debug('Loading record service...') self.record = Record(self._sport_service, data_path, self) logging.debug('Loading athlete service...') self.athlete = Athlete(data_path, self) logging.debug('Loading stats service...') self.stats = Stats(self) logging.debug('Initializing activity pool...') pool_size = self.profile.getIntValue("pytraining", "activitypool_size", default=1) self.activitypool = ActivityService(self, size=pool_size) #Loading main window self.windowmain = None logging.debug('Loading main window...') self.windowmain = Main(self._sport_service, data_path, self, self.version, gpxDir=self.profile.gpxdir) # Select initial date depending on user's preference self.selectInitialDate() logging.debug('Loading waypoint service...') self.waypoint = WaypointService(data_path, self) logging.debug('Loading extension service...') self.extension = Extension(data_path, self) logging.debug('Loading plugins service...') self.plugins = Plugins(data_path, self) self.importdata = Importdata(self._sport_service, data_path, self, self.profile) logging.debug('Loading plugins...') self.loadPlugins() logging.debug('Loading extensions...') self.loadExtensions() logging.debug('Setting values for graphs, maps and waypoint editor...') self.windowmain.setup() self.windowmain.on_calendar_selected(None) logging.debug('Refreshing sport list... is this needed?') self.refreshMainSportList() logging.debug('Launching main window...') self.windowmain.run() logging.debug('<<') def get_options(self): ''' Define usage and accepted options for command line startup returns: options - dict with option: value pairs ''' usage = '''usage: %prog [options] For more help on valid options try: %prog -h ''' parser = OptionParser(usage=usage) parser.set_defaults(log_level=logging.WARNING, validate=False, equip=False, newgraph=True, conf_dir=None, log_type="file") parser.add_option("-d", "--debug", action="store_const", const=logging.DEBUG, dest="log_level", help="enable logging at debug level") parser.add_option("-i", "--info", action="store_const", const=logging.INFO, dest="log_level", help="enable logging at info level") parser.add_option("-w", "--warn", action="store_const", const=logging.WARNING, dest="log_level", help="enable logging at warning level") parser.add_option("--error", action="store_const", const=logging.ERROR, dest="log_level", help="enable logging at error level") parser.add_option( "--valid", action="store_true", dest="validate", help= "enable validation of files imported by plugins (details at info or debug logging level) - note plugin must support validation" ) parser.add_option("--oldgraph", action="store_false", dest="newgraph", help="Turn off new graphing approach") parser.add_option( "--newgraph", action="store_true", dest="newgraph", help="Deprecated Option: Turn on new graphing approach") parser.add_option( "--confdir", dest="conf_dir", help= "Specify the directory where application configuration will be stored." ) parser.add_option( "--logtype", dest="log_type", metavar="TYPE", type="choice", choices=["file", "console"], help= "Specify where logging should be output to. TYPE is one of 'file' (default), or 'console'." ) (options, args) = parser.parse_args() return options def set_logging(self, level, log_type): '''Setup rotating log file with customized format''' if ("console" == log_type): handler = logging.StreamHandler(sys.stdout) else: handler = logging.handlers.RotatingFileHandler( self.environment.log_file, maxBytes=100000, backupCount=5) formatter = logging.Formatter( '%(asctime)s|%(levelname)s|%(module)s|%(funcName)s|%(message)s') handler.setFormatter(formatter) logging.getLogger('').addHandler(handler) self.set_logging_level(self.startup_options.log_level) def set_logging_level(self, level): '''Set level of information written to log''' logging.debug("Setting logger to level: " + str(level)) logging.getLogger('').setLevel(level) logging.getLogger('sqlalchemy.engine').setLevel(level) def quit(self): logging.debug('--') logging.info("Exit!") #self.webservice.stop() self.windowmain.gtk_main_quit() logging.shutdown() sys.exit( ) # Any nonzero value is considered "abnormal termination" by shells and the like def selectInitialDate(self): logging.debug('>>') # self.windowmain.calendar comes from SimpleGladeApp initialisation, not really sure how... :? self.date = Date(self.windowmain.calendar) if self.profile.getValue("pytraining", "prf_startscreen") == "last_entry": logging.info( "User selection is to display last entry in start screen") last_entry_date = self.record.getLastRecordDateString() try: logging.info("Last activity found on %s" % last_entry_date) self.date.setDate(last_entry_date) except: logging.error( "No data available regarding last activity date. Default date will be today" ) logging.debug("Traceback: %s" % traceback.format_exc()) else: logging.info( "User selection is to display current day in start screen") logging.debug('Setting date to %s' % self.date.getDate().strftime("%Y-%m-%d")) logging.debug('<<') def loadPlugins(self): logging.debug('>>') activeplugins = self.plugins.getActivePlugins() if (len(activeplugins) < 1): logging.info("No active plugins") else: for plugin in activeplugins: # From version 1.10 on all file imports are managed via File -> import wizard # Only showing garmintools_full and garmin-hr in 'File' dropdown plugin_name = os.path.basename(plugin) if (plugin_name == "garmintools_full" or plugin_name == "garmin-hr"): txtbutton = self.plugins.loadPlugin(plugin) self.windowmain.addImportPlugin(txtbutton) else: logging.debug( 'From version 1.10 on, file import plugins are managed via File -> Import. Not displaying plugin ' + plugin_name) logging.debug('<<') def loadExtensions(self): logging.debug('>>') activeextensions = self.extension.getActiveExtensions() if (len(activeextensions) < 1): logging.info("No active extensions") else: for extension in activeextensions: txtbutton = self.extension.loadExtension(extension) self.windowmain.addExtension(txtbutton) logging.debug('<<') def runPlugin(self, widget, pathPlugin): logging.debug('>>') self.pluginClass = self.plugins.importClass(pathPlugin) pluginFiles = self.pluginClass.run() if pluginFiles is not None: logging.debug("Plugin returned %d files" % (len(pluginFiles))) #process returned GPX files for (pluginFile, sport) in pluginFiles: if os.path.isfile(pluginFile): logging.info('File exists. Size: %d. Sport: %s' % (os.path.getsize(pluginFile), sport)) if self.record.importFromGPX(pluginFile, sport) is None: logging.error("Error importing file " + pluginFile) else: logging.error('File ' + pluginFile + ' not valid') else: logging.debug("No files returned from Plugin") self.refreshListRecords() self.refreshGraphView("day") logging.debug('<<') def runExtension(self, extension, id): logging.debug('>>') #print("Extension id: %s" % str(id)) activity = self.activitypool.get_activity(id) txtbutton, pathExtension, type = extension self.extensionClass = self.extension.importClass(pathExtension) self.extensionClass.run(id, activity) #if type == "record": # #Si es record le tenemos que crear el googlemaps, el gpx y darle el id de la bbdd # alert = self.extension.runExtension(pathExtension,id) logging.debug('<<') def refreshMainSportList(self): logging.debug('>>') sports = self._sport_service.get_all_sports() self.windowmain.updateSportList(sports) logging.debug('<<') def refreshGraphView(self, view, sport=None): logging.debug('>>') if self.windowmain is None: logging.debug("First call to refreshGraphView") logging.debug('<<') return date_selected = self.date.getDate() if view == "record": logging.debug('record view') if self.windowmain.recordview.get_current_page() == 0: self.refreshRecordGraphView("info") elif self.windowmain.recordview.get_current_page() == 1: self.refreshRecordGraphView("graphs") elif self.windowmain.recordview.get_current_page() == 2: self.refreshRecordGraphView("map") elif self.windowmain.recordview.get_current_page() == 3: self.refreshRecordGraphView("heartrate") elif self.windowmain.recordview.get_current_page() == 4: self.refreshRecordGraphView("analytics") elif view == "day": logging.debug('day view') self.windowmain.actualize_dayview(date_selected) elif view == "week": logging.debug('week view') date_range = DateRange.for_week_containing(date_selected) self.windowmain.actualize_weekview(date_range) elif view == "month": logging.debug('month view') date_range = DateRange.for_month_containing(date_selected) nameMonth, daysInMonth = getNameMonth(date_selected) self.windowmain.actualize_monthview(date_range, nameMonth, daysInMonth) elif view == "year": logging.debug('year view') date_range = DateRange.for_year_containing(date_selected) self.windowmain.actualize_yearview(date_range, date_selected.year) elif view == "listview": logging.debug('list view') self.refreshListView() elif view == "athlete": logging.debug('athlete view') self.windowmain.on_athleteview_activate() elif view == "stats": logging.debug('stats view') self.windowmain.on_statsview_activate() else: print "Unknown view %s" % view logging.debug('<<') def refreshRecordGraphView(self, view, id_record=None): logging.debug('>>') logging.info('Working on ' + view + ' graph') if id_record is not None: #Refresh called for a specific record #Select correct record in treeview model = self.windowmain.recordTreeView.get_model() #Loop through all records in treeview looking for the correct one to highlight for i, row in enumerate(model): if row[0] == id_record: self.windowmain.recordTreeView.set_cursor(i) else: selected, iter = self.windowmain.recordTreeView.get_selection( ).get_selected() if iter: id_record = selected.get_value(iter, 0) else: id_record = None view = "info" activity = self.activitypool.get_activity(id_record) if view == "info": self.windowmain.actualize_recordview(activity) if view == "graphs": self.windowmain.actualize_recordgraph(activity) if view == "map": self.refreshMapView() if view == "heartrate": self.windowmain.actualize_heartrategraph(activity) self.windowmain.actualize_hrview(activity) if view == "analytics": self.windowmain.actualize_analytics(activity) logging.debug('<<') def refreshMapView(self, full_screen=False): logging.debug('>>') if self.windowmain is None: logging.debug('Called before windowmain initialisation') logging.debug('<<') return selected, iter = self.windowmain.recordTreeView.get_selection( ).get_selected() id_record = selected.get_value(iter, 0) activity = self.activitypool.get_activity(id_record) logging.debug('Trying to show map for record ' + str(id_record)) self.windowmain.actualize_map(activity, full_screen) logging.debug('<<') def refreshListRecords(self): logging.debug('>>') #Refresh list records date = self.date.getDate() if self.windowmain.activeSport: sport = self._sport_service.get_sport_by_name( self.windowmain.activeSport) else: sport = None self.windowmain.actualize_recordTreeView(date) #Mark the monthly calendar to show which days have activity? record_list = self.record.getRecordDayList(date, sport) self.windowmain.actualize_calendar(record_list) logging.debug('<<') def refreshAthleteView(self): logging.debug('>>') self.athlete.refresh() self.windowmain.actualize_athleteview(self.athlete) logging.debug('<<') def refreshStatsView(self): logging.debug('>>') self.stats.refresh() self.windowmain.actualize_statsview( self.stats, self.activitypool.get_all_activities()) logging.debug('<<') def refreshListView(self, condition=None): logging.debug('>>') record_list = self.record.getRecordListByCondition(condition) self.windowmain.actualize_listview(record_list) logging.debug('<<') def refreshWaypointView(self, default_waypoint=None, redrawmap=1): logging.debug('>>') waypoint_list = self.waypoint.getAllWaypoints() self.windowmain.actualize_waypointview(waypoint_list, default_waypoint, redrawmap) logging.debug('<<') def editExtensions(self): logging.debug('>>') before = self.extension.getActiveExtensions() self.extension.manageExtensions() after = self.extension.getActiveExtensions() self.setExtensions(before, after) logging.debug('<<') def importData(self): logging.debug('>>') activeplugins_before = self.plugins.getActivePlugins() self.importdata.runImportdata() activeplugins_after = self.plugins.getActivePlugins() #Need to check for plugins that have been disabled (were active and now are not) self.setMenuPlugins(activeplugins_before, activeplugins_after) self.refreshListRecords() self.refreshGraphView(self.windowmain.selected_view) logging.debug('<<') def editGpsPlugins(self): logging.debug('>>') activeplugins_before = self.plugins.getActivePlugins() self.plugins.managePlugins() activeplugins_after = self.plugins.getActivePlugins() #Need to check for plugins that have been disabled (were active and now are not) self.setMenuPlugins(activeplugins_before, activeplugins_after) logging.debug('<<') def setMenuPlugins(self, activeplugins_before, activeplugins_after): logging.debug('>>') #Need to check for plugins that have been disabled (were active and now are not) for plugin in activeplugins_before: if plugin not in activeplugins_after: #disabled plugin -> need to unload plugin txtbutton = self.plugins.loadPlugin(plugin) self.windowmain.removeImportPlugin(txtbutton) #Need to check for plugins that have been enabled (were not active and now are) for plugin in activeplugins_after: if plugin not in activeplugins_before: #new active plugin -> need to load plugin plugin_name = os.path.basename(plugin) if (plugin_name == "garmintools_full" or plugin_name == "garmin-hr"): txtbutton = self.plugins.loadPlugin(plugin) self.windowmain.addImportPlugin(txtbutton) else: logging.debug( 'From version 1.10 on file import plugins are managed via File -> Import. Not displaying plugin ' + plugin_name) logging.debug('<<') def setExtensions(self, before, after): logging.debug('>>') #Need to check for extensions that have been disabled (were active and now are not) for extension in before: if extension not in after: #disabled extension -> need to unload extension print "Need to disable extension %s " % extension txtbutton = self.extension.loadExtension(extension) self.windowmain.removeExtension(txtbutton) #Need to check for plugins that have been enabled (were not active and now are) for extension in after: if extension not in before: #new active extension -> need to load extension logging.debug("Enabling extension %s " % extension) txtbutton = self.extension.loadExtension(extension) self.windowmain.addExtension(txtbutton) logging.debug('<<') def newRecord(self, title=None, distance=None, time=None, upositive=None, unegative=None, bpm=None, calories=None, comment=None, view=None): logging.debug('>>') date = self.date.getDate() self.record.newRecord(date, title, distance, time, upositive, unegative, bpm, calories, comment) self.refreshListRecords() if view is not None: self.refreshGraphView(view) logging.debug('<<') def editRecord(self, id_record, view=None): logging.debug("Editing record with id: '%s'", id_record) self.record.editRecord(id_record) self.refreshListRecords() if view is not None: self.refreshGraphView(view) logging.debug('<<') def removeRecord(self, id_record, confirm=False, view=None): logging.debug('>>') if confirm: activity = self.activitypool.get_activity(id_record) self.activitypool.remove_activity_from_db(activity) else: msg = _("Delete this database entry?") params = [id_record, True] warning = Warning(self.data_path, self.removeRecord, params) warning.set_text(msg) warning.run() self.refreshListRecords() if view is not None: self.refreshGraphView(view) logging.debug('<<') def removeWaypoint(self, id_waypoint, confirm=False): logging.debug('>>') if confirm: self.waypoint.removeWaypoint(id_waypoint) self.refreshWaypointView() else: msg = _("Delete this waypoint?") params = [id_waypoint, True] warning = Warning(self.data_path, self.removeWaypoint, params) warning.set_text(msg) warning.run() logging.debug('<<') def updateWaypoint(self, id_waypoint, lat, lon, name, desc, sym): logging.debug('>>') self.waypoint.updateWaypoint(id_waypoint, lat, lon, name, desc, sym) self.refreshWaypointView(id_waypoint) logging.debug('<<') def exportCsv(self): logging.debug('>>') from save import Save save = Save(self.data_path, self.record) save.run() logging.debug('<<') def editProfile(self): logging.debug('>>') from gui.windowprofile import WindowProfile self.profile.refreshConfiguration() if self.profilewindow is None: self.profilewindow = WindowProfile(self._sport_service, self.data_path, self.profile, pytrainer_main=self) logging.debug("setting data values") self.profilewindow.setValues(self.profile.configuration) self.profilewindow.run() self.profilewindow = None else: self.profilewindow.setValues(self.profile.configuration) self.profilewindow.present() self.profile.refreshConfiguration() self.activitypool.clear_pool() self.windowmain.setup() logging.debug('<<')
class ActivityTest(unittest.TestCase): def setUp(self): self.ddbb = DDBB() main = Mock() main.ddbb = self.ddbb main.profile = Profile() main.ddbb.connect() main.ddbb.create_tables(add_default=True) # We need a sport self.uc = UC() self.uc.set_us(False) self.service = ActivityService(pytrainer_main=main) records_table = DeclarativeBase.metadata.tables['records'] self.ddbb.session.execute(records_table.insert({'distance': 46.18, 'maxspeed': 44.6695617695, 'maxpace': 1.2, 'title': u'test activity', 'unegative': 564.08076273, 'upositive': 553.05993673, 'average': 22.3882142185, 'date_time_local': u'2016-07-24 12:58:23+0300', 'calories': 1462, 'beats': 115.0, 'comments': u'test comment', 'pace': 2.4, 'date_time_utc': u'2016-07-24T09:58:23Z', 'date': datetime.date(2016, 7, 24), 'duration': 7426, 'sport': 1, 'maxbeats': 120.0})) laps_table = DeclarativeBase.metadata.tables['laps'] self.ddbb.session.execute(laps_table.insert({'distance': 46181.9, 'lap_number': 0, 'calories': 1462, 'elapsed_time': u'7426.0', 'record': 1, 'intensity': u'active', 'avg_hr': 136, 'max_hr': 173, 'laptrigger': u'manual'})) self.activity = self.service.get_activity(1) def tearDown(self): self.service.clear_pool() self.ddbb.disconnect() self.ddbb.drop_tables() self.uc.set_us(False) def test_activity_date_time(self): self.assertEqual(self.activity.date_time, datetime.datetime(2016, 7, 24, 12, 58, 23, tzinfo=tzoffset(None, 10800))) def test_activity_distance(self): self.assertEqual(self.activity.distance, 46.18) def test_activity_sport_name(self): self.assertEqual(self.activity.sport_name, 'Mountain Bike') def test_activity_duration(self): self.assertEqual(self.activity.duration, 7426) def test_activity_time(self): self.assertEqual(self.activity.time, self.activity.duration) def test_activity_starttime(self): self.assertEqual(self.activity.starttime, '12:58:23 PM') def test_activity_time_tuple(self): self.assertEqual(self.activity.time_tuple, (2, 3, 46)) def test_activity_lap(self): self.maxDiff = None self.assertEqual(self.activity.laps[0], {'distance': 46181.9, 'end_lon': None, 'lap_number': 0, 'start_lon': None, 'id_lap': 1, 'calories': 1462, 'comments': None, 'laptrigger': u'manual', 'elapsed_time': u'7426.0', 'record': 1, 'intensity': u'active', 'avg_hr': 136, 'max_hr': 173, 'end_lat': None, 'start_lat': None, 'max_speed': None}) lap = self.activity.Laps[0] self.assertEqual(lap.distance, 46181.9) self.assertEqual(lap.duration, 7426.0) self.assertEqual(lap.calories, 1462) self.assertEqual(lap.avg_hr, 136) self.assertEqual(lap.max_hr, 173) self.assertEqual(lap.activity, self.activity) self.assertEqual(lap.lap_number, 0) self.assertEqual(lap.intensity, u'active') self.assertEqual(lap.laptrigger, u'manual') def test_activity_get_value_f(self): self.assertEqual(self.activity.get_value_f('distance', "%0.2f"), '46.18') self.assertEqual(self.activity.get_value_f('average', "%0.2f"), '22.39') self.assertEqual(self.activity.get_value_f('maxspeed', "%0.2f"), '44.67') self.assertEqual(self.activity.get_value_f('time', '%s'), '2:03:46') self.assertEqual(self.activity.get_value_f('calories', "%0.0f"), '1462') self.assertEqual(self.activity.get_value_f('pace', "%s"), '2:24') self.assertEqual(self.activity.get_value_f('maxpace', "%s"), '1:12') self.assertEqual(self.activity.get_value_f('upositive', "%0.2f"), '553.06') self.assertEqual(self.activity.get_value_f('unegative', "%0.2f"), '564.08') def test_activity_get_value_f_us(self): self.uc.set_us(True) self.assertEqual(self.activity.get_value_f('distance', "%0.2f"), '28.69') self.assertEqual(self.activity.get_value_f('average', "%0.2f"), '13.91') self.assertEqual(self.activity.get_value_f('maxspeed', "%0.2f"), '27.76') self.assertEqual(self.activity.get_value_f('time', '%s'), '2:03:46') self.assertEqual(self.activity.get_value_f('calories', "%0.0f"), '1462') self.assertEqual(self.activity.get_value_f('pace', "%s"), '3:52') self.assertEqual(self.activity.get_value_f('maxpace', "%s"), '1:56') self.assertEqual(self.activity.get_value_f('upositive', "%0.2f"), '1814.50') self.assertEqual(self.activity.get_value_f('unegative', "%0.2f"), '1850.66') def test_activity_service_null(self): none_activity = self.service.get_activity(None) self.assertIsNone(none_activity.id) def test_activity_remove(self): self.service.remove_activity_from_db(self.activity) try: self.service.get_activity(1) except NoResultFound: pass else: self.fail() def test_activities_for_day(self): activity = list(self.service.get_activities_for_day(datetime.date(2016, 7, 24)))[0] self.assertEqual(self.activity, activity) def test_activities_period(self): activity = list(self.service.get_activities_period(DateRange.for_week_containing(datetime.date(2016, 7, 24))))[0] self.assertEqual(self.activity, activity) def test_all_activities(self): activity = list(self.service.get_all_activities())[0] self.assertEqual(self.activity, activity)
def __init__(self,filename = None, data_path = None): # Based on Django's approach -> http://code.djangoproject.com/svn/django/trunk/django/__init__.py self.version = __import__('pytrainer').get_version() #Process command line options self.startup_options = self.get_options() #Setup logging self.environment = Environment(self.startup_options.conf_dir, data_path) self.environment.create_directories() self.environment.clear_temp_dir() self.set_logging(self.startup_options.log_level, self.startup_options.log_type) logging.debug('>>') logging.info("pytrainer version %s" % (self.version)) self.data_path = data_path # Checking profile logging.debug('Checking configuration and profile...') self.profile = Profile() # Write the default config to disk self.profile.saveProfile() self.uc = UC() self.profilewindow = None self.ddbb = DDBB(self.profile.sqlalchemy_url) logging.debug('connecting to DDBB') self.ddbb.connect() logging.info('Checking if some upgrade action is needed...') initialize_data(self.ddbb, self.environment.conf_dir) # Loading shared services logging.debug('Loading sport service...') self._sport_service = SportService(self.ddbb) logging.debug('Loading record service...') self.record = Record(self._sport_service, data_path, self) logging.debug('Loading athlete service...') self.athlete = Athlete(data_path, self) logging.debug('Loading stats service...') self.stats = Stats(self) logging.debug('Initializing activity pool...') pool_size = self.profile.getIntValue("pytraining","activitypool_size", default=1) self.activitypool = ActivityService(self, size=pool_size) #Loading main window self.windowmain = None logging.debug('Loading main window...') self.windowmain = Main(self._sport_service, data_path,self,self.version, gpxDir=self.profile.gpxdir) # Select initial date depending on user's preference self.selectInitialDate() logging.debug('Loading waypoint service...') self.waypoint = WaypointService(data_path, self) logging.debug('Loading extension service...') self.extension = Extension(data_path, self) logging.debug('Loading plugins service...') self.plugins = Plugins(data_path, self) self.importdata = Importdata(self._sport_service, data_path, self, self.profile) logging.debug('Loading plugins...') self.loadPlugins() logging.debug('Loading extensions...') self.loadExtensions() logging.debug('Setting values for graphs, maps and waypoint editor...') self.windowmain.setup() self.windowmain.on_calendar_selected(None) logging.debug('Refreshing sport list... is this needed?') self.refreshMainSportList() logging.debug('Launching main window...') self.windowmain.run() logging.debug('<<')
class pyTrainer: def __init__(self,filename = None, data_path = None): # Based on Django's approach -> http://code.djangoproject.com/svn/django/trunk/django/__init__.py self.version = __import__('pytrainer').get_version() #Process command line options self.startup_options = self.get_options() #Setup logging self.environment = Environment(self.startup_options.conf_dir, data_path) self.environment.create_directories() self.environment.clear_temp_dir() self.set_logging(self.startup_options.log_level, self.startup_options.log_type) logging.debug('>>') logging.info("pytrainer version %s" % (self.version)) self.data_path = data_path # Checking profile logging.debug('Checking configuration and profile...') self.profile = Profile() # Write the default config to disk self.profile.saveProfile() self.uc = UC() self.profilewindow = None self.ddbb = DDBB(self.profile.sqlalchemy_url) logging.debug('connecting to DDBB') self.ddbb.connect() logging.info('Checking if some upgrade action is needed...') initialize_data(self.ddbb, self.environment.conf_dir) # Loading shared services logging.debug('Loading sport service...') self._sport_service = SportService(self.ddbb) logging.debug('Loading record service...') self.record = Record(self._sport_service, data_path, self) logging.debug('Loading athlete service...') self.athlete = Athlete(data_path, self) logging.debug('Loading stats service...') self.stats = Stats(self) logging.debug('Initializing activity pool...') pool_size = self.profile.getIntValue("pytraining","activitypool_size", default=1) self.activitypool = ActivityService(self, size=pool_size) #Loading main window self.windowmain = None logging.debug('Loading main window...') self.windowmain = Main(self._sport_service, data_path,self,self.version, gpxDir=self.profile.gpxdir) # Select initial date depending on user's preference self.selectInitialDate() logging.debug('Loading waypoint service...') self.waypoint = WaypointService(data_path, self) logging.debug('Loading extension service...') self.extension = Extension(data_path, self) logging.debug('Loading plugins service...') self.plugins = Plugins(data_path, self) self.importdata = Importdata(self._sport_service, data_path, self, self.profile) logging.debug('Loading plugins...') self.loadPlugins() logging.debug('Loading extensions...') self.loadExtensions() logging.debug('Setting values for graphs, maps and waypoint editor...') self.windowmain.setup() self.windowmain.on_calendar_selected(None) logging.debug('Refreshing sport list... is this needed?') self.refreshMainSportList() logging.debug('Launching main window...') self.windowmain.run() logging.debug('<<') def get_options(self): ''' Define usage and accepted options for command line startup returns: options - dict with option: value pairs ''' usage = '''usage: %prog [options] For more help on valid options try: %prog -h ''' parser = OptionParser(usage=usage) parser.set_defaults(log_level=logging.WARNING, validate=False, equip=False, newgraph=True, conf_dir=None, log_type="file") parser.add_option("-d", "--debug", action="store_const", const=logging.DEBUG, dest="log_level", help="enable logging at debug level") parser.add_option("-i", "--info", action="store_const", const=logging.INFO, dest="log_level", help="enable logging at info level") parser.add_option("-w", "--warn", action="store_const", const=logging.WARNING, dest="log_level", help="enable logging at warning level") parser.add_option("--error", action="store_const", const=logging.ERROR, dest="log_level", help="enable logging at error level") parser.add_option("--valid", action="store_true", dest="validate", help="enable validation of files imported by plugins (details at info or debug logging level) - note plugin must support validation") parser.add_option("--oldgraph", action="store_false", dest="newgraph", help="Turn off new graphing approach") parser.add_option("--newgraph", action="store_true", dest="newgraph", help="Deprecated Option: Turn on new graphing approach") parser.add_option("--confdir", dest="conf_dir", help="Specify the directory where application configuration will be stored.") parser.add_option("--logtype", dest="log_type", metavar="TYPE", type="choice" , choices=["file", "console"], help="Specify where logging should be output to. TYPE is one of 'file' (default), or 'console'.") (options, args) = parser.parse_args() return options def set_logging(self, level, log_type): '''Setup rotating log file with customized format''' logging.captureWarnings(True) if("console" == log_type): handler = logging.StreamHandler(sys.stdout) else: handler = logging.handlers.RotatingFileHandler(self.environment.log_file, maxBytes=100000, backupCount=5) formatter = logging.Formatter('%(asctime)s|%(levelname)s|%(module)s|%(funcName)s|%(message)s') handler.setFormatter(formatter) logging.getLogger('').addHandler(handler) self.set_logging_level(self.startup_options.log_level) def set_logging_level(self, level): '''Set level of information written to log''' logging.debug("Setting logger to level: %s", level) logging.getLogger('').setLevel(level) logging.getLogger('sqlalchemy.engine').setLevel(level) def quit(self): logging.debug('--') logging.info("Exit!") #self.webservice.stop() self.windowmain.gtk_main_quit() logging.shutdown() sys.exit() # Any nonzero value is considered "abnormal termination" by shells and the like def selectInitialDate(self): logging.debug('>>') # self.windowmain.calendar comes from SimpleGladeApp initialisation, not really sure how... :? self.date = Date(self.windowmain.calendar) if self.profile.getValue("pytraining","prf_startscreen") == "last_entry": logging.info("User selection is to display last entry in start screen") last_entry_date = self.record.getLastRecordDateString() try: logging.info("Last activity found on %s" %last_entry_date) self.date.setDate(last_entry_date) except: logging.error("No data available regarding last activity date. Default date will be today") logging.debug("Traceback: %s" % traceback.format_exc()) else: logging.info("User selection is to display current day in start screen") logging.debug('Setting date to %s' % self.date.getDate().strftime("%Y-%m-%d")) logging.debug('<<') def loadPlugins(self): logging.debug('>>') activeplugins = self.plugins.getActivePlugins() if (len(activeplugins)<1): logging.info("No active plugins") else: for plugin in activeplugins: # From version 1.10 on all file imports are managed via File -> import wizard # Only showing garmintools_full and garmin-hr in 'File' dropdown plugin_name = os.path.basename(plugin) if (plugin_name == "garmintools_full" or plugin_name == "garmin-hr"): warnings.warn('Attempted to enable an unsupported plugin %s' % plugin_name, UserWarning) else: logging.debug('From version 1.10 on, file import plugins are managed via File -> Import. Not displaying plugin ' + plugin_name) logging.debug('<<') def loadExtensions(self): logging.debug('>>') activeextensions = self.extension.getActiveExtensions() if (len(activeextensions)<1): logging.info("No active extensions") else: for extension in activeextensions: txtbutton = self.extension.loadExtension(extension) self.windowmain.addExtension(txtbutton) logging.debug('<<') def runPlugin(self,widget,pathPlugin): logging.debug('>>') self.pluginClass = self.plugins.importClass(pathPlugin) pluginFiles = self.pluginClass.run() if pluginFiles is not None: logging.debug("Plugin returned %d files" % (len(pluginFiles)) ) #process returned GPX files for (pluginFile, sport) in pluginFiles: if os.path.isfile(pluginFile): logging.info('File exists. Size: %d. Sport: %s' % (os.path.getsize(pluginFile), sport)) if self.record.importFromGPX(pluginFile, sport) is None: logging.error("Error importing file "+pluginFile) else: logging.error('File '+pluginFile+' not valid') else: logging.debug("No files returned from Plugin") self.refreshListRecords() self.refreshGraphView("day") logging.debug('<<') def runExtension(self,extension,id): logging.debug('>>') #print("Extension id: %s" % str(id)) activity = self.activitypool.get_activity(id) txtbutton,pathExtension,type = extension self.extensionClass = self.extension.importClass(pathExtension) self.extensionClass.run(id, activity) #if type == "record": # #Si es record le tenemos que crear el googlemaps, el gpx y darle el id de la bbdd # alert = self.extension.runExtension(pathExtension,id) logging.debug('<<') def refreshMainSportList(self): logging.debug('>>') sports = self._sport_service.get_all_sports() self.windowmain.updateSportList(sports) logging.debug('<<') def refreshGraphView(self, view, sport=None): logging.debug('>>') if self.windowmain is None: logging.debug("First call to refreshGraphView") logging.debug('<<') return date_selected = self.date.getDate() if view=="record": logging.debug('record view') if self.windowmain.recordview.get_current_page()==0: self.refreshRecordGraphView("info") elif self.windowmain.recordview.get_current_page()==1: self.refreshRecordGraphView("graphs") elif self.windowmain.recordview.get_current_page()==2: self.refreshRecordGraphView("map") elif self.windowmain.recordview.get_current_page()==3: self.refreshRecordGraphView("heartrate") elif self.windowmain.recordview.get_current_page()==4: self.refreshRecordGraphView("analytics") elif view=="day": logging.debug('day view') self.windowmain.actualize_dayview(date_selected) elif view=="week": logging.debug('week view') date_range = DateRange.for_week_containing(date_selected) self.windowmain.actualize_weekview(date_range) elif view=="month": logging.debug('month view') date_range = DateRange.for_month_containing(date_selected) nameMonth, daysInMonth = getNameMonth(date_selected) self.windowmain.actualize_monthview(date_range, nameMonth, daysInMonth) elif view=="year": logging.debug('year view') date_range = DateRange.for_year_containing(date_selected) self.windowmain.actualize_yearview(date_range, date_selected.year) elif view=="listview": logging.debug('list view') self.refreshListView() elif view=="athlete": logging.debug('athlete view') self.windowmain.on_athleteview_activate() elif view=="stats": logging.debug('stats view') self.windowmain.on_statsview_activate() else: logging.error("Unknown view %s", view) logging.debug('<<') def refreshRecordGraphView(self, view, id_record=None): logging.debug('>>') logging.info('Working on '+view+' graph') if id_record is not None: #Refresh called for a specific record #Select correct record in treeview model = self.windowmain.recordTreeView.get_model() #Loop through all records in treeview looking for the correct one to highlight for i,row in enumerate(model): if row[0] == id_record: self.windowmain.recordTreeView.set_cursor(i) else: selected,iter = self.windowmain.recordTreeView.get_selection().get_selected() if iter: id_record = selected.get_value(iter,0) else: id_record = None view="info" activity = self.activitypool.get_activity(id_record) if view=="info": self.windowmain.actualize_recordview(activity) if view=="graphs": self.windowmain.actualize_recordgraph(activity) if view=="map": self.refreshMapView() if view=="heartrate": self.windowmain.actualize_heartrategraph(activity) self.windowmain.actualize_hrview(activity) if view=="analytics": self.windowmain.actualize_analytics(activity) logging.debug('<<') def refreshMapView(self, full_screen=False): logging.debug('>>') if self.windowmain is None: logging.debug('Called before windowmain initialisation') logging.debug('<<') return selected,iter = self.windowmain.recordTreeView.get_selection().get_selected() id_record = selected.get_value(iter,0) activity = self.activitypool.get_activity(id_record) logging.debug('Trying to show map for record %s', id_record) self.windowmain.actualize_map(activity, full_screen) logging.debug('<<') def refreshListRecords(self): logging.debug('>>') #Refresh list records date = self.date.getDate() if self.windowmain.activeSport: sport = self._sport_service.get_sport_by_name(self.windowmain.activeSport) else: sport = None self.windowmain.actualize_recordTreeView(date) #Mark the monthly calendar to show which days have activity? record_list = self.record.getRecordDayList(date, sport) self.windowmain.actualize_calendar(record_list) logging.debug('<<') def refreshAthleteView(self): logging.debug('>>') self.athlete.refresh() self.windowmain.actualize_athleteview(self.athlete) logging.debug('<<') def refreshStatsView(self): logging.debug('>>') self.stats.refresh() self.windowmain.actualize_statsview(self.stats, self.activitypool.get_all_activities()) logging.debug('<<') def refreshListView(self,condition=None): logging.debug('>>') record_list = self.record.getRecordListByCondition(condition) self.windowmain.actualize_listview(record_list) logging.debug('<<') def refreshWaypointView(self,default_waypoint=None,redrawmap=1): logging.debug('>>') waypoint_list = self.waypoint.getAllWaypoints() self.windowmain.actualize_waypointview(waypoint_list,default_waypoint,redrawmap) logging.debug('<<') def editExtensions(self): logging.debug('>>') before = self.extension.getActiveExtensions() self.extension.manageExtensions() after = self.extension.getActiveExtensions() self.setExtensions(before, after) logging.debug('<<') def importData(self): logging.debug('>>') activeplugins_before = self.plugins.getActivePlugins() self.importdata.runImportdata() activeplugins_after = self.plugins.getActivePlugins() #Need to check for plugins that have been disabled (were active and now are not) self.setMenuPlugins(activeplugins_before, activeplugins_after) self.refreshListRecords() self.refreshGraphView(self.windowmain.selected_view) logging.debug('<<') def editGpsPlugins(self): logging.debug('>>') activeplugins_before = self.plugins.getActivePlugins() self.plugins.managePlugins() activeplugins_after = self.plugins.getActivePlugins() #Need to check for plugins that have been disabled (were active and now are not) self.setMenuPlugins(activeplugins_before, activeplugins_after) logging.debug('<<') def setMenuPlugins(self, activeplugins_before, activeplugins_after): logging.debug('>>') #Need to check for plugins that have been disabled (were active and now are not) for plugin in activeplugins_before: if plugin not in activeplugins_after: #disabled plugin -> need to unload plugin txtbutton = self.plugins.loadPlugin(plugin) self.windowmain.removeImportPlugin(txtbutton) #Need to check for plugins that have been enabled (were not active and now are) for plugin in activeplugins_after: if plugin not in activeplugins_before: #new active plugin -> need to load plugin plugin_name = os.path.basename(plugin) if (plugin_name == "garmintools_full" or plugin_name == "garmin-hr"): warnings.warn('Attempted to enable an unsupported plugin %s' % plugin_name, UserWarning) else: logging.debug('From version 1.10 on file import plugins are managed via File -> Import. Not displaying plugin ' + plugin_name) logging.debug('<<') def setExtensions(self, before, after): logging.debug('>>') #Need to check for extensions that have been disabled (were active and now are not) for extension in before: if extension not in after: #disabled extension -> need to unload extension logging.error("Need to disable extension %s", extension) txtbutton = self.extension.loadExtension(extension) self.windowmain.removeExtension(txtbutton) #Need to check for plugins that have been enabled (were not active and now are) for extension in after: if extension not in before: #new active extension -> need to load extension logging.debug("Enabling extension %s " % extension) txtbutton = self.extension.loadExtension(extension) self.windowmain.addExtension(txtbutton) logging.debug('<<') def newRecord(self,title=None,distance=None,time=None,upositive=None,unegative=None,bpm=None,calories=None,comment=None,view=None): logging.debug('>>') date = self.date.getDate() self.record.newRecord(date, title, distance, time, upositive, unegative, bpm, calories, comment) self.refreshListRecords() if view is not None: self.refreshGraphView(view) logging.debug('<<') def editRecord(self, id_record, view=None): logging.debug("Editing record with id: '%s'", id_record) self.record.editRecord(id_record) self.refreshListRecords() if view is not None: self.refreshGraphView(view) logging.debug('<<') def removeRecord(self, id_record, confirm = False, view=None): logging.debug('>>') if confirm: activity = self.activitypool.get_activity(id_record) self.activitypool.remove_activity_from_db(activity) else: msg = _("Delete this database entry?") params = [id_record,True] warning = Warning(self.data_path,self.removeRecord,params) warning.set_text(msg) warning.run() self.refreshListRecords() if view is not None: self.refreshGraphView(view) logging.debug('<<') def removeWaypoint(self,id_waypoint, confirm = False): logging.debug('>>') if confirm: self.waypoint.removeWaypoint(id_waypoint) self.refreshWaypointView() else: msg = _("Delete this waypoint?") params = [id_waypoint,True] warning = Warning(self.data_path,self.removeWaypoint,params) warning.set_text(msg) warning.run() logging.debug('<<') def updateWaypoint(self,id_waypoint,lat,lon,name,desc,sym): logging.debug('>>') self.waypoint.updateWaypoint(id_waypoint,lat,lon,name,desc,sym) self.refreshWaypointView(id_waypoint) logging.debug('<<') def exportCsv(self): logging.debug('>>') from .save import Save save = Save(self.data_path, self.record) save.run() logging.debug('<<') def editProfile(self): logging.debug('>>') from .gui.windowprofile import WindowProfile self.profile.refreshConfiguration() if self.profilewindow is None: self.profilewindow = WindowProfile(self._sport_service, self.data_path, self.profile, pytrainer_main=self) logging.debug("setting data values") self.profilewindow.setValues(self.profile.configuration) self.profilewindow.run() self.profilewindow = None else: self.profilewindow.setValues(self.profile.configuration) self.profilewindow.present() self.profile.refreshConfiguration() self.activitypool.clear_pool() self.windowmain.setup() logging.debug('<<')