Skip to content

Commit

Permalink
Concept Endpoints (#158)
Browse files Browse the repository at this point in the history
- Update dependencies
- Added support for concept, concept_list and concept search (Fixes #17)
- Recheck all endpoint fields if required to be optional or not (Fixes
#153 #154 #155)
  - `Character.first_issue` and `CharacterEntry.first_issue` is Optional
- `Character.issue_count` and `CharacterEntry.issue_count` is Not
Optional
  - `Character.publisher` and `CharacterEntry.publisher` is Optional
  - `Issue.number` and `IssueEntry.number` is Optional
  - `Location.issue_count` and `LocationEntry.issue_count` is Optional
  - `Team.first_issue` and `TeamEntry.first_issue` is Optional
  - `Team.publisher` and `TeamEntry.publisher` is Optional
  • Loading branch information
Buried-In-Code authored Jan 10, 2023
1 parent 084bdf2 commit 072e38c
Show file tree
Hide file tree
Showing 20 changed files with 465 additions and 161 deletions.
41 changes: 0 additions & 41 deletions .github/workflows/code-analysis.yaml

This file was deleted.

4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.189
rev: v0.0.216
hooks:
- id: ruff
- repo: https://github.com/asottile/pyupgrade
Expand Down Expand Up @@ -55,7 +55,7 @@ repos:
hooks:
- id: black
- repo: https://github.com/pappasam/toml-sort
rev: v0.20.1
rev: v0.22.1
hooks:
- id: toml-sort
args:
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
[![Ruff](https://img.shields.io/badge/Linter-Ruff-informational?style=flat-square)](https://github.com/charliermarsh/ruff)

[![Github - Contributors](https://img.shields.io/github/contributors/Metron-Project/Simyan.svg?logo=Github&label=Contributors&style=flat-square)](https://github.com/Metron-Project/Simyan/graphs/contributors)
[![Github Action - Code Analysis](https://img.shields.io/github/actions/workflow/status/Metron-Project/Simyan/code-analysis.yaml?branch=main&logo=Github-Actions&label=Code-Analysis&style=flat-square)](https://github.com/Metron-Project/Simyan/actions/workflows/code-analysis.yaml)
[![Github Action - Testing](https://img.shields.io/github/actions/workflow/status/Metron-Project/Simyan/testing.yaml?branch=main&logo=Github-Actions&label=Testing&style=flat-square)](https://github.com/Metron-Project/Simyan/actions/workflows/testing.yaml)

[![Read the Docs](https://img.shields.io/readthedocs/simyan?label=Read-the-Docs&logo=Read-the-Docs&style=flat-square)](https://simyan.readthedocs.io/en/latest/?badge=latest)
Expand Down
4 changes: 4 additions & 0 deletions docs/simyan/schemas/concept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Concept

::: simyan.schemas.concept.Concept
::: simyan.schemas.concept.ConceptEntry
1 change: 1 addition & 0 deletions mkdocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ nav:
- simyan.schemas:
- Package: simyan/schemas/__init__.md
- character: simyan/schemas/character.md
- concept: simyan/schemas/concept.md
- creator: simyan/schemas/creator.md
- generic_entries: simyan/schemas/generic_entries.md
- issue: simyan/schemas/issue.md
Expand Down
62 changes: 49 additions & 13 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ requires = ["hatchling"]

[project]
authors = [
{ name = "BuriedInCode", email = "BuriedInCode@tuta.io" },
{email = "BuriedInCode@tuta.io", name = "BuriedInCode"}
]
classifiers = [
"Development Status :: 4 - Beta",
Expand All @@ -15,12 +15,12 @@ classifiers = [
"Operating System :: MacOS",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python",
"Topic :: Internet",
"Typing :: Typed"
]
Expand All @@ -31,10 +31,10 @@ dependencies = [
]
description = "A Python wrapper for the Comicvine API."
dynamic = ["version"]
keywords = ["comics", "comic", "metadata"]
keywords = ["comic", "comics", "metadata"]
license = "GPL-3.0-or-later"
maintainers = [
{ name = "BuriedInCode", email = "BuriedInCode@tuta.io" },
{email = "BuriedInCode@tuta.io", name = "BuriedInCode"}
]
name = "Simyan"
readme = "README.md"
Expand Down Expand Up @@ -64,7 +64,7 @@ Source = "https://github.com/Metron-Project/Simyan"

[tool.black]
line-length = 100
target-version = ["py37", "py38", "py39", "py310", "py311"]
target-version = ["py310", "py311", "py37", "py38", "py39"]

[tool.coverage.report]
show_missing = true
Expand All @@ -81,14 +81,50 @@ addopts = ["--cov", "-x"]
[tool.ruff]
fix = true
ignore = [
"D203", "D204", "D213", "D215", "D400", "D404", "D406", "D407", "D408", "D409", "D413", # Ignored for google docstyle
"D107", "D212", "ANN101"
# Missing D401
"ANN101",
"D107",
"D203",
"D204",
"D212",
"D213",
"D215",
"D400",
"D404",
"D406",
"D407",
"D408",
"D409",
"D413" # Ignored for google docstyle
]
line-length = 100
select = [
"F", "E", "W", "C90", "I", "D", "UP", "N", "YTT", "ANN", "S", "BLE", "B", "A", "C4", "ICN", "Q",
"RET", "SIM", "TID", "ARG", "ERA", "PLC", "PLE", "PLR", "PLW", "RUF",
"A",
"ANN",
"ARG",
"B",
"BLE",
"C4",
"C90",
"D",
"E",
"ERA",
"F",
"I",
"ICN",
"N",
"PLC",
"PLE",
"PLR",
"PLW",
"Q",
"RET",
"RUF",
"S",
"SIM",
"TID",
"UP",
"W",
"YTT"
]
target-version = "py37"

Expand All @@ -109,4 +145,4 @@ max-complexity = 10
classmethod-decorators = ["classmethod", "pydantic.validator"]

[tool.ruff.per-file-ignores]
"tests/test_*.py" = ["S101", "ANN201"]
"tests/test_*.py" = ["ANN201", "S101"]
68 changes: 58 additions & 10 deletions simyan/comicvine.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from simyan import __version__
from simyan.exceptions import AuthenticationError, CacheError, ServiceError
from simyan.schemas.character import Character, CharacterEntry
from simyan.schemas.concept import Concept, ConceptEntry
from simyan.schemas.creator import Creator, CreatorEntry
from simyan.schemas.issue import Issue, IssueEntry
from simyan.schemas.location import Location, LocationEntry
Expand All @@ -38,22 +39,24 @@
class ComicvineResource(Enum):
"""Enum class for Comicvine Resources."""

CHARACTER = (4005, "character", List[CharacterEntry])
"""Details for the Character resource on Comicvine."""
CREATOR = (4040, "person", List[CreatorEntry])
"""Details for the Creator resource on Comicvine."""
ISSUE = (4000, "issue", List[IssueEntry])
"""Details for the Issue resource on Comicvine."""
LOCATION = (4020, "location", List[LocationEntry])
"""Details for the Location resource on Comicvine."""
PUBLISHER = (4010, "publisher", List[PublisherEntry])
"""Details for the Publisher resource on Comicvine."""
VOLUME = (4050, "volume", List[VolumeEntry])
"""Details for the Volume resource on Comicvine."""
ISSUE = (4000, "issue", List[IssueEntry])
"""Details for the Issue resource on Comicvine."""
STORY_ARC = (4045, "story_arc", List[StoryArcEntry])
"""Details for the Story Arc resource on Comicvine."""
CREATOR = (4040, "person", List[CreatorEntry])
"""Details for the Creator resource on Comicvine."""
CHARACTER = (4005, "character", List[CharacterEntry])
"""Details for the Character resource on Comicvine."""
TEAM = (4060, "team", List[TeamEntry])
"""Details for the Team resource on Comicvine."""
VOLUME = (4050, "volume", List[VolumeEntry])
"""Details for the Volume resource on Comicvine."""
LOCATION = (4020, "location", List[LocationEntry])
"""Details for the Location resource on Comicvine."""
CONCEPT = (4015, "concept", List[ConceptEntry])
"""Details for the Concept resource on Comicvine."""

@property
def resource_id(self) -> int:
Expand Down Expand Up @@ -540,6 +543,50 @@ def location_list(
except ValidationError as err:
raise ServiceError(err) from err

def concept(self, concept_id: int) -> Concept:
"""
Request data for a Concept based on its id.
Args:
concept_id: The Concept id.
Returns:
A Concept object
Raises:
ServiceError: If there is an issue with validating the response.
"""
try:
result = self._get_request(
endpoint=f"/concept/{ComicvineResource.CONCEPT.resource_id}-{concept_id}"
)["results"]
return parse_obj_as(Concept, result)
except ValidationError as err:
raise ServiceError(err) from err

def concept_list(
self, params: Optional[Dict[str, Union[str, int]]] = None, max_results: int = 500
) -> List[ConceptEntry]:
"""
Request data for a list of ConceptEntries.
Args:
params: Parameters to add to the request.
max_results: Limits the amount of results looked up and returned.
Returns:
A list of ConceptEntry objects.
Raises:
ServiceError: If there is an issue with validating the response.
"""
try:
results = self._retrieve_offset_results(
endpoint="/concepts/", params=params, max_results=max_results
)
return parse_obj_as(List[ConceptEntry], results)
except ValidationError as err:
raise ServiceError(err) from err

def search(
self, resource: ComicvineResource, query: str, max_results: int = 500
) -> Union[
Expand All @@ -551,6 +598,7 @@ def search(
List[CharacterEntry],
List[TeamEntry],
List[LocationEntry],
List[ConceptEntry],
]:
"""
Request a list of search results filtered by provided resource.
Expand Down
48 changes: 29 additions & 19 deletions simyan/schemas/character.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
__all__ = ["Character", "CharacterEntry"]
import re
from datetime import date, datetime
from typing import List, Optional
from typing import Any, List, Optional

from pydantic import Field

Expand Down Expand Up @@ -57,29 +57,34 @@ class Character(BaseModel):
creators: List[GenericEntry] = Field(default_factory=list)
date_added: datetime
date_last_updated: datetime
date_of_birth: Optional[date] = Field(default=None, alias="birth")
deaths: List[GenericEntry] = Field(default_factory=list, alias="issues_died_in")
date_of_birth: Optional[date] = Field(alias="birth", default=None)
deaths: List[GenericEntry] = Field(alias="issues_died_in", default_factory=list)
description: Optional[str] = None
enemies: List[GenericEntry] = Field(default_factory=list, alias="character_enemies")
enemy_teams: List[GenericEntry] = Field(default_factory=list, alias="team_enemies")
first_issue: IssueEntry = Field(alias="first_appeared_in_issue")
friendly_teams: List[GenericEntry] = Field(default_factory=list, alias="team_friends")
friends: List[GenericEntry] = Field(default_factory=list, alias="character_friends")
enemies: List[GenericEntry] = Field(alias="character_enemies", default_factory=list)
enemy_teams: List[GenericEntry] = Field(alias="team_enemies", default_factory=list)
first_issue: Optional[IssueEntry] = Field(alias="first_appeared_in_issue", default=None)
friendly_teams: List[GenericEntry] = Field(alias="team_friends", default_factory=list)
friends: List[GenericEntry] = Field(alias="character_friends", default_factory=list)
gender: int
character_id: int = Field(alias="id")
image: ImageEntry
issue_count: Optional[int] = Field(default=None, alias="count_of_issue_appearances")
issues: List[GenericEntry] = Field(default_factory=list, alias="issue_credits")
issue_count: int = Field(alias="count_of_issue_appearances")
issues: List[GenericEntry] = Field(alias="issue_credits", default_factory=list)
name: str
origin: Optional[GenericEntry] = None
powers: List[GenericEntry] = Field(default_factory=list)
publisher: GenericEntry
publisher: Optional[GenericEntry] = None
real_name: Optional[str] = None
site_url: str = Field(alias="site_detail_url")
story_arcs: List[GenericEntry] = Field(default_factory=list, alias="story_arc_credits")
summary: Optional[str] = Field(default=None, alias="deck")
story_arcs: List[GenericEntry] = Field(alias="story_arc_credits", default_factory=list)
summary: Optional[str] = Field(alias="deck", default=None)
teams: List[GenericEntry] = Field(default_factory=list)
volumes: List[GenericEntry] = Field(default_factory=list, alias="volume_credits")
volumes: List[GenericEntry] = Field(alias="volume_credits", default_factory=list)

def __init__(self, **data: Any):
if "birth" in data and data["birth"]:
data["birth"] = datetime.strptime(data["birth"], "%b %d, %Y").date()
super().__init__(**data)

@property
def alias_list(self) -> List[str]:
Expand Down Expand Up @@ -120,19 +125,24 @@ class CharacterEntry(BaseModel):
api_url: str = Field(alias="api_detail_url")
date_added: datetime
date_last_updated: datetime
date_of_birth: Optional[date] = Field(default=None, alias="birth")
date_of_birth: Optional[date] = Field(alias="birth", default=None)
description: Optional[str] = None
first_issue: IssueEntry = Field(alias="first_appeared_in_issue")
first_issue: Optional[IssueEntry] = Field(alias="first_appeared_in_issue", default=None)
gender: int
character_id: int = Field(alias="id")
image: ImageEntry
issue_count: Optional[int] = Field(default=None, alias="count_of_issue_appearances")
issue_count: int = Field(alias="count_of_issue_appearances")
name: str
origin: Optional[GenericEntry] = None
publisher: GenericEntry
publisher: Optional[GenericEntry] = None
real_name: Optional[str] = None
site_url: str = Field(alias="site_detail_url")
summary: Optional[str] = Field(default=None, alias="deck")
summary: Optional[str] = Field(alias="deck", default=None)

def __init__(self, **data: Any):
if "birth" in data and data["birth"]:
data["birth"] = datetime.strptime(data["birth"], "%b %d, %Y").date()
super().__init__(**data)

@property
def alias_list(self) -> List[str]:
Expand Down
Loading

0 comments on commit 072e38c

Please sign in to comment.