Skip to main content

The most up-to-date version of this README is on GitHub.

pygal-stubs

What is this?

  • pygal-stubs is a package that provides external type stubs (PEP 561) for pygal.
  • Install it to get static analyisis, type-checking and autocompletion in your favorite IDE, so that you no longer have to pollute your "strict" codebase with # pyright: ignore[reportUnknownMemberType]. Be sure to read Usage as well.

What this isn't

  • This package is not affiliated with pygal.
  • It is almost certainly not perfect or 100% accurate. If you spot a mistake (any mistake) and know how to fix it, submit a PR; If you don't, open an issue.
  • (Per the LICENSE, this package comes with no warranty whatsoever, however there is one thing we know for a fact will not work at all) This package is not suitable for contributing to pygal itself. If you try to open pygal's source with pygal-stubs installed and your type checker on "strict", you will almost certainly get type-checking errors and could potentially be misled as to the real types of the objects you're dealing with.
    • This package is aimed at the end users of pygal and as such reflects the types that appear in the public API, which might differ from implementation details.
  • These stubs are not intended for use with any particular type checker, however, they were written while using basedpyright and were tested more thoroughly with it than with any other type checker. As such, it is this package's primary target type checker (it's extremely similar to Pylance so vanilla VS Code users should have no issues). If you have a specific issue with another type checker, please submit a PR or open an issue.
  • (obviously) This isn't replacement for pygal's documentation, which should always be considered the source of truth when using pygal.

Installation

pygal-stubs is available on PyPI. Install it with:

pip install pygal-stubs

Or however you usually install PyPI packages.

This will automatically install the following type dependencies:

  • typing-extensions: Backports modern typing features to all supported Python versions.
  • types-lxml & django-types: Stubs for pygal's optional dependencies to prevent Any / Unknown from leaking into your codebase.
    • You might still get Unknown from other pygal dependencies that don't have type stubs available such as cairosvg and pyquery, as well as the map modules (see below).

Note that this package only installs the type stubs, not the optional runtime libraries themselves. If your code uses pygal features that rely on lxml or django, ensure you install those packages separately to avoid runtime ImportErrors.

This package does not include stubs for the separately packaged map modules. You'll need to download those separately. I have created type stubs for my active fork of the world map module. You can find them here: fork, stubs. 1

Usage

Reading and writing Graph attributes

If you already use a strict type checker, existing pygal code will continue to work. However, there is one key detail you must know: Graph attributes (used to configure graphs) are set dynamically at runtime via __setattr__, not defined explicitly on __init__. This means that if you try to access a Graph attribute you haven't set explicitly, you'll get an AttributeError at runtime that type checkers (and these stubs) have no way of knowing about.

For example:

line = pygal.Line()
title = line.title # Your type checker will say this is str | None, when in reality this line will cause an AttributeError!

This isn't an issue if you never read these attributes. Assigning to them doesn't cause any issues, as seen here:

import pygal
line = pygal.Line()
line.title = "My Title" # This is fine

We have also added the more popular (the ones found in the docs + a couple of others) attributes to the __init__ method stubs, so you can assign them directly at instantiation:

import pygal
# Instead of:
line = pygal.Line()
line.title = "My Title"

# or:
config = pygal.Config()
config.title = "My Title"
line = pygal.Line(config)

# You can do:
line = pygal.Line(title="My Title")

Values that aren't in the __init__ signature will be assigned just fine, but they won't be type checked as you'll be falling back to the untyped **kwargs. If you believe that more attributes should be added to an __init__ method signature, please submit a PR. This paragraph also applies to some other methods (e.g. add)

Why is this?

pygal does not define which attributes each specific Graph type requires, instead providing all attributes, for all graphs, in the massive CommonConfig and Config classes for documentation purposes. Then, at runtime, all attributes are assigned arbitrarily (via __setattr__ from either explicit instance.attr = val asignment from the user or at instantiation time from the constructor **kwargs) to the graph instances.

This means that if we wanted type-checking for these values (instead of accepting anything for any key like __setattr__ normally does), we had to basically hardcode all config attributes for all graphs as properties of BaseGraph, the class that all graphs inherit from. If you know a better way to do this without erasing type checking for these attributes, please submit a PR

Graphs are now generic

Graph, the base class that all pygal graphs inherit from directly or indirectly, is now generic in ValueT, XLabelT, and YLabelT (with defaults Iterable[float], str and str respectively). For most usages this information is not relevant (the values you try to add will be checked for satisfaction of your specific chart class' _ValueT), but this pattern could cause unexpected behaviour in code that can deal with multiple graph types.

For example, say that you want to create a function that takes any pygal graph and renders it in the browser. Since all pygal graphs inherit from Graph, you might think of hinting it like this:

import pygal

def render_any_graph(g: pygal.Graph) -> None:
    g.render_in_browser()

But this is wrong. If you try to pass a graph instance whose values and labels types aren't exactly the same as Graph's defaults (see above), you will get a type checking error. An instance of Pie, for example, defines its _ValueT as Sequence[float] | float, which is not Iterable[float] and will therefore be rejected by the type checker.

Your options for typing code that needs to accept multiple graph types are:

  1. Narrow down the accepted types to only the graphs you need to handle, e.g.
def render_bar_or_line(g: pygal.Bar | pygal.Line) -> None:
    g.render_in_browser()
  1. Only if you truly need to accept all pygal graphs, you can use AnyGraph, a type alias (union of Graph and all its subclasses provided by pygal-stubs for convenience, but does not exist at runtime) to represent all graph types:
from pygal import AnyGraph

def render_any_graph(g: AnyGraph) -> None:
    g.render_in_browser()
  1. I cannot currently work on stubs for other map modules (both the documented France and Switzerland maps nor the various non-Kozea ones you can find on PyPI). If you want to make your own type stubs for those, you're more than welcome to do so using pygal-stubs and my world map stubs as a base. If you'd like those stubs to be compatible with pygal-stubs and a mistake in the definition of BaseMap is causing problems, please submit a PR. Once you're done making your type stubs, make an issue so I can add your wonderful contribution to this README for all pygal-stubs users to see. ↩

Metadata

Release files for pygal-stubs 3.1.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pygal-stubs 3.1.3.2
File Size Uploaded
pygal_stubs-3.1.3.2.tar.gz 22.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pygal-stubs 3.1.3.2
File Interpreter ABI Platform
pygal_stubs-3.1.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 57.4 kB

Release files / pygal_stubs-3.1.3.2.tar.gz

Download URL pygal_stubs-3.1.3.2.tar.gz
Size 22.5 kB
Tags Source
SHA-256 checksum
How to use checksums
d8f9202f29df3719d8e5874f73b5a24653b8d806609d99818de51a67bcf343e2
BLAKE2b-256 checksum
How to use checksums
7a7a04100eb376667a31cd621cb78fd90d478a4b5050d2c11f8c8dd9fe417ddb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via Hatch/1.18.0 {"ci":null,"cpu":"x86_64","distro":{"id":"zena","libc":{"lib":"glibc","version":"2.39"},"name":"Linux Mint","version":"22.3"},"implementation":{"name":"CPython","version":"3.10.20"},"installer":{"name":"hatch","version":"1.18.0"},"openssl_version":"OpenSSL 3.5.7 9 Jun 2026","python":"3.10.20","system":{"name":"Linux","release":"7.0.0-31-generic"}} HTTPX2/2.12.0

Release files / pygal_stubs-3.1.3.2-py3-none-any.whl

Download URL pygal_stubs-3.1.3.2-py3-none-any.whl
Size 34.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5d9db38496929180218b030db1130b6f60ccdd73e1f322b837e05513ec3f78c0
BLAKE2b-256 checksum
How to use checksums
f543a814637099e876d5700d52cb760c7037f8f20970cbf70ffc0ef036ae4314
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via Hatch/1.18.0 {"ci":null,"cpu":"x86_64","distro":{"id":"zena","libc":{"lib":"glibc","version":"2.39"},"name":"Linux Mint","version":"22.3"},"implementation":{"name":"CPython","version":"3.10.20"},"installer":{"name":"hatch","version":"1.18.0"},"openssl_version":"OpenSSL 3.5.7 9 Jun 2026","python":"3.10.20","system":{"name":"Linux","release":"7.0.0-31-generic"}} HTTPX2/2.12.0

Release history Release notifications | RSS feed

This release

3.1.3.2 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page