Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# format code with ruff
1655999065f0d8bd6d26597a0f527a2242d5f11e
22 changes: 22 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: lint

on:
push:
pull_request:
types: [ opened, reopened, synchronize ]

jobs:
ruff:
permissions:
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- name: Get Ruff Version
id: ruff-version
run: echo "version=$(grep -Po '(?<=ruff==)[0-9]+\.[0-9]+\.[0-9]+' pyproject.toml)" >> $GITHUB_OUTPUT

- uses: astral-sh/ruff-action@v3
with:
version: ${{ steps.ruff-version.outputs.version }}
Comment thread Fixed
52 changes: 2 additions & 50 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This workflow will ensure that the pushed contents to the repo
# are not majorly breaking, and they comply with black standards.
# are not majorly breaking.

name: Pytests

Expand Down Expand Up @@ -34,52 +34,4 @@ jobs:
shell: bash
env:
TEST_API_KEY: ${{ secrets.TEST_API_KEY }}
run: python -m pytest --cov=fortnite_api --import-mode=importlib -vs tests/

black:
name: Black Formatting Check
runs-on: ubuntu-latest

# Checkout the repository
steps:
- name: Checkout
uses: actions/checkout@v5

- name: Setup Python 3.9
uses: actions/setup-python@v6
with:
python-version: "3.9"
cache: "pip" # Cache the pip packages to speed up the workflow

- name: Install Dependencies and Project
run: |
python -m pip install -U pip setuptools
pip install -U -r requirements.txt
pip install -e .[dev]

- name: Run Black Check
run: black --check --diff --verbose fortnite_api

isort:
name: Isort Formatting Check
runs-on: ubuntu-latest

# Checkout the repository
steps:
- name: Checkout
uses: actions/checkout@v5

- name: Setup Python 3.9
uses: actions/setup-python@v6
with:
python-version: "3.9"
cache: "pip" # Cache the pip packages to speed up the workflow

- name: Install Dependencies and Project
run: |
python -m pip install -U pip setuptools
pip install -U -r requirements.txt
pip install -e .[dev]

- name: Run Isort Check
run: isort --check --diff fortnite_api
run: python -m pytest --cov=fortnite_api --import-mode=importlib -vs tests/
16 changes: 7 additions & 9 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# Black formatter pre commit hook
repos:
- repo: https://github.com/psf/black
rev: 24.10.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.13.2
hooks:
- id: black

- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
name: isort (python)
# Run the linter.
- id: ruff-check
args: [ --fix ]
# Run the formatter.
- id: ruff-format
4 changes: 2 additions & 2 deletions docs/extensions/outdated_code_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ class OutdatedCodeBlock(CodeBlock):
}

def run(self) -> list[Node]:

# Create the main node that holds the code block and warning
root = OutdatedCodeBlockNode()

Expand All @@ -144,7 +143,8 @@ def setup(app: Sphinx):
app.add_node(OutdatedCodeBlockNode, html=(visit_outdated_code_block_node, depart_outdated_code_block_node)) # type: ignore
app.add_node(OutdatedCodeBlockWarning, html=(visit_outdated_code_block_warning, depart_outdated_code_block_warning)) # type: ignore
app.add_node( # type: ignore
OutdatedCodeBlockWarningText, html=(visit_outdated_code_block_warning_text, depart_outdated_code_block_warning_text)
OutdatedCodeBlockWarningText,
html=(visit_outdated_code_block_warning_text, depart_outdated_code_block_warning_text),
)

app.add_directive('outdated-code-block', OutdatedCodeBlock)
Expand Down
10 changes: 9 additions & 1 deletion fortnite_api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,15 @@
from .aes import Aes
from .all import CosmeticsAll
from .banner import Banner, BannerColor
from .cosmetics import CosmeticBr, CosmeticCar, CosmeticInstrument, CosmeticLegoKit, CosmeticTrack, VariantBean, VariantLego
from .cosmetics import (
CosmeticBr,
CosmeticCar,
CosmeticInstrument,
CosmeticLegoKit,
CosmeticTrack,
VariantBean,
VariantLego,
)
from .creator_code import CreatorCode
from .enums import *
from .errors import BetaAccessNotEnabled, BetaUnknownException, MissingAPIKey
Expand Down
4 changes: 3 additions & 1 deletion fortnite_api/cosmetics/track.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ def __init__(self, *, data: dict[str, Any], http: HTTPClientT) -> None:
self.bpm: int = data['bpm']
self.duration: int = data['duration']

self.difficulty: CosmeticTrackDifficulty[HTTPClientT] = CosmeticTrackDifficulty(data=data['difficulty'], http=http)
self.difficulty: CosmeticTrackDifficulty[HTTPClientT] = CosmeticTrackDifficulty(
data=data['difficulty'], http=http
)
self.gameplay_tags: list[str] = get_with_fallback(data, 'gameplayTags', list)
self.genres: list[str] = get_with_fallback(data, 'genres', list)
self.album_art: Asset[HTTPClientT] = Asset(http=http, url=data['albumArt'])
Expand Down
4 changes: 3 additions & 1 deletion fortnite_api/cosmetics/variants/bean.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ def fetch_cosmetic_br(
) -> Coroutine[Any, Any, CosmeticBr]: ...

@overload
def fetch_cosmetic_br(self: VariantBean[SyncHTTPClient], *, language: Optional[GameLanguage] = None) -> CosmeticBr: ...
def fetch_cosmetic_br(
self: VariantBean[SyncHTTPClient], *, language: Optional[GameLanguage] = None
) -> CosmeticBr: ...

def fetch_cosmetic_br(
self, *, language: Optional[GameLanguage] = None
Expand Down
4 changes: 3 additions & 1 deletion fortnite_api/cosmetics/variants/lego.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ def fetch_cosmetic_br(
) -> Coroutine[Any, Any, CosmeticBr]: ...

@overload
def fetch_cosmetic_br(self: VariantLego[SyncHTTPClient], *, language: Optional[GameLanguage] = None) -> CosmeticBr: ...
def fetch_cosmetic_br(
self: VariantLego[SyncHTTPClient], *, language: Optional[GameLanguage] = None
) -> CosmeticBr: ...

def fetch_cosmetic_br(
self, *, language: Optional[GameLanguage] = None
Expand Down
3 changes: 1 addition & 2 deletions fortnite_api/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,10 @@ def key(self) -> str:


class HTTPMixin(abc.ABC):

def __init__(self, *, token: Optional[str] = None) -> None:
self.token: Optional[str] = token

self.user_agent = 'FortniteApi (https://github.com/Fortnite-API/py-wrapper {0}) Python/{1[0]}.{1[1]}'.format(
self.user_agent = 'FortniteApi (https://github.com/Fortnite-API/py-wrapper {0}) Python/{1[0]}.{1[1]}'.format( # noqa: UP032
__version__, sys.version_info
)

Expand Down
3 changes: 2 additions & 1 deletion fortnite_api/new_display_asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ def __init__(self, *, data: dict[str, Any], http: HTTPClientT) -> None:
self.id: str = data["id"]
self.cosmetic_id: Optional[str] = data.get("cosmeticId")
self.material_instances: list[MaterialInstance[HTTPClientT]] = [
MaterialInstance(data=instance, http=http) for instance in get_with_fallback(data, "materialInstances", list)
MaterialInstance(data=instance, http=http)
for instance in get_with_fallback(data, "materialInstances", list)
]
self.render_images: list[RenderImage[HTTPClientT]] = [
RenderImage(data=instance, http=http) for instance in get_with_fallback(data, "renderImages", list)
Expand Down
4 changes: 3 additions & 1 deletion fortnite_api/proxies.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ class TransformerListProxy(Generic[T, K_co, V_co], list[T]):
to ensure that the data is always in a consistent state.
"""

def __init__(self, raw_data: Iterable[dict[K_co, V_co]], /, transform_data: Callable[[dict[K_co, V_co]], T]) -> None:
def __init__(
self, raw_data: Iterable[dict[K_co, V_co]], /, transform_data: Callable[[dict[K_co, V_co]], T]
) -> None:
self._transform_data: Callable[[dict[K_co, V_co]], T] = transform_data
super().__init__(cast(list[T], raw_data))

Expand Down
4 changes: 3 additions & 1 deletion fortnite_api/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,9 @@ def __init__(self, *, data: dict[str, Any], http: HTTPClientT) -> None:
self.user: Account[HTTPClientT] = Account(data=_user, http=http)

_battle_pass = data.get("battlePass")
self.battle_pass: Optional[BrBattlePass[HTTPClientT]] = _battle_pass and BrBattlePass(data=_battle_pass, http=http)
self.battle_pass: Optional[BrBattlePass[HTTPClientT]] = _battle_pass and BrBattlePass(
data=_battle_pass, http=http
)

_image = data.get("image")
self.image: Optional[Asset[HTTPClientT]] = _image and Asset(http=http, url=_image)
Expand Down
36 changes: 21 additions & 15 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ docs = [
'furo',
'sphinx-copybutton',
]
dev = ['black', 'isort', 'discord.py', 'pyright', 'pre-commit']
dev = ['ruff==0.13.2', 'discord.py', 'pyright', 'pre-commit']
speed = ['orjson']

[project.urls]
Expand All @@ -87,13 +87,6 @@ asyncio_mode = "strict"
testpaths = ["tests"]
addopts = "--import-mode=importlib"

# Black formatting

[tool.black]
line-length = 125
skip-string-normalization = true
force-exclude = "LICENSE|requirements.txt|pyproject.toml|README.md"

# Pyright configuration

[tool.pyright]
Expand All @@ -105,11 +98,24 @@ reportPrivateUsage = "none"
exclude = ["**/__pycache__", "build", "dist", "docs"]
include = ["fortnite_api/", "tests/", "examples/"]

# Isort configuration
# Ruff formatting

[tool.ruff]
# Allow lines to be as long as 120.
line-length = 120

[tool.ruff.format]
# Prefer single quotes over double quotes.
quote-style = "preserve"

[tool.ruff.lint]
select = [
"I", # Isort
"UP", # Pyupgrade
]

[tool.ruff.lint.isort]
combine-as-imports = true

[tool.isort]
profile = "black"
combine_as_imports = true
combine_star = true
line_length = 125
src_paths = ["fortnite_api/", "tests/", "examples/"]
[tool.ruff.lint.pyupgrade]
keep-runtime-typing = true
3 changes: 0 additions & 3 deletions tests/test_asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

def test_sync_asset_reading():
with fortnite_api.SyncClient() as client:

mock_asset = fortnite_api.Asset(http=client.http, url=V_BUCK_ICON_URL)

# Read the asset and ensure it is bytes
Expand All @@ -44,7 +43,6 @@ def test_sync_asset_reading():
@pytest.mark.asyncio
async def test_async_asset_reading():
async with fortnite_api.Client() as client:

mock_asset = fortnite_api.Asset(http=client.http, url=V_BUCK_ICON_URL)

# Read the asset and ensure it is bytes
Expand All @@ -54,7 +52,6 @@ async def test_async_asset_reading():

def test_asset():
with fortnite_api.SyncClient() as client:

mock_asset = fortnite_api.Asset(http=client.http, url=V_BUCK_ICON_URL)

assert mock_asset.url == V_BUCK_ICON_URL
Expand Down
2 changes: 0 additions & 2 deletions tests/test_async_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,6 @@ async def test_async_fetch_playlist_by_id(api_key: str):

@pytest.mark.asyncio
async def test_async_beta_fetch_new_display_assets(api_key: str):

# Ensure you cannot call this without beta=True
with pytest.raises(fn_api.BetaAccessNotEnabled):
await fn_api.Client().beta_fetch_new_display_assets()
Expand Down Expand Up @@ -586,7 +585,6 @@ async def test_async_beta_fetch_new_display_assets(api_key: str):

@pytest.mark.asyncio
async def test_async_beta_fetch_material_instances(api_key: str):

# Ensure you cannot call this without beta=True
with pytest.raises(fn_api.BetaAccessNotEnabled):
await fn_api.Client().beta_fetch_material_instances()
Expand Down
2 changes: 0 additions & 2 deletions tests/test_beta.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,13 @@ async def test_async_cannot_call_beta_method():

# A mock of the SyncClient beta function that raises an error
class MockSyncFortniteAPI(fortnite_api.SyncClient):

@beta_method
def beta_mock_call(self):
raise ValueError('Mock error')


# A mock of the Client beta function that raises an error
class MockFortniteAPI(fortnite_api.Client):

@beta_method
async def beta_mock_call(self):
raise ValueError('Mock error')
Expand Down
1 change: 0 additions & 1 deletion tests/test_ratelimits.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ async def test_async_rate_limit_handling(async_client: HTTPClient):
# Make a request
route = Route('GET', 'https://example.com')
with pytest.raises(RateLimited) as excinfo:

# This will try 5 times to request, and each time get a 429 response. After it
# should raise the RateLimited error. Any subsequent requests with the same route
# should immediately raise the RateLimited error.
Expand Down
1 change: 0 additions & 1 deletion tests/test_sync_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,6 @@ def test_sync_fetch_playlist_by_id(api_key: str):


def test_sync_beta_fetch_new_display_assets(api_key: str):

# Ensure you cannot call this without beta=True
with pytest.raises(fn_api.BetaAccessNotEnabled):
fn_api.SyncClient().beta_fetch_new_display_assets()
Expand Down