diff --git a/freezing/sync/autolog.py b/freezing/sync/autolog.py index 050c33b..0bf093d 100644 --- a/freezing/sync/autolog.py +++ b/freezing/sync/autolog.py @@ -64,7 +64,10 @@ def _getUnterpolatedMessage(self, msg, args): # by casting the left side (the "msg" variable) in this context # to unicode. So we'll do that here - if sys.version_info >= (3, 0,): + if sys.version_info >= ( + 3, + 0, + ): # this is most likely unnecessary on python 3, but it's here # for completeness, in the case of someone manually creating # a bytestring @@ -213,7 +216,7 @@ def __getattr__(self, name): def log_exceptions(fn): - """ A decorator designed to wrap a function and log any exception that method produces. + """A decorator designed to wrap a function and log any exception that method produces. The exception will still be raised after being logged. diff --git a/freezing/sync/cli/sync_activities.py b/freezing/sync/cli/sync_activities.py index 40f2dd5..c70186e 100644 --- a/freezing/sync/cli/sync_activities.py +++ b/freezing/sync/cli/sync_activities.py @@ -57,7 +57,6 @@ def build_parser(self): return parser def execute(self, args): - fetcher = ActivitySync(logger=self.logger) fetcher.sync_rides( start_date=args.start_date, diff --git a/freezing/sync/cli/sync_details.py b/freezing/sync/cli/sync_details.py index ee304a6..62a79e4 100644 --- a/freezing/sync/cli/sync_details.py +++ b/freezing/sync/cli/sync_details.py @@ -3,7 +3,6 @@ class SyncActivityDetails(BaseCommand): - name = "sync-activity-detail" description = "Sync the activity details JSON." diff --git a/freezing/sync/cli/sync_photos.py b/freezing/sync/cli/sync_photos.py index 6f7e5c0..619df42 100644 --- a/freezing/sync/cli/sync_photos.py +++ b/freezing/sync/cli/sync_photos.py @@ -4,12 +4,10 @@ class SyncPhotosScript(BaseCommand): - name = "sync-photos" description = "Sync ride photos." def execute(self, args): - fetcher = PhotoSync() fetcher.sync_photos() diff --git a/freezing/sync/config.py b/freezing/sync/config.py index b6c54b2..ddcbe29 100644 --- a/freezing/sync/config.py +++ b/freezing/sync/config.py @@ -19,7 +19,6 @@ class Config: - DEBUG = env("DEBUG") # type: bool SQLALCHEMY_URL = env("SQLALCHEMY_URL") BEANSTALKD_HOST = env("BEANSTALKD_HOST", default="localhost") @@ -32,7 +31,9 @@ class Config: ) VISUAL_CROSSING_API_KEY = env("VISUAL_CROSSING_API_KEY") - VISUAL_CROSSING_CACHE_DIR = env("VISUAL_CROSSING_CACHE_DIR", default="/data/cache/weather") + VISUAL_CROSSING_CACHE_DIR = env( + "VISUAL_CROSSING_CACHE_DIR", default="/data/cache/weather" + ) COMPETITION_TEAMS = env("TEAMS", cast=list, subcast=int, default=[]) OBSERVER_TEAMS = env("OBSERVER_TEAMS", cast=list, subcast=int, default=[]) diff --git a/freezing/sync/data/__init__.py b/freezing/sync/data/__init__.py index b7357ff..b3448ff 100644 --- a/freezing/sync/data/__init__.py +++ b/freezing/sync/data/__init__.py @@ -16,7 +16,9 @@ class StravaClientForAthlete(Client): """ def __init__( - self, athlete: Union[int, Athlete], logger: logging.Logger = None, + self, + athlete: Union[int, Athlete], + logger: logging.Logger = None, ): self.logger = logger or logging.getLogger(__name__) assert athlete, "No athlete ID or Athlete object provided." @@ -49,7 +51,8 @@ def refresh_access_token(self, athlete: Athlete): # Access token is still valid - no action needed refresh_token = None self.logger.info( - "access token for athlete %s is still valid ", athlete.id, + "access token for athlete %s is still valid ", + athlete.id, ) elif athlete.access_token is not None: # Athlete has an access token but no refresh token yet. @@ -63,7 +66,9 @@ def refresh_access_token(self, athlete: Athlete): if refresh_token: self.logger.info("saving refresh token for athlete %s", athlete.id) token_dict = super().refresh_access_token( - Config.STRAVA_CLIENT_ID, Config.STRAVA_CLIENT_SECRET, refresh_token, + Config.STRAVA_CLIENT_ID, + Config.STRAVA_CLIENT_SECRET, + refresh_token, ) self.access_token = token_dict["access_token"] athlete.access_token = token_dict["access_token"] diff --git a/freezing/sync/data/activity.py b/freezing/sync/data/activity.py index 89ae36a..712d485 100644 --- a/freezing/sync/data/activity.py +++ b/freezing/sync/data/activity.py @@ -30,7 +30,6 @@ class ActivitySync(BaseSync): - name = "sync-activity" description = "Sync activities." @@ -144,7 +143,7 @@ def write_ride_efforts(self, strava_activity: Activity, ride: Ride): else: ride.resync_count = 1 + sync_count ride.resync_date = datetime.now() + timedelta( - hours=6 ** sync_count + hours=6**sync_count ) # 1, 6, 36 hours except: @@ -266,7 +265,6 @@ def sync_rides_detail( use_cache: bool = True, only_cache: bool = False, ): - session = meta.scoped_session() q = session.query(Ride) @@ -345,9 +343,7 @@ def delete_activity(self, *, athlete_id: int, activity_id: int): def fetch_and_store_activity_detail( self, *, athlete_id: int, activity_id: int, use_cache: bool = False ): - with meta.transaction_context() as session: - self.logger.info( "Fetching detailed activity athlete_id={}, activity_id={}".format( athlete_id, activity_id @@ -624,7 +620,6 @@ def write_ride(self, activity: Activity) -> Ride: ride = Ride(activity.id) if new_ride: - # Set the "workflow flags". These all default to False in the database. The value of NULL means # that the workflow flag does not apply (e.g. do not bother fetching this) @@ -667,7 +662,6 @@ def write_ride(self, activity: Activity) -> Ride: def _sync_rides( self, start_date: datetime, end_date: datetime, athlete, rewrite: bool = False ): - sess = meta.scoped_session() api_ride_entries = self.list_rides( @@ -695,7 +689,7 @@ def _sync_rides( ride_ids_needing_detail = [] ride_ids_needing_streams = [] - for (i, strava_activity) in enumerate(api_ride_entries): + for i, strava_activity in enumerate(api_ride_entries): self.logger.debug( "Processing ride: {0} ({1}/{2})".format( strava_activity.id, i + 1, num_rides @@ -834,9 +828,7 @@ def sync_rides( force: bool = False, athlete_ids: List[int] = None, ): - with meta.transaction_context() as sess: - if start_date is None: start_date = config.START_DATE diff --git a/freezing/sync/data/athlete.py b/freezing/sync/data/athlete.py index 9d395f1..8335ff6 100644 --- a/freezing/sync/data/athlete.py +++ b/freezing/sync/data/athlete.py @@ -38,7 +38,6 @@ class AthleteSync(BaseSync): - name = "sync-athletes" description = "Sync athletes." @@ -48,9 +47,7 @@ def all_done(self): return loc_time > end_time def sync_athletes(self, max_records: int = None): - with meta.transaction_context() as sess: - # We iterate over all of our athletes that have access tokens. # (We can't fetch anything for those that don't.) @@ -171,7 +168,10 @@ def register_athlete_team( matches = [c for c in matches if c.id not in config.OBSERVER_TEAMS] if len(matches) > 1: self.logger.info( - "Multiple teams matched for {}: {}".format(strava_athlete, matches,) + "Multiple teams matched for {}: {}".format( + strava_athlete, + matches, + ) ) raise MultipleTeamsError(matches) if len(matches) == 0: diff --git a/freezing/sync/data/photos.py b/freezing/sync/data/photos.py index a85d5fa..d73fc63 100644 --- a/freezing/sync/data/photos.py +++ b/freezing/sync/data/photos.py @@ -11,14 +11,11 @@ class PhotoSync(BaseSync): - name = "sync-photos" description = "Sync (non-primary) ride photos." def sync_photos(self): - with meta.transaction_context() as sess: - q = sess.query(orm.Ride) q = q.filter_by(photos_fetched=False, private=False) @@ -76,7 +73,6 @@ def write_ride_photos_nonprimary(self, activity_photos, ride): # insta_client = insta.configured_instagram_client() for activity_photo in activity_photos: - # If it's already in the db, then skip it. existing = meta.scoped_session().query(RidePhoto).get(activity_photo.uid) if existing: diff --git a/freezing/sync/data/streams.py b/freezing/sync/data/streams.py index 21e3206..edbea88 100644 --- a/freezing/sync/data/streams.py +++ b/freezing/sync/data/streams.py @@ -23,7 +23,6 @@ class StreamSync(BaseSync): - name = "sync-activity-streams" description = "Sync activity streams (GPS, etc.) JSON." @@ -35,7 +34,6 @@ def sync_streams( use_cache: bool = True, only_cache: bool = False, ): - session = meta.scoped_session() q = session.query(Ride).options(joinedload(Ride.athlete)) @@ -44,7 +42,9 @@ def sync_streams( q = q.filter(and_(Ride.private == False, Ride.manual == False)) if not rewrite: - q = q.filter(Ride.track_fetched == False,) + q = q.filter( + Ride.track_fetched == False, + ) if athlete_id: self.logger.info("Filtering activity details for {}".format(athlete_id)) @@ -86,9 +86,7 @@ def sync_streams( def fetch_and_store_activity_streams( self, *, athlete_id: int, activity_id: int, use_cache: bool = False ): - with meta.transaction_context() as session: - self.logger.info( "Fetching activity streams for athlete_id={}, activity_id={}".format( athlete_id, activity_id diff --git a/freezing/sync/data/weather.py b/freezing/sync/data/weather.py index d41a0dc..9276d96 100644 --- a/freezing/sync/data/weather.py +++ b/freezing/sync/data/weather.py @@ -69,7 +69,6 @@ def sync_weather( num_rides = len(rows) for i, r in enumerate(rows): - if limit and i >= limit: logging.info("Limit ({0}) reached".format(limit)) break @@ -80,7 +79,6 @@ def sync_weather( ) try: - # If you can't reproduce the ancient infrastructure required by all this and so can't run any of the # geoalchemy stuff you can hardcode this to debug # start_geo_wkt = "POINT(-76.96 38.96)" @@ -120,7 +118,8 @@ def sync_weather( key=lambda d: abs((d.time - ride_start).total_seconds()), ) end_obs = min( - hist.day.hours, key=lambda d: abs((d.time - ride_end).total_seconds()) + hist.day.hours, + key=lambda d: abs((d.time - ride_end).total_seconds()), ) if len(ride_observations) <= 2: diff --git a/freezing/sync/run.py b/freezing/sync/run.py index 434e524..21cfa81 100644 --- a/freezing/sync/run.py +++ b/freezing/sync/run.py @@ -17,7 +17,6 @@ def main(): - init_logging() init_model(config.SQLALCHEMY_URL) diff --git a/freezing/sync/subscribe.py b/freezing/sync/subscribe.py index 984277a..cb5d211 100644 --- a/freezing/sync/subscribe.py +++ b/freezing/sync/subscribe.py @@ -30,7 +30,6 @@ def handle_message(self, message: ActivityUpdate): self.logger.info("Processing activity update {}".format(message)) with meta.transaction_context() as session: - athlete: Athlete = session.query(Athlete).get(message.athlete_id) if not athlete: self.logger.warning( diff --git a/freezing/sync/utils/cache.py b/freezing/sync/utils/cache.py index 3a04973..bf79720 100644 --- a/freezing/sync/utils/cache.py +++ b/freezing/sync/utils/cache.py @@ -121,7 +121,6 @@ def retrieve_object_json( object_json = None if object_json is None: - if only_cache: self.logger.info( "[CACHE-MISS] Skipping {} {} " @@ -171,7 +170,6 @@ def retrieve_object_json( class CachingActivityFetcher(CachingAthleteObjectFetcher): - object_type = "activity" def download_object_json( @@ -209,7 +207,6 @@ def fetch( class CachingStreamFetcher(CachingAthleteObjectFetcher): - object_type = "streams" def filename(self, *, athlete_id: int, object_id: int): diff --git a/freezing/sync/wx/darksky/model.py b/freezing/sync/wx/darksky/model.py index ff45606..10ec01f 100644 --- a/freezing/sync/wx/darksky/model.py +++ b/freezing/sync/wx/darksky/model.py @@ -6,7 +6,6 @@ class Hour(object): - time: datetime temperature: float apparent_temperature: float @@ -22,7 +21,6 @@ def __init__(self, json, tz): class Day(object): - sunrise_time: datetime sunset_time: datetime temperature_min: float @@ -36,7 +34,6 @@ def __init__(self, json, tz): class Forecast(object): - timezone: str latitude: float longitude: float diff --git a/freezing/sync/wx/ncdc/api.py b/freezing/sync/wx/ncdc/api.py index ee3482d..9006e74 100644 --- a/freezing/sync/wx/ncdc/api.py +++ b/freezing/sync/wx/ncdc/api.py @@ -40,7 +40,6 @@ def __init__(self, p1, p2=None): class Client(object): - base_url = urllib.parse.urlparse("http://www.ncdc.noaa.gov/cdo-services/services") def __init__(self, token, cache_dir=None): @@ -56,9 +55,9 @@ def _handle_protocol_error(self, response): """ Parses the JSON response from the server, raising a :class:`stravatools.api.Fault` if the server returned an error. - + :param response: The response JSON - :raises Fault: If the response contains an error. + :raises Fault: If the response contains an error. """ if "cdoError" in response: raise Fault(response["name"], response["message"]) diff --git a/freezing/sync/wx/ncdc/model.py b/freezing/sync/wx/ncdc/model.py index 8418c96..ee931f4 100644 --- a/freezing/sync/wx/ncdc/model.py +++ b/freezing/sync/wx/ncdc/model.py @@ -2,8 +2,7 @@ class BaseCollection(object): - """ - """ + """ """ totalCount = None @@ -17,7 +16,6 @@ def parse(self, result): class PagedCollection(object): - pageCount = None _page = None @@ -112,7 +110,6 @@ def fill(self, collection, overwrite=False): class LocationSearchResult(object): - _minDate = None _maxDate = None diff --git a/freezing/sync/wx/sunrise.py b/freezing/sync/wx/sunrise.py index 912e749..927a175 100644 --- a/freezing/sync/wx/sunrise.py +++ b/freezing/sync/wx/sunrise.py @@ -12,12 +12,12 @@ class Sun: - """ + """ Calculate sunrise and sunset based on equations from NOAA http://www.srrb.noaa.gov/highlights/sunrise/calcdetails.html - + typical use, calculating the sunrise at the present day: - + import datetime import sunrise s = Sun(lat=49,lon=3) @@ -53,7 +53,7 @@ def solarnoon(self, when): def _timefromdecimalday(cls, day): """ returns a datetime.time object. - + day is a decimal day between 0.0 and 1.0, e.g. noon = 0.5 """ hours = (24 * day) % 24 @@ -66,7 +66,7 @@ def _timefromdecimalday(cls, day): def _preptime(self, when): """ - Extract information in a suitable format from when, + Extract information in a suitable format from when, a datetime.datetime object. """ # datetime days are numbered in the Gregorian calendar @@ -87,7 +87,7 @@ def _calc(self): """ Perform the actual calculations for sunrise, sunset and a number of related quantities. - + The results are stored in the instance variables sunrise_t, sunset_t and solarnoon_t """ diff --git a/freezing/sync/wx/visualcrossing/api.py b/freezing/sync/wx/visualcrossing/api.py index 436394f..3758129 100644 --- a/freezing/sync/wx/visualcrossing/api.py +++ b/freezing/sync/wx/visualcrossing/api.py @@ -9,6 +9,7 @@ from .model import Forecast + class HistoVisualCrossing(object): """ Histomorphic visual crossing. Kinda like animal crossing, but for weather data. diff --git a/freezing/sync/wx/visualcrossing/model.py b/freezing/sync/wx/visualcrossing/model.py index a976b1f..daa9f2e 100644 --- a/freezing/sync/wx/visualcrossing/model.py +++ b/freezing/sync/wx/visualcrossing/model.py @@ -14,7 +14,9 @@ class Hour(object): source: str # obs,fcst def __init__(self, json, date, tz): - self.time = datetime.combine(date, time.fromisoformat(json["datetime"]).replace(tzinfo=tz)) + self.time = datetime.combine( + date, time.fromisoformat(json["datetime"]).replace(tzinfo=tz) + ) self.temperature = json["temp"] self.apparent_temperature = json["feelslike"] precip_types = json["preciptype"] # can be null @@ -43,8 +45,12 @@ class Day(object): def __init__(self, json, tz): self.date = date.fromisoformat(json["datetime"]) - self.sunrise = datetime.combine(self.date, time.fromisoformat(json["sunrise"]).replace(tzinfo=tz)) - self.sunset = datetime.combine(self.date, time.fromisoformat(json["sunset"]).replace(tzinfo=tz)) + self.sunrise = datetime.combine( + self.date, time.fromisoformat(json["sunrise"]).replace(tzinfo=tz) + ) + self.sunset = datetime.combine( + self.date, time.fromisoformat(json["sunset"]).replace(tzinfo=tz) + ) self.temperature_min = json["tempmin"] self.temperature_max = json["tempmax"] self.hours = [Hour(d, self.date, tz) for d in json["hours"]] diff --git a/freezing/sync/wx/wunder/api.py b/freezing/sync/wx/wunder/api.py index b942d78..a42aa4c 100644 --- a/freezing/sync/wx/wunder/api.py +++ b/freezing/sync/wx/wunder/api.py @@ -132,9 +132,9 @@ def _handle_protocol_error(self, response): """ Parses the JSON response from the server, raising a :class:`stravatools.api.Fault` if the server returned an error. - + :param response: The response JSON - :raises Fault: If the response contains an error. + :raises Fault: If the response contains an error. """ if "error" in response["response"]: raise Fault( @@ -186,7 +186,6 @@ def get(self, *args, **kwargs): time.sleep(self.pause) def history(self, date, lat=None, lon=None, us_city=None): - latlon_location_param = None us_city_location_param = None diff --git a/freezing/sync/wx/wunder/model.py b/freezing/sync/wx/wunder/model.py index bc81409..8a01369 100644 --- a/freezing/sync/wx/wunder/model.py +++ b/freezing/sync/wx/wunder/model.py @@ -32,7 +32,7 @@ def build_date(dateobj): - """ Builds a date from wundergound date structure. """ + """Builds a date from wundergound date structure.""" year = int(dateobj["year"]) mon = int(dateobj["mon"]) day = int(dateobj["mday"]) @@ -101,7 +101,7 @@ def __init__(self): self.observations = [] def find_first_before(self, date): - """ Finds the first observation before the specified date. """ + """Finds the first observation before the specified date.""" date = date.replace(tzinfo=self.date.tzinfo) # Iterate over the observations until the date is later, then return the previous assert len(self.observations) > 0 @@ -126,7 +126,7 @@ def find_first_before(self, date): return prev def find_next_after(self, date): - """ Finds the next observation after the specified date. """ + """Finds the next observation after the specified date.""" assert len(self.observations) > 0 date = date.replace(tzinfo=self.date.tzinfo) # Iterate over the observations until the date is later, then return the previous @@ -179,7 +179,7 @@ def find_observations_within(self, start_date, end_date): def find_nearest_observation(self, date): """ - Gets the observation closest in time (before or after) to specified date. + Gets the observation closest in time (before or after) to specified date. """ if date.tzinfo is None: date = copy(date).replace(tzinfo=self.date.tzinfo)