Skip to content

Grand Comics Database

GrandComicsDatabase

Class with functionality to request GCD API endpoints.

PARAMETER DESCRIPTION
email

The user's GCD email address, which is used for authentication.

TYPE: str

password

The user's GCD password, which is used for authentication.

TYPE: str

base_url

Root URL of the GCD API.

TYPE: str | None DEFAULT: None

user_agent

Value sent in the User-Agent request header.

TYPE: str | None DEFAULT: None

timeout

Set how long requests will wait for a response (in seconds).

TYPE: float DEFAULT: 20

cache_path

Path to the SQLite cache file. If not provided, a default path will be used under ~/.cache/grayven/cache.sqlite

TYPE: Path | None DEFAULT: None

cache_expiry

Duration for which cached responses are valid. Response cache-headers take precedence.

TYPE: timedelta DEFAULT: timedelta(days=14)

ratelimit_path

Path to the SQLite ratelimit file. If not provided, a default path will be used under ~/.cache/grayven/ratelimits.sqlite

TYPE: Path | None DEFAULT: None

Source code in grayven/grand_comics_database.py
Python
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
def __init__(
    self,
    email: str,
    password: str,
    base_url: str | None = None,
    user_agent: str | None = None,
    timeout: float = 20,
    cache_path: Path | None = None,
    cache_expiry: timedelta = timedelta(days=14),
    ratelimit_path: Path | None = None,
):
    self._base_url = base_url or "https://www.comics.org/api"
    self._session = CachedLimiterSession(
        backend=SQLiteCache(
            db_path=cache_path or (get_cache_root() / "cache.sqlite"), serializer="json"
        ),
        expire_after=cache_expiry,
        cache_control=cache_expiry != NEVER_EXPIRE,
        per_minute=20,
        per_hour=200,
        per_day=2_000,
        max_delay=timeout * 2,
        bucket_class=SQLiteBucket,
        bucket_kwargs={"path": ratelimit_path or (get_cache_root() / "ratelimits.sqlite")},
        per_host=False,
        bucket_name="grand-comics-database",
    )
    self._session.headers.update(
        {
            "Accept": "application/json",
            "User-Agent": user_agent
            or f"Grayven/{__version__} ({platform.system()}: {platform.release()}; Python v{platform.python_version()})",  # noqa: E501
        }
    )
    self._session.auth = HTTPBasicAuth(username=email, password=password)
    self._timeout = timeout

Methods:

get_issue

Request an Issue using its id.

PARAMETER DESCRIPTION
issue_id

The Issue id.

TYPE: int

RETURNS DESCRIPTION
Issue

A Issue object.

RAISES DESCRIPTION
ServiceError

If the API response is invalid or validation fails.

AuthenticationError

If credentials are invalid.

RateLimitError

If the API rate limit is exceeded.

Source code in grayven/grand_comics_database.py
Python
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
def get_issue(self, issue_id: int) -> Issue:
    """Request an Issue using its id.

    Args:
        issue_id: The Issue id.

    Returns:
        A Issue object.

    Raises:
        ServiceError: If the API response is invalid or validation fails.
        AuthenticationError: If credentials are invalid.
        RateLimitError: If the API rate limit is exceeded.
    """
    return self._get_item(endpoint=f"/issue/{issue_id}", type_=Issue)

get_publisher

Request a Publisher using its id.

PARAMETER DESCRIPTION
publisher_id

The Publisher id.

TYPE: int

RETURNS DESCRIPTION
Publisher

A Publisher object.

RAISES DESCRIPTION
ServiceError

If the API response is invalid or validation fails.

AuthenticationError

If credentials are invalid.

RateLimitError

If the API rate limit is exceeded.

Source code in grayven/grand_comics_database.py
Python
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
def get_publisher(self, publisher_id: int) -> Publisher:
    """Request a Publisher using its id.

    Args:
        publisher_id: The Publisher id.

    Returns:
        A Publisher object.

    Raises:
        ServiceError: If the API response is invalid or validation fails.
        AuthenticationError: If credentials are invalid.
        RateLimitError: If the API rate limit is exceeded.
    """
    return self._get_item(endpoint=f"/publisher/{publisher_id}", type_=Publisher)

get_series

Request a Series using its id.

PARAMETER DESCRIPTION
series_id

The Series id.

TYPE: int

RETURNS DESCRIPTION
Series

A Series object.

RAISES DESCRIPTION
ServiceError

If the API response is invalid or validation fails.

AuthenticationError

If credentials are invalid.

RateLimitError

If the API rate limit is exceeded.

Source code in grayven/grand_comics_database.py
Python
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
def get_series(self, series_id: int) -> Series:
    """Request a Series using its id.

    Args:
        series_id: The Series id.

    Returns:
        A Series object.

    Raises:
        ServiceError: If the API response is invalid or validation fails.
        AuthenticationError: If credentials are invalid.
        RateLimitError: If the API rate limit is exceeded.
    """
    return self._get_item(endpoint=f"/series/{series_id}", type_=Series)

list_issues

Request a list of Issues.

PARAMETER DESCRIPTION
series_name

The name of the series to filter issues from.

TYPE: str

issue_number

The number to filter issues by.

TYPE: int

year

Filter the results using the issue year via its key_date.

TYPE: int | None DEFAULT: None

max_results

If given, return at most this many results.

TYPE: int | None DEFAULT: 500

RETURNS DESCRIPTION
list[BasicIssue]

A list of Issue objects.

RAISES DESCRIPTION
ServiceError

If the API response is invalid or validation fails.

AuthenticationError

If credentials are invalid.

RateLimitError

If the API rate limit is exceeded.

Source code in grayven/grand_comics_database.py
Python
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
def list_issues(
    self,
    series_name: str,
    issue_number: int,
    year: int | None = None,
    max_results: int | None = 500,
) -> list[BasicIssue]:
    """Request a list of Issues.

    Args:
        series_name: The name of the series to filter issues from.
        issue_number: The number to filter issues by.
        year: Filter the results using the issue year via its key_date.
        max_results: If given, return at most this many results.

    Returns:
        A list of Issue objects.

    Raises:
        ServiceError: If the API response is invalid or validation fails.
        AuthenticationError: If credentials are invalid.
        RateLimitError: If the API rate limit is exceeded.
    """
    if year is None:
        return self._get_list(
            endpoint=f"/series/name/{series_name}/issue/{issue_number}",
            type_=BasicIssue,
            max_results=max_results,
        )
    return self._get_list(
        endpoint=f"/series/name/{series_name}/issue/{issue_number}/year/{year}",
        type_=BasicIssue,
        max_results=max_results,
    )

list_onsale_weekly_issues

Request a list of issues on sale in a given ISO week.

PARAMETER DESCRIPTION
year

The ISO year (4-digit year).

TYPE: int

week

The ISO week number (1-53).

TYPE: int

max_results

If given, return at most this many results.

TYPE: int | None DEFAULT: 500

RETURNS DESCRIPTION
list[BasicIssue]

List of BasicIssue objects representing issues that went on sale during the given week.

RAISES DESCRIPTION
ServiceError

If the API response is invalid or validation fails.

AuthenticationError

If credentials are invalid.

RateLimitError

If the API rate limit is exceeded.

Source code in grayven/grand_comics_database.py
Python
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
def list_onsale_weekly_issues(
    self, year: int, week: int, max_results: int | None = 500
) -> list[BasicIssue]:
    """Request a list of issues on sale in a given ISO week.

    Args:
        year: The ISO year (4-digit year).
        week: The ISO week number (1-53).
        max_results: If given, return at most this many results.

    Returns:
        List of BasicIssue objects representing issues that went on sale during the given week.

    Raises:
        ServiceError: If the API response is invalid or validation fails.
        AuthenticationError: If credentials are invalid.
        RateLimitError: If the API rate limit is exceeded.
    """
    return self._get_list(
        endpoint=f"/issue/on_sale_weekly/{year}/week/{week}",
        type_=BasicIssue,
        max_results=max_results,
    )

list_publishers

Request a list of Publishers.

PARAMETER DESCRIPTION
max_results

If given, return at most this many results.

TYPE: int | None DEFAULT: 500

RETURNS DESCRIPTION
list[Publisher]

A list of Publisher objects.

RAISES DESCRIPTION
ServiceError

If the API response is invalid or validation fails.

AuthenticationError

If credentials are invalid.

RateLimitError

If the API rate limit is exceeded.

Source code in grayven/grand_comics_database.py
Python
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
def list_publishers(self, max_results: int | None = 500) -> list[Publisher]:
    """Request a list of Publishers.

    Args:
        max_results: If given, return at most this many results.

    Returns:
        A list of Publisher objects.

    Raises:
        ServiceError: If the API response is invalid or validation fails.
        AuthenticationError: If credentials are invalid.
        RateLimitError: If the API rate limit is exceeded.
    """
    return self._get_list(endpoint="/publisher", type_=Publisher, max_results=max_results)

list_series

Request a list of Series.

PARAMETER DESCRIPTION
name

Filter the results using the series name.

TYPE: str | None DEFAULT: None

year

Filter the results using the series beginning year (Requires name to be passed).

TYPE: int | None DEFAULT: None

max_results

If given, return at most this many results.

TYPE: int | None DEFAULT: 500

RETURNS DESCRIPTION
list[Series]

A list of Series objects.

RAISES DESCRIPTION
ServiceError

If the API response is invalid or validation fails.

AuthenticationError

If credentials are invalid.

RateLimitError

If the API rate limit is exceeded.

Source code in grayven/grand_comics_database.py
Python
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
def list_series(
    self, name: str | None = None, year: int | None = None, max_results: int | None = 500
) -> list[Series]:
    """Request a list of Series.

    Args:
        name: Filter the results using the series name.
        year: Filter the results using the series beginning year (Requires name to be passed).
        max_results: If given, return at most this many results.

    Returns:
        A list of Series objects.

    Raises:
        ServiceError: If the API response is invalid or validation fails.
        AuthenticationError: If credentials are invalid.
        RateLimitError: If the API rate limit is exceeded.
    """
    if name is None:
        return self._get_list(endpoint="/series", type_=Series, max_results=max_results)
    if year is None:
        return self._get_list(
            endpoint=f"/series/name/{name}", type_=Series, max_results=max_results
        )
    return self._get_list(
        endpoint=f"/series/name/{name}/year/{year}", type_=Series, max_results=max_results
    )