Beispiel #1
0
 def test_client_throws_when_missing_required_fields(self, user_email, user_password):
     with pytest.raises(AssertionError) as err:
         garminUploader = garminClient.GarminClient(user_email, user_password)
     
     if user_email is None or user_email == "":
         assert "email" in str(err.value)
     else:
         assert "password" in str(err.value)
Beispiel #2
0
    def test_uploadActivity_when_auth_fails_throws(self, mocker):
        # Setup
        garminUploader = garminClient.GarminClient("email", "pwd")

        # Act
        with pytest.raises(AssertionError) as err:
            garminUploader.uploadToGarmin(None)

        # Assert
        assert "Failed to authenticate garmin user." in str(err.value)
Beispiel #3
0
    def test_addActivity_adds_activity(self):
        # Setup
        garminUploader = garminClient.GarminClient("email", "pwd")

        # Act
        garminUploader.addActivity("some/path", "someType", "someName01", "someId01")
        garminUploader.addActivity("some/path", "someType", "someName02", "someId02")

        # Assert
        assert len(garminUploader.activities) == 2

        assert garminUploader.activities["someId01"].name == "someName01"
        assert garminUploader.activities["someId02"].name == "someName02"
    def run(config):
        numActivities = config.numActivities
        logger = config.logger
        pelotonClient = pelotonApi.PelotonApi(config.peloton_email,
                                              config.peloton_password)
        database = TinyDB('database.json')
        garminUploadHistoryTable = database.table('garminUploadHistory')

        if config.uploadToGarmin:
            garminUploader = garminClient.GarminClient(config.garmin_email,
                                                       config.garmin_password)
        '''
        Split the main work loop into a two-step approach:
        1. Download the requested number of workouts from Peloton API and saving them to the working directory.
        2. Process all the files in the working directory.  This converts the file to the .TCX format and 
            optionally uploads them to Garmin, as before.
        This enables easier dev/test of the steps independently.  Specifically, by skipping the first step,
        previously saved workout files can be processed without re-downloading them from Peloton.
        '''
        if config.skip_download:
            logger.info("Skipping download of workouts from Peloton!")
            workouts = []
        else:
            if numActivities is None:
                numActivities = input(
                    "How many past activities do you want to grab?  ")
            logger.info("Get latest " + str(numActivities) + " workouts.")
            workouts = pelotonClient.getXWorkouts(numActivities)

        #
        #   Step 1:  Download requested number of workouts to the working_dir directory
        #
        for w in workouts:
            workoutId = w["id"]
            logger.info("Get workout: {}".format(str(workoutId)))

            if w["status"] != "COMPLETE":
                logger.info("Workout status: {} - skipping".format(
                    w["status"]))
                continue

            workout = pelotonClient.getWorkoutById(workoutId)

            # Print basic summary about the workout here, because if we filter out the activity type
            # we won't otherwise see the activity.
            descriptor = tcx_builder.GetWorkoutSummary(workout)
            logger.info(
                "Downloading {workoutId} : {title} ({type}) at {timestamp}".
                format(workoutId=workoutId,
                       title=descriptor['workout_title'],
                       type=descriptor['workout_type'],
                       timestamp=descriptor['workout_started']))

            # Skip the unwanted activities before downloading the rest of the data.
            if config.pelotonWorkoutTypes and not descriptor[
                    "workout_type"] in config.pelotonWorkoutTypes:
                logger.info("Workout type: {type} - skipping".format(
                    type=descriptor['workout_type']))
                continue

            logger.info("Get workout samples")
            workoutSamples = pelotonClient.getWorkoutSamplesById(workoutId)

            logger.info("Get workout summary")
            workoutSummary = pelotonClient.getWorkoutSummaryById(workoutId)

            try:
                filename = tcx_builder.getWorkoutFilename(workout, "json")
                PelotonToGarmin.exportPelotonWorkoutFile(
                    config.working_dir, filename, workout, workoutSamples,
                    workoutSummary)
            except Exception as e:
                logger.error(
                    "Failed to save workout {id} to working directory {dir} - Exception: {ex}"
                    .format(id=workoutId, ex=e, dir=config.working_dir))

        #
        #   Step 2:  Process all files found under working_dir directory
        #
        workoutFiles = PelotonToGarmin.getPelotonWorkoutFiles(
            config.working_dir)
        logger.info("Begin processing {count} workout files.".format(
            count=len(workoutFiles)))
        for workoutFile in workoutFiles:
            workout, workoutSamples, workoutSummary = PelotonToGarmin.importPelotonWorkoutFile(
                workoutFile)
            if not workout:
                continue
            workoutId = workout["id"]

            # Print basic summary about the workout here, because if we filter out the activity type
            # we won't otherwise see the activity.
            descriptor = tcx_builder.GetWorkoutSummary(workout)
            workoutType = descriptor["workout_type"]
            logger.info(
                "Processing {workoutId} : {title} ({type}) at {timestamp}".
                format(workoutId=workoutId,
                       title=descriptor['workout_title'],
                       type=descriptor['workout_type'],
                       timestamp=descriptor['workout_started']))

            if config.pelotonWorkoutTypes and not workoutType in config.pelotonWorkoutTypes:
                logger.info(
                    "Workout type: {type} - skipping".format(type=workoutType))
                continue

            try:
                title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
                    workout, workoutSummary, workoutSamples,
                    config.output_directory)
                logger.info("Wrote TCX file: " + filename)
            except Exception as e:
                logger.error(
                    "Failed to write TCX file for workout {} - Exception: {}".
                    format(workoutId, e))

            # After we are done with the file, optionally copy the file to the archive directory, and/or retain
            # a copy of the file in the working directory.  Otherwise, the working file is deleted (default behavior).
            if config.archive_files:
                archive_dir = config.archive_dir
                if config.archive_by_type:
                    archive_dir += "/" + workoutType
                if not os.path.exists(archive_dir):
                    os.makedirs(archive_dir)
                shutil.copy(workoutFile, archive_dir)
            if not config.retain_files:
                os.remove(workoutFile)

            if config.uploadToGarmin:
                try:
                    uploadItem = Query()
                    workoutAlreadyUploaded = garminUploadHistoryTable.contains(
                        uploadItem.workoutId == workoutId)
                    if workoutAlreadyUploaded:
                        logger.info(
                            "Workout already uploaded to garmin, skipping...")
                        continue

                    logger.info(
                        "Queuing activity for upload: {}".format(title))
                    fileToUpload = config.output_directory + "/" + filename
                    garminUploader.addActivity(fileToUpload,
                                               garmin_activity_type.lower(),
                                               title, workoutId)
                except Exception as e:
                    logger.error(
                        "Failed to queue activity for Garmin upload: {}".
                        format(e))

        if config.uploadToGarmin:
            try:
                logger.info("Uploading activities to Garmin...")
                garminUploader.uploadToGarmin(garminUploadHistoryTable)
            except Exception as e:
                database.close()
                logger.info(
                    "Failed to upload to Garmin. With error: {}".format(e))
                input("Press the <ENTER> key to quit...")
                raise e

        logger.info("Done!")
        logger.info(
            "Your Garmin TCX files can be found in the Output directory: " +
            config.output_directory)

        if config.pause_on_finish:
            input("Press the <ENTER> key to continue...")
    def run(config):
        numActivities = config.numActivities
        logger = config.logger
        pelotonClient = pelotonApi.PelotonApi(config.peloton_email,
                                              config.peloton_password)
        database = TinyDB('database.json')
        garminUploadHistoryTable = database.table('garminUploadHistory')

        if numActivities is None:
            numActivities = input(
                "How many past activities do you want to grab?  ")

        logger.info("Get latest " + str(numActivities) + " workouts.")
        workouts = pelotonClient.getXWorkouts(numActivities)

        if config.uploadToGarmin:
            garminUploader = garminClient.GarminClient(config.garmin_email,
                                                       config.garmin_password)

        for w in workouts:
            workoutId = w["id"]
            logger.info("Get workout: {}".format(str(workoutId)))

            if w["status"] != "COMPLETE":
                logger.info("Workout status: {} - skipping".format(
                    w["status"]))
                continue

            workout = pelotonClient.getWorkoutById(workoutId)

            logger.info("Get workout samples")
            workoutSamples = pelotonClient.getWorkoutSamplesById(workoutId)

            logger.info("Get workout summary")
            workoutSummary = pelotonClient.getWorkoutSummaryById(workoutId)

            try:
                title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
                    workout, workoutSummary, workoutSamples,
                    config.output_directory)
                logger.info("Writing TCX file: " + filename)
            except Exception as e:
                logger.error(
                    "Failed to write TCX file for workout {} - Exception: {}".
                    format(workoutId, e))

            if config.uploadToGarmin:
                try:
                    uploadItem = Query()
                    workoutAlreadyUploaded = garminUploadHistoryTable.contains(
                        uploadItem.workoutId == workoutId)
                    if workoutAlreadyUploaded:
                        logger.info(
                            "Workout already uploaded to garmin, skipping...")
                        continue

                    logger.info("Queing activity for upload: {}".format(title))
                    fileToUpload = config.output_directory + "/" + filename
                    garminUploader.addActivity(fileToUpload,
                                               garmin_activity_type.lower(),
                                               title, workoutId)
                except Exception as e:
                    logger.error(
                        "Failed to queue activity for Garmin upload: {}".
                        format(e))

        if config.uploadToGarmin:
            try:
                logger.info("Uploading activities to Garmin...")
                garminUploader.uploadToGarmin(garminUploadHistoryTable)
            except Exception as e:
                database.close()
                raise e

        logger.info("Done!")
        logger.info(
            "Your Garmin TCX files can be found in the Output directory: " +
            config.output_directory)

        if config.pause_on_finish:
            input("Press the <ENTER> key to continue...")
    def run(config):
        numActivities = config.numActivities
        logger = config.logger
        pelotonClient = pelotonApi.PelotonApi(config.peloton_email,
                                              config.peloton_password)
        database = TinyDB('database.json')
        garminUploadHistoryTable = database.table('garminUploadHistory')

        if numActivities is None:
            numActivities = input(
                "How many past activities do you want to grab?  ")

        logger.info("Get latest " + str(numActivities) + " workouts.")
        workouts = pelotonClient.getXWorkouts(numActivities)

        if config.uploadToGarmin:
            garminUploader = garminClient.GarminClient(config.garmin_email,
                                                       config.garmin_password)

        for w in workouts:
            workoutId = w["id"]
            logger.info("Get workout: {}".format(str(workoutId)))

            if w["status"] != "COMPLETE":
                logger.info("Workout status: {} - skipping".format(
                    w["status"]))
                continue

            workout = pelotonClient.getWorkoutById(workoutId)

            # Print basic summary about the workout here, because if we filter out the activity type
            # we won't otherwise see the activity.
            workoutSummary = tcx_builder.GetWorkoutSummary(workout)
            logger.info("{workoutId} : {title} ({type}) at {timestamp}".format(
                workoutId=workoutId,
                title=workoutSummary['workout_title'],
                type=workoutSummary['workout_type'],
                timestamp=workoutSummary['workout_started']))

            # Skip the unwanted activities before downloading the rest of the data.
            if config.pelotonWorkoutTypes and not workoutSummary[
                    "workout_type"] in config.pelotonWorkoutTypes:
                logger.info("Workout type: {type} - skipping".format(
                    type=workoutSummary['workout_type']))
                continue

            logger.info("Get workout samples")
            workoutSamples = pelotonClient.getWorkoutSamplesById(workoutId)

            logger.info("Get workout summary")
            workoutSummary = pelotonClient.getWorkoutSummaryById(workoutId)

            try:
                title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
                    workout, workoutSummary, workoutSamples,
                    config.output_directory)
                logger.info("Writing TCX file: " + filename)
            except Exception as e:
                logger.error(
                    "Failed to write TCX file for workout {} - Exception: {}".
                    format(workoutId, e))

            if config.uploadToGarmin:
                try:
                    uploadItem = Query()
                    workoutAlreadyUploaded = garminUploadHistoryTable.contains(
                        uploadItem.workoutId == workoutId)
                    if workoutAlreadyUploaded:
                        logger.info(
                            "Workout already uploaded to garmin, skipping...")
                        continue

                    logger.info(
                        "Queuing activity for upload: {}".format(title))
                    fileToUpload = config.output_directory + "/" + filename
                    garminUploader.addActivity(fileToUpload,
                                               garmin_activity_type.lower(),
                                               title, workoutId)
                except Exception as e:
                    logger.error(
                        "Failed to queue activity for Garmin upload: {}".
                        format(e))

        if config.uploadToGarmin:
            try:
                logger.info("Uploading activities to Garmin...")
                garminUploader.uploadToGarmin(garminUploadHistoryTable)
            except Exception as e:
                database.close()
                logger.info(
                    "Failed to upload to Garmin. With error: {}".format(e))
                input("Press the <ENTER> key to quit...")
                raise e

        logger.info("Done!")
        logger.info(
            "Your Garmin TCX files can be found in the Output directory: " +
            config.output_directory)

        if config.pause_on_finish:
            input("Press the <ENTER> key to continue...")