matplotlib-dark 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eduardo J. Barrios
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: matplotlib-dark
3
+ Version: 0.1.0
4
+ Summary: Automatic dark themes for Matplotlib, with one-line activation
5
+ Author-email: "Eduardo J. Barrios" <edujbarrios@outlook.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/edujbarrios/matplotlib-dark
8
+ Project-URL: Documentation, https://github.com/edujbarrios/matplotlib-dark#readme
9
+ Project-URL: Repository, https://github.com/edujbarrios/matplotlib-dark
10
+ Project-URL: Issues, https://github.com/edujbarrios/matplotlib-dark/issues
11
+ Project-URL: Changelog, https://github.com/edujbarrios/matplotlib-dark/blob/main/CHANGELOG.md
12
+ Keywords: matplotlib,dark-mode,visualization,plotting,theme
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Scientific/Engineering :: Visualization
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: matplotlib>=3.5.0
26
+ Provides-Extra: test
27
+ Requires-Dist: pytest>=7; extra == "test"
28
+ Provides-Extra: dev
29
+ Requires-Dist: build>=1; extra == "dev"
30
+ Requires-Dist: pytest>=7; extra == "dev"
31
+ Requires-Dist: twine>=5; extra == "dev"
32
+ Dynamic: license-file
33
+
34
+ <div align="center">
35
+
36
+ # matplotlib-dark
37
+
38
+ **Automatic dark mode for Matplotlib — polished charts without designing a theme.**
39
+
40
+ [![CI](https://github.com/edujbarrios/matplotlib-dark/actions/workflows/ci.yml/badge.svg)](https://github.com/edujbarrios/matplotlib-dark/actions/workflows/ci.yml)
41
+ [![PyPI](https://img.shields.io/pypi/v/matplotlib-dark)](https://pypi.org/project/matplotlib-dark/)
42
+ [![Python](https://img.shields.io/pypi/pyversions/matplotlib-dark)](https://pypi.org/project/matplotlib-dark/)
43
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
44
+
45
+ </div>
46
+
47
+ `matplotlib-dark` is the automatic alternative to hand-picking backgrounds,
48
+ grid colors, text contrast, and line palettes for every chart. Activate it in
49
+ one line, then keep using the Matplotlib API you already know.
50
+
51
+ ![Six matplotlib-dark themes compared](https://raw.githubusercontent.com/edujbarrios/matplotlib-dark/main/images/theme_comparison.png)
52
+
53
+ ## Installation
54
+
55
+ ```bash
56
+ python -m pip install matplotlib-dark
57
+ ```
58
+
59
+ Python 3.9+ and Matplotlib 3.5+ are supported.
60
+
61
+ ## Quick start
62
+
63
+ ```python
64
+ import matplotlib.pyplot as plt
65
+ import matplotlib_dark as mdk
66
+
67
+ mdk.dark_mode() # That's it: every following chart uses dark mode.
68
+
69
+ plt.plot([1, 2, 3, 4], [1, 4, 2, 3])
70
+ plt.title("Ready for the dark")
71
+ plt.show()
72
+ ```
73
+
74
+ No custom CSS, manual color selection, or complex design code is required.
75
+
76
+ ## Choose a theme
77
+
78
+ ```python
79
+ mdk.dark_mode("nord")
80
+ ```
81
+
82
+ Six ready-to-use themes are included: `default`, `nord`, `monokai`,
83
+ `dracula`, `neon`, and `material`.
84
+
85
+ ```python
86
+ print(mdk.get_available_themes())
87
+ ```
88
+
89
+ ## Apply dark mode temporarily
90
+
91
+ Use the context manager when only some charts should be dark. Your previous
92
+ Matplotlib configuration is restored automatically, even if plotting fails.
93
+
94
+ ```python
95
+ with mdk.dark_theme("dracula"):
96
+ plt.plot([1, 2, 3], [3, 1, 4])
97
+ plt.savefig("dark-chart.png")
98
+ ```
99
+
100
+ For global mode, restore your original configuration explicitly:
101
+
102
+ ```python
103
+ mdk.dark_mode("material")
104
+ # Create charts...
105
+ mdk.light_mode()
106
+ ```
107
+
108
+ ## Why matplotlib-dark?
109
+
110
+ - One-line automatic dark mode
111
+ - Six coordinated color palettes
112
+ - Works with the complete Matplotlib API
113
+ - Global mode or safe, temporary context manager
114
+ - Dark backgrounds are preserved when saving figures
115
+ - Zero dependencies beyond Matplotlib
116
+
117
+ ## Development
118
+
119
+ ```bash
120
+ git clone https://github.com/edujbarrios/matplotlib-dark.git
121
+ cd matplotlib-dark
122
+ python -m pip install -e ".[dev]"
123
+ python -m pytest
124
+ python -m build
125
+ python -m twine check dist/*
126
+ ```
127
+
128
+ ## License
129
+
130
+ MIT © Eduardo J. Barrios
@@ -0,0 +1,97 @@
1
+ <div align="center">
2
+
3
+ # matplotlib-dark
4
+
5
+ **Automatic dark mode for Matplotlib — polished charts without designing a theme.**
6
+
7
+ [![CI](https://github.com/edujbarrios/matplotlib-dark/actions/workflows/ci.yml/badge.svg)](https://github.com/edujbarrios/matplotlib-dark/actions/workflows/ci.yml)
8
+ [![PyPI](https://img.shields.io/pypi/v/matplotlib-dark)](https://pypi.org/project/matplotlib-dark/)
9
+ [![Python](https://img.shields.io/pypi/pyversions/matplotlib-dark)](https://pypi.org/project/matplotlib-dark/)
10
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
11
+
12
+ </div>
13
+
14
+ `matplotlib-dark` is the automatic alternative to hand-picking backgrounds,
15
+ grid colors, text contrast, and line palettes for every chart. Activate it in
16
+ one line, then keep using the Matplotlib API you already know.
17
+
18
+ ![Six matplotlib-dark themes compared](https://raw.githubusercontent.com/edujbarrios/matplotlib-dark/main/images/theme_comparison.png)
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ python -m pip install matplotlib-dark
24
+ ```
25
+
26
+ Python 3.9+ and Matplotlib 3.5+ are supported.
27
+
28
+ ## Quick start
29
+
30
+ ```python
31
+ import matplotlib.pyplot as plt
32
+ import matplotlib_dark as mdk
33
+
34
+ mdk.dark_mode() # That's it: every following chart uses dark mode.
35
+
36
+ plt.plot([1, 2, 3, 4], [1, 4, 2, 3])
37
+ plt.title("Ready for the dark")
38
+ plt.show()
39
+ ```
40
+
41
+ No custom CSS, manual color selection, or complex design code is required.
42
+
43
+ ## Choose a theme
44
+
45
+ ```python
46
+ mdk.dark_mode("nord")
47
+ ```
48
+
49
+ Six ready-to-use themes are included: `default`, `nord`, `monokai`,
50
+ `dracula`, `neon`, and `material`.
51
+
52
+ ```python
53
+ print(mdk.get_available_themes())
54
+ ```
55
+
56
+ ## Apply dark mode temporarily
57
+
58
+ Use the context manager when only some charts should be dark. Your previous
59
+ Matplotlib configuration is restored automatically, even if plotting fails.
60
+
61
+ ```python
62
+ with mdk.dark_theme("dracula"):
63
+ plt.plot([1, 2, 3], [3, 1, 4])
64
+ plt.savefig("dark-chart.png")
65
+ ```
66
+
67
+ For global mode, restore your original configuration explicitly:
68
+
69
+ ```python
70
+ mdk.dark_mode("material")
71
+ # Create charts...
72
+ mdk.light_mode()
73
+ ```
74
+
75
+ ## Why matplotlib-dark?
76
+
77
+ - One-line automatic dark mode
78
+ - Six coordinated color palettes
79
+ - Works with the complete Matplotlib API
80
+ - Global mode or safe, temporary context manager
81
+ - Dark backgrounds are preserved when saving figures
82
+ - Zero dependencies beyond Matplotlib
83
+
84
+ ## Development
85
+
86
+ ```bash
87
+ git clone https://github.com/edujbarrios/matplotlib-dark.git
88
+ cd matplotlib-dark
89
+ python -m pip install -e ".[dev]"
90
+ python -m pytest
91
+ python -m build
92
+ python -m twine check dist/*
93
+ ```
94
+
95
+ ## License
96
+
97
+ MIT © Eduardo J. Barrios
@@ -0,0 +1,57 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "matplotlib-dark"
7
+ version = "0.1.0"
8
+ description = "Automatic dark themes for Matplotlib, with one-line activation"
9
+ readme = "README.md"
10
+ authors = [
11
+ {name = "Eduardo J. Barrios", email = "edujbarrios@outlook.com"}
12
+ ]
13
+ license = "MIT"
14
+ license-files = ["LICENSE"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "Intended Audience :: Science/Research",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.9",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Topic :: Scientific/Engineering :: Visualization",
25
+ ]
26
+ keywords = ["matplotlib", "dark-mode", "visualization", "plotting", "theme"]
27
+ dependencies = [
28
+ "matplotlib>=3.5.0",
29
+ ]
30
+ requires-python = ">=3.9"
31
+
32
+ [project.optional-dependencies]
33
+ test = [
34
+ "pytest>=7",
35
+ ]
36
+ dev = [
37
+ "build>=1",
38
+ "pytest>=7",
39
+ "twine>=5",
40
+ ]
41
+
42
+ [project.urls]
43
+ Homepage = "https://github.com/edujbarrios/matplotlib-dark"
44
+ Documentation = "https://github.com/edujbarrios/matplotlib-dark#readme"
45
+ Repository = "https://github.com/edujbarrios/matplotlib-dark"
46
+ Issues = "https://github.com/edujbarrios/matplotlib-dark/issues"
47
+ Changelog = "https://github.com/edujbarrios/matplotlib-dark/blob/main/CHANGELOG.md"
48
+
49
+ [tool.setuptools.packages.find]
50
+ where = ["src"]
51
+
52
+ [tool.setuptools.package-data]
53
+ matplotlib_dark = ["py.typed"]
54
+
55
+ [tool.pytest.ini_options]
56
+ addopts = "-ra"
57
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,19 @@
1
+ """
2
+ matplotlib-dark: matplotlib, but in dark mode
3
+ A lightweight package to apply dark themes to matplotlib plots.
4
+ """
5
+
6
+ __version__ = "0.1.0"
7
+ __author__ = "Eduardo J. Barrios"
8
+
9
+ from .core import dark_mode, dark_theme, get_available_themes, light_mode, set_theme
10
+ from .themes import THEMES
11
+
12
+ __all__ = [
13
+ "dark_mode",
14
+ "dark_theme",
15
+ "light_mode",
16
+ "set_theme",
17
+ "get_available_themes",
18
+ "THEMES",
19
+ ]
@@ -0,0 +1,148 @@
1
+ """Core functionality for matplotlib-dark."""
2
+
3
+ from contextlib import contextmanager
4
+ from typing import Iterator, List, Optional
5
+
6
+ import matplotlib as mpl
7
+ from matplotlib import cycler
8
+
9
+ from .themes import THEMES
10
+
11
+ # Store original rcParams
12
+ _original_params: Optional[dict] = None
13
+
14
+
15
+ def dark_mode(theme: str = "default") -> None:
16
+ """
17
+ Apply a dark theme to matplotlib plots.
18
+
19
+ Parameters
20
+ ----------
21
+ theme : str, optional
22
+ The name of the theme to apply. Available themes:
23
+ 'default', 'nord', 'monokai', 'dracula'
24
+ Default is 'default'.
25
+
26
+ Examples
27
+ --------
28
+ >>> import matplotlib_dark as mdk
29
+ >>> mdk.dark_mode()
30
+ >>> mdk.dark_mode(theme='nord')
31
+ """
32
+ set_theme(theme)
33
+
34
+
35
+ def light_mode() -> None:
36
+ """
37
+ Restore matplotlib to its default light theme.
38
+
39
+ Examples
40
+ --------
41
+ >>> import matplotlib_dark as mdk
42
+ >>> mdk.dark_mode()
43
+ >>> # ... create plots ...
44
+ >>> mdk.light_mode() # Restore defaults
45
+ """
46
+ global _original_params
47
+
48
+ if _original_params is None:
49
+ mpl.rcdefaults()
50
+ else:
51
+ mpl.rcParams.update(_original_params)
52
+ _original_params = None
53
+
54
+
55
+ def set_theme(theme_name: str) -> None:
56
+ """
57
+ Set a specific dark theme.
58
+
59
+ Parameters
60
+ ----------
61
+ theme_name : str
62
+ The name of the theme to apply.
63
+
64
+ Raises
65
+ ------
66
+ ValueError
67
+ If the theme name is not recognized.
68
+ """
69
+ global _original_params
70
+
71
+ if theme_name not in THEMES:
72
+ available = ', '.join(THEMES.keys())
73
+ raise ValueError(
74
+ f"Unknown theme '{theme_name}'. "
75
+ f"Available themes: {available}"
76
+ )
77
+
78
+ # Save original params on first call
79
+ if _original_params is None:
80
+ _original_params = dict(mpl.rcParams)
81
+
82
+ theme = THEMES[theme_name]
83
+
84
+ # Apply theme colors
85
+ mpl.rcParams.update({
86
+ 'figure.facecolor': theme['bg_color'],
87
+ 'axes.facecolor': theme['axes_bg'],
88
+ 'axes.edgecolor': theme['text_color'],
89
+ 'axes.labelcolor': theme['text_color'],
90
+ 'axes.grid': True,
91
+ 'grid.color': theme['grid_color'],
92
+ 'grid.alpha': 0.3,
93
+ 'text.color': theme['text_color'],
94
+ 'xtick.color': theme['text_color'],
95
+ 'ytick.color': theme['text_color'],
96
+ 'legend.facecolor': theme['axes_bg'],
97
+ 'legend.edgecolor': theme['grid_color'],
98
+ 'savefig.facecolor': theme['bg_color'],
99
+ 'savefig.edgecolor': theme['bg_color'],
100
+ })
101
+
102
+ # Set color cycle
103
+ colors = theme.get('colors', [
104
+ '#8FBCBB', '#88C0D0', '#81A1C1', '#5E81AC',
105
+ '#BF616A', '#D08770', '#EBCB8B', '#A3BE8C', '#B48EAD'
106
+ ])
107
+ mpl.rcParams['axes.prop_cycle'] = cycler(color=colors)
108
+
109
+
110
+ def get_available_themes() -> List[str]:
111
+ """
112
+ Get a list of available theme names.
113
+
114
+ Returns
115
+ -------
116
+ list
117
+ List of available theme names.
118
+
119
+ Examples
120
+ --------
121
+ >>> import matplotlib_dark as mdk
122
+ >>> themes = mdk.get_available_themes()
123
+ >>> print(themes)
124
+ ['default', 'nord', 'monokai', 'dracula']
125
+ """
126
+ return list(THEMES.keys())
127
+
128
+
129
+ @contextmanager
130
+ def dark_theme(theme: str = "default") -> Iterator[None]:
131
+ """Temporarily apply a dark theme and restore the current style afterwards.
132
+
133
+ This is safe to nest and is useful when only one plot should use the theme.
134
+
135
+ Examples
136
+ --------
137
+ >>> import matplotlib_dark as mdk
138
+ >>> with mdk.dark_theme("nord"):
139
+ ... pass # Create and save a plot here.
140
+ """
141
+ global _original_params
142
+ previous_original = _original_params
143
+ with mpl.rc_context():
144
+ set_theme(theme)
145
+ try:
146
+ yield
147
+ finally:
148
+ _original_params = previous_original
@@ -0,0 +1,104 @@
1
+ """Dark theme definitions for matplotlib-dark"""
2
+
3
+ THEMES = {
4
+ 'default': {
5
+ 'bg_color': '#1e1e1e',
6
+ 'axes_bg': '#2d2d2d',
7
+ 'text_color': '#e4e4e4',
8
+ 'grid_color': '#505050',
9
+ 'colors': [
10
+ '#61AFEF', # Blue
11
+ '#98C379', # Green
12
+ '#E06C75', # Red
13
+ '#C678DD', # Purple
14
+ '#56B6C2', # Cyan
15
+ '#E5C07B', # Yellow
16
+ '#D19A66', # Orange
17
+ ]
18
+ },
19
+
20
+ 'nord': {
21
+ 'bg_color': '#2E3440',
22
+ 'axes_bg': '#3B4252',
23
+ 'text_color': '#ECEFF4',
24
+ 'grid_color': '#4C566A',
25
+ 'colors': [
26
+ '#88C0D0', # Frost Blue
27
+ '#A3BE8C', # Aurora Green
28
+ '#EBCB8B', # Aurora Yellow
29
+ '#D08770', # Aurora Orange
30
+ '#BF616A', # Aurora Red
31
+ '#B48EAD', # Aurora Purple
32
+ '#5E81AC', # Frost Dark Blue
33
+ '#8FBCBB', # Frost Teal
34
+ '#81A1C1', # Frost Light Blue
35
+ ]
36
+ },
37
+
38
+ 'monokai': {
39
+ 'bg_color': '#272822',
40
+ 'axes_bg': '#3E3D32',
41
+ 'text_color': '#F8F8F2',
42
+ 'grid_color': '#75715E',
43
+ 'colors': [
44
+ '#66D9EF', # Cyan
45
+ '#A6E22E', # Green
46
+ '#F92672', # Pink
47
+ '#FD971F', # Orange
48
+ '#AE81FF', # Purple
49
+ '#E6DB74', # Yellow
50
+ ]
51
+ },
52
+
53
+ 'dracula': {
54
+ 'bg_color': '#282A36',
55
+ 'axes_bg': '#44475A',
56
+ 'text_color': '#F8F8F2',
57
+ 'grid_color': '#6272A4',
58
+ 'colors': [
59
+ '#8BE9FD', # Cyan
60
+ '#50FA7B', # Green
61
+ '#FFB86C', # Orange
62
+ '#FF79C6', # Pink
63
+ '#BD93F9', # Purple
64
+ '#FF5555', # Red
65
+ '#F1FA8C', # Yellow
66
+ ]
67
+ },
68
+
69
+ 'neon': {
70
+ 'bg_color': '#0a0a0a',
71
+ 'axes_bg': '#1a1a1a',
72
+ 'text_color': '#ffffff',
73
+ 'grid_color': '#ffffff40',
74
+ 'colors': [
75
+ '#00ffff', # Cyan neón
76
+ '#00ff00', # Verde neón
77
+ '#ff00ff', # Magenta neón
78
+ '#ffff00', # Amarillo neón
79
+ '#ff0080', # Rosa neón
80
+ '#00ff80', # Verde-cyan neón
81
+ '#ff00ff', # Púrpura neón
82
+ '#ff8000', # Naranja neón
83
+ '#0080ff', # Azul neón
84
+ ]
85
+ },
86
+
87
+ 'material': {
88
+ 'bg_color': '#212121',
89
+ 'axes_bg': '#303030',
90
+ 'text_color': '#FFFFFF',
91
+ 'grid_color': '#424242',
92
+ 'colors': [
93
+ '#2196F3', # Material Blue
94
+ '#4CAF50', # Material Green
95
+ '#FF5722', # Material Deep Orange
96
+ '#9C27B0', # Material Purple
97
+ '#00BCD4', # Material Cyan
98
+ '#FFEB3B', # Material Yellow
99
+ '#E91E63', # Material Pink
100
+ '#FF9800', # Material Orange
101
+ '#009688', # Material Teal
102
+ ]
103
+ },
104
+ }
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: matplotlib-dark
3
+ Version: 0.1.0
4
+ Summary: Automatic dark themes for Matplotlib, with one-line activation
5
+ Author-email: "Eduardo J. Barrios" <edujbarrios@outlook.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/edujbarrios/matplotlib-dark
8
+ Project-URL: Documentation, https://github.com/edujbarrios/matplotlib-dark#readme
9
+ Project-URL: Repository, https://github.com/edujbarrios/matplotlib-dark
10
+ Project-URL: Issues, https://github.com/edujbarrios/matplotlib-dark/issues
11
+ Project-URL: Changelog, https://github.com/edujbarrios/matplotlib-dark/blob/main/CHANGELOG.md
12
+ Keywords: matplotlib,dark-mode,visualization,plotting,theme
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Scientific/Engineering :: Visualization
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: matplotlib>=3.5.0
26
+ Provides-Extra: test
27
+ Requires-Dist: pytest>=7; extra == "test"
28
+ Provides-Extra: dev
29
+ Requires-Dist: build>=1; extra == "dev"
30
+ Requires-Dist: pytest>=7; extra == "dev"
31
+ Requires-Dist: twine>=5; extra == "dev"
32
+ Dynamic: license-file
33
+
34
+ <div align="center">
35
+
36
+ # matplotlib-dark
37
+
38
+ **Automatic dark mode for Matplotlib — polished charts without designing a theme.**
39
+
40
+ [![CI](https://github.com/edujbarrios/matplotlib-dark/actions/workflows/ci.yml/badge.svg)](https://github.com/edujbarrios/matplotlib-dark/actions/workflows/ci.yml)
41
+ [![PyPI](https://img.shields.io/pypi/v/matplotlib-dark)](https://pypi.org/project/matplotlib-dark/)
42
+ [![Python](https://img.shields.io/pypi/pyversions/matplotlib-dark)](https://pypi.org/project/matplotlib-dark/)
43
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
44
+
45
+ </div>
46
+
47
+ `matplotlib-dark` is the automatic alternative to hand-picking backgrounds,
48
+ grid colors, text contrast, and line palettes for every chart. Activate it in
49
+ one line, then keep using the Matplotlib API you already know.
50
+
51
+ ![Six matplotlib-dark themes compared](https://raw.githubusercontent.com/edujbarrios/matplotlib-dark/main/images/theme_comparison.png)
52
+
53
+ ## Installation
54
+
55
+ ```bash
56
+ python -m pip install matplotlib-dark
57
+ ```
58
+
59
+ Python 3.9+ and Matplotlib 3.5+ are supported.
60
+
61
+ ## Quick start
62
+
63
+ ```python
64
+ import matplotlib.pyplot as plt
65
+ import matplotlib_dark as mdk
66
+
67
+ mdk.dark_mode() # That's it: every following chart uses dark mode.
68
+
69
+ plt.plot([1, 2, 3, 4], [1, 4, 2, 3])
70
+ plt.title("Ready for the dark")
71
+ plt.show()
72
+ ```
73
+
74
+ No custom CSS, manual color selection, or complex design code is required.
75
+
76
+ ## Choose a theme
77
+
78
+ ```python
79
+ mdk.dark_mode("nord")
80
+ ```
81
+
82
+ Six ready-to-use themes are included: `default`, `nord`, `monokai`,
83
+ `dracula`, `neon`, and `material`.
84
+
85
+ ```python
86
+ print(mdk.get_available_themes())
87
+ ```
88
+
89
+ ## Apply dark mode temporarily
90
+
91
+ Use the context manager when only some charts should be dark. Your previous
92
+ Matplotlib configuration is restored automatically, even if plotting fails.
93
+
94
+ ```python
95
+ with mdk.dark_theme("dracula"):
96
+ plt.plot([1, 2, 3], [3, 1, 4])
97
+ plt.savefig("dark-chart.png")
98
+ ```
99
+
100
+ For global mode, restore your original configuration explicitly:
101
+
102
+ ```python
103
+ mdk.dark_mode("material")
104
+ # Create charts...
105
+ mdk.light_mode()
106
+ ```
107
+
108
+ ## Why matplotlib-dark?
109
+
110
+ - One-line automatic dark mode
111
+ - Six coordinated color palettes
112
+ - Works with the complete Matplotlib API
113
+ - Global mode or safe, temporary context manager
114
+ - Dark backgrounds are preserved when saving figures
115
+ - Zero dependencies beyond Matplotlib
116
+
117
+ ## Development
118
+
119
+ ```bash
120
+ git clone https://github.com/edujbarrios/matplotlib-dark.git
121
+ cd matplotlib-dark
122
+ python -m pip install -e ".[dev]"
123
+ python -m pytest
124
+ python -m build
125
+ python -m twine check dist/*
126
+ ```
127
+
128
+ ## License
129
+
130
+ MIT © Eduardo J. Barrios
@@ -0,0 +1,13 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/matplotlib_dark/__init__.py
5
+ src/matplotlib_dark/core.py
6
+ src/matplotlib_dark/py.typed
7
+ src/matplotlib_dark/themes.py
8
+ src/matplotlib_dark.egg-info/PKG-INFO
9
+ src/matplotlib_dark.egg-info/SOURCES.txt
10
+ src/matplotlib_dark.egg-info/dependency_links.txt
11
+ src/matplotlib_dark.egg-info/requires.txt
12
+ src/matplotlib_dark.egg-info/top_level.txt
13
+ tests/test_core.py
@@ -0,0 +1,9 @@
1
+ matplotlib>=3.5.0
2
+
3
+ [dev]
4
+ build>=1
5
+ pytest>=7
6
+ twine>=5
7
+
8
+ [test]
9
+ pytest>=7
@@ -0,0 +1 @@
1
+ matplotlib_dark
@@ -0,0 +1,97 @@
1
+ """Tests for matplotlib-dark core functionality"""
2
+
3
+ import pytest
4
+ import matplotlib.pyplot as plt
5
+ import matplotlib_dark as mdk
6
+
7
+
8
+ @pytest.fixture(autouse=True)
9
+ def restore_matplotlib_style():
10
+ """Keep global Matplotlib state from leaking between tests."""
11
+ original = plt.rcParams.copy()
12
+ yield
13
+ plt.rcParams.update(original)
14
+
15
+
16
+ def test_dark_mode_default():
17
+ """Test applying default dark mode"""
18
+ mdk.dark_mode()
19
+ assert plt.rcParams['figure.facecolor'] == '#1e1e1e'
20
+ mdk.light_mode()
21
+
22
+
23
+ def test_dark_mode_nord():
24
+ """Test applying nord theme"""
25
+ mdk.dark_mode(theme='nord')
26
+ assert plt.rcParams['figure.facecolor'] == '#2E3440'
27
+ mdk.light_mode()
28
+
29
+
30
+ def test_dark_mode_monokai():
31
+ """Test applying monokai theme"""
32
+ mdk.dark_mode(theme='monokai')
33
+ assert plt.rcParams['figure.facecolor'] == '#272822'
34
+ mdk.light_mode()
35
+
36
+
37
+ def test_dark_mode_dracula():
38
+ """Test applying dracula theme"""
39
+ mdk.dark_mode(theme='dracula')
40
+ assert plt.rcParams['figure.facecolor'] == '#282A36'
41
+ mdk.light_mode()
42
+
43
+
44
+ def test_invalid_theme():
45
+ """Test that invalid theme raises ValueError"""
46
+ with pytest.raises(ValueError):
47
+ mdk.dark_mode(theme='nonexistent')
48
+
49
+
50
+ def test_light_mode_restore():
51
+ """Test that light mode restores defaults"""
52
+ original_bg = plt.rcParams['figure.facecolor']
53
+ mdk.dark_mode()
54
+ mdk.light_mode()
55
+ assert plt.rcParams['figure.facecolor'] == original_bg
56
+
57
+
58
+ def test_get_available_themes():
59
+ """Test getting available themes"""
60
+ themes = mdk.get_available_themes()
61
+ assert isinstance(themes, list)
62
+ assert 'default' in themes
63
+ assert 'nord' in themes
64
+ assert 'monokai' in themes
65
+ assert 'dracula' in themes
66
+ assert 'neon' in themes
67
+ assert 'material' in themes
68
+
69
+
70
+ def test_set_theme():
71
+ """Test set_theme function"""
72
+ mdk.set_theme('nord')
73
+ assert plt.rcParams['figure.facecolor'] == '#2E3440'
74
+ mdk.light_mode()
75
+
76
+
77
+ def test_switching_theme_still_restores_original_style():
78
+ original_bg = plt.rcParams['figure.facecolor']
79
+ mdk.dark_mode('nord')
80
+ mdk.dark_mode('dracula')
81
+ mdk.light_mode()
82
+ assert plt.rcParams['figure.facecolor'] == original_bg
83
+
84
+
85
+ def test_dark_theme_context_restores_style():
86
+ original_bg = plt.rcParams['figure.facecolor']
87
+ with mdk.dark_theme('material'):
88
+ assert plt.rcParams['figure.facecolor'] == '#212121'
89
+ assert plt.rcParams['figure.facecolor'] == original_bg
90
+
91
+
92
+ def test_dark_theme_context_restores_style_after_error():
93
+ original_bg = plt.rcParams['figure.facecolor']
94
+ with pytest.raises(RuntimeError):
95
+ with mdk.dark_theme('neon'):
96
+ raise RuntimeError('plot failed')
97
+ assert plt.rcParams['figure.facecolor'] == original_bg