Skip to content

Commit

Permalink
Merge pull request #12 from ReubenFrankel/ruff-lint-format
Browse files Browse the repository at this point in the history
Setup Ruff linting/formatting
  • Loading branch information
ReubenFrankel authored Mar 6, 2024
2 parents eaddc55 + aeee639 commit 7035348
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 19 deletions.
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ repos:
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix, --show-fixes]
exclude: tests/
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-mypy
Expand All @@ -36,3 +37,4 @@ repos:
- id: mypy
additional_dependencies:
- types-requests
exclude: tests/
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.PHONY: help init lint test

help:
@echo AVAILABLE COMMANDS
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-23s\033[0m%s\n", $$1, $$2}'

init: ## Initialise repo for local development
@poetry install --sync --with dev
@poetry run pre-commit install --install-hooks

lint: ## Lint files
poetry run pre-commit run ruff

test: ## Run tests
@poetry run pytest
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ warn_unused_configs = true

[tool.ruff]
ignore = [
"ANN001", # missing-type-function-argument
"ANN101", # missing-type-self
"ANN102", # missing-type-cls
"ANN201", # missing-return-type-undocumented-public-function
"COM812", # missing-trailing-comma
"ISC001", # single-line-implicit-string-concatenation
]
select = ["ALL"]
src = ["tap_f1"]
Expand Down
3 changes: 3 additions & 0 deletions tap_f1/client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""REST client handling, including F1Stream base class."""

from singer_sdk.streams import RESTStream
from typing_extensions import override

from tap_f1.pagination import F1Paginator

Expand All @@ -11,9 +12,11 @@ class F1Stream(RESTStream):
url_base = "https://ergast.com/api/f1"
_limit = 1000

@override
def get_new_paginator(self):
return F1Paginator(0, self._limit)

@override
def get_url_params(self, context, next_page_token):
params = super().get_url_params(context, next_page_token)
params["limit"] = self._limit
Expand Down
7 changes: 7 additions & 0 deletions tap_f1/pagination.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
"""Pagination classes for tap-f1."""


from singer_sdk.pagination import BaseOffsetPaginator
from typing_extensions import override


class F1Paginator(BaseOffsetPaginator):
"""Base API paginator."""

@override
def has_more(self, response):
data = response.json()["MRData"]

Expand Down
37 changes: 23 additions & 14 deletions tap_f1/streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
from datetime import date

from singer_sdk import typing as th
from typing_extensions import override

from tap_f1.client import F1Stream


class SpeedUnitType(th.StringType):
"""Speed unit type."""

@override
@th.DefaultInstanceProperty
def type_dict(self):
return {
Expand All @@ -24,7 +28,7 @@ class SeasonsStream(F1Stream):
"""Define seasons stream."""

name = "seasons"
primary_keys = ["season"]
primary_keys = ("season",)
replication_key = "season"
path = "/seasons.json"
records_jsonpath = "MRData.SeasonTable.Seasons[*]"
Expand All @@ -34,6 +38,7 @@ class SeasonsStream(F1Stream):
th.Property("url", th.URIType),
).to_dict()

@override
def get_child_context(self, record, context):
start_date = date.fromisoformat(self.config["start_date"])

Expand All @@ -48,7 +53,7 @@ class CircuitsStream(F1Stream):

parent_stream_type = SeasonsStream
name = "circuits"
primary_keys = ["circuitId"]
primary_keys = ("circuitId",)
path = "/{season}/circuits.json"
records_jsonpath = "MRData.CircuitTable.Circuits[*]"

Expand All @@ -74,7 +79,7 @@ class DriversStream(F1Stream):
parent_stream_type = SeasonsStream
context_key = "Driver"
name = "drivers"
primary_keys = ["driverId"]
primary_keys = ("driverId",)
path = "/{season}/drivers.json"
records_jsonpath = "MRData.DriverTable.Drivers[*]"

Expand All @@ -96,7 +101,7 @@ class ConstructorsStream(F1Stream):
parent_stream_type = SeasonsStream
context_key = "Constructor"
name = "constructors"
primary_keys = ["constructorId"]
primary_keys = ("constructorId",)
path = "/{season}/constructors.json"
records_jsonpath = "MRData.ConstructorTable.Constructors[*]"

Expand All @@ -113,7 +118,7 @@ class RacesStream(F1Stream):

parent_stream_type = SeasonsStream
name = "races"
primary_keys = ["season", "round"]
primary_keys = ("season", "round")
replication_key = "date"
path = "/{season}.json"
records_jsonpath = "MRData.RaceTable.Races[*]"
Expand Down Expand Up @@ -179,6 +184,7 @@ class RacesStream(F1Stream):
),
).to_dict()

@override
def get_child_context(self, record, context):
value = self.get_starting_replication_key_value(context)
start_date = date.fromisoformat(value)
Expand All @@ -197,7 +203,7 @@ class QualifyingResultsStream(F1Stream):

parent_stream_type = RacesStream
name = "qualifying_results"
primary_keys = ["season", "round", "number"]
primary_keys = ("season", "round", "number")
path = "/{season}/{round}/qualifying.json"
records_jsonpath = "MRData.RaceTable.Races[*].QualifyingResults[*]"

Expand Down Expand Up @@ -239,7 +245,7 @@ class SprintResultsStream(F1Stream):

parent_stream_type = RacesStream
name = "sprints_results"
primary_keys = ["season", "round", "number"]
primary_keys = ("season", "round", "number")
path = "/{season}/{round}/sprint.json"
records_jsonpath = "MRData.RaceTable.Races[*].SprintResults[*]"

Expand Down Expand Up @@ -310,7 +316,7 @@ class RaceResultsStream(F1Stream):

parent_stream_type = RacesStream
name = "race_results"
primary_keys = ["season", "round", "number"]
primary_keys = ("season", "round", "number")
path = "/{season}/{round}/results.json"
records_jsonpath = "MRData.RaceTable.Races[*].Results[*]"

Expand Down Expand Up @@ -375,6 +381,7 @@ class RaceResultsStream(F1Stream):
),
).to_dict()

@override
def get_child_context(self, record, context):
return {
**super().get_child_context(record, context),
Expand All @@ -387,7 +394,7 @@ class LapsStream(F1Stream):

parent_stream_type = RaceResultsStream
name = "laps"
primary_keys = ["season", "round", "driverId", "number"]
primary_keys = ("season", "round", "driverId", "number")
path = "/{season}/{round}/drivers/{driverId}/laps.json"
records_jsonpath = "MRData.RaceTable.Races[*].Laps[*]"

Expand All @@ -403,7 +410,7 @@ class LapsStream(F1Stream):
th.Property("driverId", th.StringType),
th.Property("position", th.StringType),
th.Property("time", th.StringType),
)
),
),
),
).to_dict()
Expand All @@ -414,7 +421,7 @@ class PitStopsStream(F1Stream):

parent_stream_type = RacesStream
name = "pit_stops"
primary_keys = ["season", "round", "driverId", "stop"]
primary_keys = ("season", "round", "driverId", "stop")
path = "/{season}/{round}/pitstops.json"
records_jsonpath = "MRData.RaceTable.Races[*].PitStops[*]"

Expand All @@ -434,7 +441,7 @@ class DriverStandingsStream(F1Stream):

parent_stream_type = RacesStream
name = "driver_standings"
primary_keys = ["season", "round", "driverId", "position"]
primary_keys = ("season", "round", "driverId", "position")
path = "/{season}/{round}/driverStandings.json"
records_jsonpath = "MRData.StandingsTable.StandingsLists[*].DriverStandings[*]"

Expand Down Expand Up @@ -467,11 +474,12 @@ class DriverStandingsStream(F1Stream):
th.Property("url", th.URIType),
th.Property("name", th.StringType),
th.Property("nationality", th.StringType),
)
),
),
),
).to_dict()

@override
def post_process(self, row, context):
# driverId forms part of primary key
row["driverId"] = row["Driver"]["driverId"]
Expand All @@ -484,7 +492,7 @@ class ConstructorStandingsStream(F1Stream):

parent_stream_type = RacesStream
name = "constructor_standings"
primary_keys = ["season", "round", "constructorId", "position"]
primary_keys = ("season", "round", "constructorId", "position")
path = "/{season}/{round}/constructorStandings.json"
records_jsonpath = "MRData.StandingsTable.StandingsLists[*].ConstructorStandings[*]"

Expand All @@ -507,6 +515,7 @@ class ConstructorStandingsStream(F1Stream):
),
).to_dict()

@override
def post_process(self, row, context):
# constructorId forms part of primary key
row["constructorId"] = row["Constructor"]["constructorId"]
Expand Down
6 changes: 4 additions & 2 deletions tap_f1/tap.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"""F1 tap class."""

from datetime import date
from datetime import date, datetime, timezone

import singer_sdk.typing as th
from singer_sdk import Tap
from typing_extensions import override

from tap_f1 import streams

Expand Down Expand Up @@ -32,10 +33,11 @@ class TapF1(Tap):
th.Property(
"start_date",
th.DateType,
default=date(date.today().year, 1, 1).isoformat(),
default=date(datetime.now(tz=timezone.utc).year, 1, 1).isoformat(),
),
).to_dict()

@override
def discover_streams(self):
return [stream_type(self) for stream_type in STREAM_TYPES]

Expand Down
3 changes: 0 additions & 3 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,3 @@
tap_class=TapF1,
config=SAMPLE_CONFIG,
)


# TODO: Create additional tests as appropriate for your tap.

0 comments on commit 7035348

Please sign in to comment.