Name | xivapy JSON |
Version |
0.4.0
JSON |
| download |
home_page | None |
Summary | Async Python client for XIVAPI for Final Fantasy XIV |
upload_time | 2025-08-31 14:29:03 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.13.2 |
license | MIT |
keywords |
api
async
ffxiv
xiv
xivapi
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# xivapy
An async python client for accessing XIVAPI data for Final Fantasy XIV.
## Features
* Custom model support powered by pydantic
* Async python
* Type hints throughout for pleasant developer experience
* All major endpoints of xivapi covered
## Installation
```
pip install git+https://github.com/macrocosmos-app/xivapy.git@main
```
## Quick Start
The easiest way to use the client is to define a model and try looking through a sheet with a search.
```python
import typing
from pydantic import Field
import xivapy
class ContentFinderCondition(xivapy.Model):
# Custom map a python field to an xivapi field name
id: int = Field(alias='row_id')
# compress language fields into a dictionary for easy viewing
# for this, however, you'll need to set up a default dict for it to use
# The output of this is:
# {
# 'en': "The Protector and the Destroyer",
# 'de': "Schützer des Volkes, Schlächter des Volkes",
# 'fr': "Protecteurs et destructeurs",
# 'ja': "護る者、壊す者"
# }
# Optional languages will be omitted
name: Annotated[xivapy.LangDict, xivapy.FieldMapping('Name', languages=['en', 'de', 'fr', 'ja'])] = Field(default_factory=lambda: xivapy.LangDict.copy())
# get a deeply nested (and optional) field lifted up into a top-level field
bgm_file: Annotated[str | None, xivapy.FieldMapping('Content.BGM.File')] = None
# by default, the sheet to be searched will be the name of the model
# if you wish to override this, set the following:
#__sheetname__ = 'SomeOtherSheetName'
async with xivapy.Client() as client:
# Search ContentFinderCondition for all content that mentor roulette applies to
async for content in client.search(ContentFinderCondition, query=xivapy.QueryBuilder().where(MentorRoulette=1)):
# Data is typed as SearchResult[ContentFinderCondition], accessable by the `.data` field
print(f'{content.data.name} ({content.data.id}) - {content.data.bgm_file}')
# The same thing, but for a single id:
result = await client.sheet(ContentFinderCondition, row=998)
if result is not None:
# result is a ContentFinderCondition instance
print(result)
# You can also search for multiple ids:
async for result in client.sheet(ContentFinderCondition, rows=[1, 3, 99, 128]):
# result is of type ContentFinderCondition
print(result)
```
## API Reference
This is only a basic overview of the library; as documentation is developed, this section will be removed/changed
### Core Classes
**`xivapy.Client`**:
* `search(model: xivapy.Model, query: xivapy.QueryBuilder | str)` - Search sheets with a query
* `search(models: tuple[xivapy.Model], query: xivapy.QueryBuilder | str)` - Search multiple sheets with a query
* `sheet(model: xivapy.Model, *, row: int = N)` - Pull a single row from a sheet
* `sheet(model: xivapy.Model, *, rows: list[int] = [...])` - Pull several rows from a sheet
* `asset(path: str, format: xivapy.Format = 'png')` - Retrieve an asset from the game (defaults to png format)
* `icon(icon_id: int, format: xivapy.Format = 'jpg')` - Retrieve an icon from the game
* `map(territory: str, index: str)` - Retrieve a (composed) map from the game
* `versions()` - Get available game versions
* `sheets()` - List all available sheets
**`xivapy.Model`**:
* Inherit to create a typed data class for use with client methods - they provide the field parameters and sheet name automatically
* Use fields with `xivapy.FieldMapping` to map API fields to model fields:
```python
custom_name: Annotated[str, xivapy.FieldMapping('Name')]
```
* If your model name does not match the sheet name, you can set the sheet name with `__sheetname__ = 'CorrectSheetName'`
**`xivapy.QueryBuilder`** - Build search queries
* `.where(Field=value)` - looking for exact matches; can be compounded:
```python
QueryBuilder().where(Name='Foo', Bar='Baz')
```
* `.contains(Field='text')` - Search within fields
```python
QueryBuilder().contains(Name='the') # equivalent to `Name~"the"
```
* Supports `>`, `>=`, `<`, `<=` with `.gt`, `.gte`, `.lt`, `.lte`
* `.required()` / `.excluded()` - makes the previous item as required or excluded
### Types
**`xivapy.LangDict`** - `TypedDict` representing the return fields of items like `Name@lang(en)`
**`xivapy.Format`** - Listed formats that are acceptable for `asset` method
## Development
The only real prerequisite you need is [uv](https://docs.astral.sh/uv/); afterwards:
* `git clone https://github.com/macrocosmos-app/xivapy`
* `uv sync --locked`
Afterwards, you should be able to develop against the library or use it with `uv run python` in a shell (for example) - it's an editable package inside the virtual environment.
### Code quality
To ensure code quality, install the pre-commit hooks with:
```
uv run pre-commit install --install-hooks
```
This ensures that commits follow a baseline quality and typing standard. This project uses `ruff` for formatting and checking (see [docs](https://docs.astral.sh/ruff/)); configure your formatter or use `uv run ruff format ...` as appropriate for your environment.
For typing, this project uses mypy; you can check with `uv run mypy` for a basic check, though the pre-commit hooks have a few extra flags.
### Testing and coverage
You can run the existing tests (and get coverage) with
```
uv run coverage run -m pytest
uv run coverage report
```
## License
MIT License - see LICENSE file
## Links
* https://v2.xivapi.com
* https://github.com/macrocosmos-app/xivapy/issues
Raw data
{
"_id": null,
"home_page": null,
"name": "xivapy",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.13.2",
"maintainer_email": null,
"keywords": "api, async, ffxiv, xiv, xivapi",
"author": null,
"author_email": "Oowazu Nonowazu <oowazu.nonowazu@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/c3/26/a76f642aa7c96ac39ab46a738b29063a647950b397f1f7d74cf7e4079ce9/xivapy-0.4.0.tar.gz",
"platform": null,
"description": "# xivapy\n\nAn async python client for accessing XIVAPI data for Final Fantasy XIV.\n\n## Features\n\n* Custom model support powered by pydantic\n* Async python\n* Type hints throughout for pleasant developer experience\n* All major endpoints of xivapi covered\n\n## Installation\n\n```\npip install git+https://github.com/macrocosmos-app/xivapy.git@main\n```\n\n## Quick Start\n\nThe easiest way to use the client is to define a model and try looking through a sheet with a search.\n\n```python\nimport typing\nfrom pydantic import Field\nimport xivapy\n\nclass ContentFinderCondition(xivapy.Model):\n # Custom map a python field to an xivapi field name\n id: int = Field(alias='row_id')\n # compress language fields into a dictionary for easy viewing\n # for this, however, you'll need to set up a default dict for it to use\n # The output of this is:\n # {\n # 'en': \"The Protector and the Destroyer\",\n # 'de': \"Sch\u00fctzer des Volkes, Schl\u00e4chter des Volkes\",\n # 'fr': \"Protecteurs et destructeurs\",\n # 'ja': \"\u8b77\u308b\u8005\u3001\u58ca\u3059\u8005\"\n # }\n # Optional languages will be omitted\n name: Annotated[xivapy.LangDict, xivapy.FieldMapping('Name', languages=['en', 'de', 'fr', 'ja'])] = Field(default_factory=lambda: xivapy.LangDict.copy())\n # get a deeply nested (and optional) field lifted up into a top-level field\n bgm_file: Annotated[str | None, xivapy.FieldMapping('Content.BGM.File')] = None\n # by default, the sheet to be searched will be the name of the model\n # if you wish to override this, set the following:\n #__sheetname__ = 'SomeOtherSheetName'\n\nasync with xivapy.Client() as client:\n # Search ContentFinderCondition for all content that mentor roulette applies to\n async for content in client.search(ContentFinderCondition, query=xivapy.QueryBuilder().where(MentorRoulette=1)):\n # Data is typed as SearchResult[ContentFinderCondition], accessable by the `.data` field\n print(f'{content.data.name} ({content.data.id}) - {content.data.bgm_file}')\n\n # The same thing, but for a single id:\n result = await client.sheet(ContentFinderCondition, row=998)\n if result is not None:\n # result is a ContentFinderCondition instance\n print(result)\n # You can also search for multiple ids:\n async for result in client.sheet(ContentFinderCondition, rows=[1, 3, 99, 128]):\n # result is of type ContentFinderCondition\n print(result)\n```\n\n## API Reference\n\nThis is only a basic overview of the library; as documentation is developed, this section will be removed/changed\n\n### Core Classes\n\n**`xivapy.Client`**:\n* `search(model: xivapy.Model, query: xivapy.QueryBuilder | str)` - Search sheets with a query\n* `search(models: tuple[xivapy.Model], query: xivapy.QueryBuilder | str)` - Search multiple sheets with a query\n* `sheet(model: xivapy.Model, *, row: int = N)` - Pull a single row from a sheet\n* `sheet(model: xivapy.Model, *, rows: list[int] = [...])` - Pull several rows from a sheet\n* `asset(path: str, format: xivapy.Format = 'png')` - Retrieve an asset from the game (defaults to png format)\n* `icon(icon_id: int, format: xivapy.Format = 'jpg')` - Retrieve an icon from the game\n* `map(territory: str, index: str)` - Retrieve a (composed) map from the game\n* `versions()` - Get available game versions\n* `sheets()` - List all available sheets\n\n**`xivapy.Model`**:\n* Inherit to create a typed data class for use with client methods - they provide the field parameters and sheet name automatically\n* Use fields with `xivapy.FieldMapping` to map API fields to model fields:\n\n```python\ncustom_name: Annotated[str, xivapy.FieldMapping('Name')]\n```\n\n* If your model name does not match the sheet name, you can set the sheet name with `__sheetname__ = 'CorrectSheetName'`\n\n**`xivapy.QueryBuilder`** - Build search queries\n* `.where(Field=value)` - looking for exact matches; can be compounded:\n\n```python\nQueryBuilder().where(Name='Foo', Bar='Baz')\n```\n\n* `.contains(Field='text')` - Search within fields\n\n```python\nQueryBuilder().contains(Name='the') # equivalent to `Name~\"the\"\n```\n\n* Supports `>`, `>=`, `<`, `<=` with `.gt`, `.gte`, `.lt`, `.lte`\n* `.required()` / `.excluded()` - makes the previous item as required or excluded\n\n### Types\n\n**`xivapy.LangDict`** - `TypedDict` representing the return fields of items like `Name@lang(en)`\n**`xivapy.Format`** - Listed formats that are acceptable for `asset` method\n\n## Development\n\nThe only real prerequisite you need is [uv](https://docs.astral.sh/uv/); afterwards:\n\n* `git clone https://github.com/macrocosmos-app/xivapy`\n* `uv sync --locked`\n\nAfterwards, you should be able to develop against the library or use it with `uv run python` in a shell (for example) - it's an editable package inside the virtual environment.\n\n### Code quality\n\nTo ensure code quality, install the pre-commit hooks with:\n\n```\nuv run pre-commit install --install-hooks\n```\n\nThis ensures that commits follow a baseline quality and typing standard. This project uses `ruff` for formatting and checking (see [docs](https://docs.astral.sh/ruff/)); configure your formatter or use `uv run ruff format ...` as appropriate for your environment.\n\nFor typing, this project uses mypy; you can check with `uv run mypy` for a basic check, though the pre-commit hooks have a few extra flags.\n\n### Testing and coverage\n\nYou can run the existing tests (and get coverage) with\n\n```\nuv run coverage run -m pytest\nuv run coverage report\n```\n\n## License\n\nMIT License - see LICENSE file\n\n## Links\n\n* https://v2.xivapi.com\n* https://github.com/macrocosmos-app/xivapy/issues\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Async Python client for XIVAPI for Final Fantasy XIV",
"version": "0.4.0",
"project_urls": {
"Documentation": "https://github.com/macrocosmos-app/xivapy#readme",
"Homepage": "https://github.com/macrocosmos-app/xivapy",
"Issues": "https://github.com/macrocosmos-app/xivapy/issues",
"Repository": "https://github.com/macrocosmos-app/xivapy"
},
"split_keywords": [
"api",
" async",
" ffxiv",
" xiv",
" xivapi"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "9d24951e213883cb5b637e4080999c4689748f67f4c29a5f06e948f080f96e26",
"md5": "931a156eeeef3375a970eaa1cb7edf8a",
"sha256": "b6f80c33c02c5fc0dc3f0b1f49a5dc20ae13c00fdd073e64aa959f79f0635bf7"
},
"downloads": -1,
"filename": "xivapy-0.4.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "931a156eeeef3375a970eaa1cb7edf8a",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.13.2",
"size": 15216,
"upload_time": "2025-08-31T14:29:02",
"upload_time_iso_8601": "2025-08-31T14:29:02.332622Z",
"url": "https://files.pythonhosted.org/packages/9d/24/951e213883cb5b637e4080999c4689748f67f4c29a5f06e948f080f96e26/xivapy-0.4.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "c326a76f642aa7c96ac39ab46a738b29063a647950b397f1f7d74cf7e4079ce9",
"md5": "cb3e2a32a4a1c11d7a10f4978b83908f",
"sha256": "3a5ed86362ba8664ada2a6e48a794df7024fe2644bfdfe48e490fbfbf3bc71fd"
},
"downloads": -1,
"filename": "xivapy-0.4.0.tar.gz",
"has_sig": false,
"md5_digest": "cb3e2a32a4a1c11d7a10f4978b83908f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.13.2",
"size": 54157,
"upload_time": "2025-08-31T14:29:03",
"upload_time_iso_8601": "2025-08-31T14:29:03.695318Z",
"url": "https://files.pythonhosted.org/packages/c3/26/a76f642aa7c96ac39ab46a738b29063a647950b397f1f7d74cf7e4079ce9/xivapy-0.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-31 14:29:03",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "macrocosmos-app",
"github_project": "xivapy#readme",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "xivapy"
}