Skip to content

Commit 2660f5d

Browse files
authored
Type information and datetime improvements (#63)
1 parent ebe04df commit 2660f5d

62 files changed

Lines changed: 5519 additions & 4180 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/CI.yml

Lines changed: 11 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,67 +14,35 @@ jobs:
1414
fail-fast: false
1515
matrix:
1616
os: [ubuntu-latest, macos-latest, windows-latest]
17-
python-version: ['pypy-3.8', 3.8, 'pypy-3.9', 3.9, '3.10', 'pypy-3.10', '3.11', '3.12']
18-
include:
19-
- os: ubuntu-latest
20-
path: ~/.cache/pip
21-
- os: macos-latest
22-
path: ~/Library/Caches/pip
23-
- os: windows-latest
24-
path: ~\AppData\Local\pip\Cache
17+
python-version: ['3.10', 'pypy-3.11', '3.11', '3.12', '3.13', '3.14']
2518
exclude:
2619
- os: macos-latest
27-
python-version: 'pypy-3.8'
28-
- os: macos-latest
29-
python-version: 'pypy-3.9'
30-
- os: macos-latest
31-
python-version: 'pypy-3.10'
32-
- os: windows-latest
33-
python-version: 'pypy-3.8'
34-
- os: windows-latest
35-
python-version: 'pypy-3.9'
20+
python-version: 'pypy-3.11'
3621
- os: windows-latest
37-
python-version: 'pypy-3.10'
22+
python-version: 'pypy-3.11'
3823
defaults:
3924
run:
4025
shell: bash
4126

4227
runs-on: ${{ matrix.os }}
4328
env:
4429
PYTHONIOENCODING: UTF-8
30+
UV_PYTHON: ${{ matrix.python-version }}
4531
steps:
4632
- name: Checkout repo
47-
uses: actions/checkout@v4
33+
uses: actions/checkout@v6
4834

4935
- name: Set Up Python ${{ matrix.python-version }}
50-
uses: actions/setup-python@v4
51-
with:
52-
python-version: ${{ matrix.python-version }}
53-
54-
- name: Cache Install
55-
id: restore-cache
56-
uses: actions/cache@v4
57-
with:
58-
path: |
59-
${{ matrix.path }}
60-
poetry.lock
61-
key: ${{ matrix.os }}-${{ matrix.python-version }}-pip-${{ hashFiles('pyproject.toml') }}-${{ hashFiles('tests/requirements.txt') }}
62-
63-
- name: Install Poetry
64-
uses: snok/install-poetry@v1
65-
with:
66-
version: ${{ startsWith(matrix.python-version, 'pypy') && '1.2.2' || '1.7.0' }}
67-
virtualenvs-create: false
36+
uses: astral-sh/setup-uv@v7
6837

69-
- name: Install
70-
run: poetry install
38+
- if: ${{ ! startsWith(matrix.python-version, 'pypy-') }}
39+
run: make check
7140

72-
- name: Style
73-
if: ${{ ! startsWith(matrix.python-version, 'pypy-') }}
74-
run: poetry run flake8 tests/ plotille/ examples/
41+
- if: ${{ ! startsWith(matrix.python-version, 'pypy-') }}
42+
run: make typing
7543

7644
- name: Tests
77-
run: poetry run pytest -s -vvv
45+
run: make tests
7846

7947
- uses: codecov/codecov-action@v4
8048
with:

.github/workflows/Publish.yml

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,20 @@ jobs:
1313

1414
steps:
1515
- name: Checkout repo
16-
uses: actions/checkout@v3
16+
uses: actions/checkout@v6
1717

18-
- name: Set Up Python 3.7
19-
uses: actions/setup-python@v4
18+
- name: Set Up Python 3.12
19+
uses: astral-sh/setup-uv@v7
2020
with:
21-
python-version: 3.7
22-
23-
- name: Install Poetry
24-
uses: snok/install-poetry@v1
25-
with:
26-
version: 1.2.2
21+
python-version: 3.12
2722

2823
- name: Build
29-
run: poetry build -vvv -f sdist
24+
run: uv build -v
3025

3126
- name: Archive artifacts
32-
uses: actions/upload-artifact@v3
27+
uses: actions/upload-artifact@v6
3328
with:
34-
path: dist/*.tar.gz
29+
path: dist/*
3530

3631
- name: Publish
37-
run: poetry publish -vvv -n -u tammoippen -p ${{ secrets.PYPI_PASS }}
32+
run: uv publish -v -n -t ${{ secrets.PYPI_PASS }}

.github/workflows/codeql.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727

2828
steps:
2929
- name: Checkout repository
30-
uses: actions/checkout@v3
30+
uses: actions/checkout@v6
3131

3232
# Initializes the CodeQL tools for scanning.
3333
- name: Initialize CodeQL

LICENSE.txt

Lines changed: 0 additions & 21 deletions
This file was deleted.

Makefile

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
.PHONY: style tests install
22

3-
style:
4-
poetry run flake8 tests/ plotille/ examples/
3+
fmt:
4+
uv run --locked ruff format .
5+
uv run --locked ruff check --fix .
6+
7+
check:
8+
uv run --locked ruff format --check .
9+
uv run --locked ruff check .
10+
11+
typing:
12+
uv run --locked mypy ./plotille
13+
# uv run --locked ty check ./plotille
514

615
tests:
7-
poetry run pytest -s -vvv
16+
uv run --locked pytest -s -vvv
817

918
install:
10-
poetry install
19+
uv install

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44

55
[![CI](https://github.com/tammoippen/plotille/actions/workflows/CI.yml/badge.svg)](https://github.com/tammoippen/plotille/actions/workflows/CI.yml)
66
[![codecov](https://codecov.io/gh/tammoippen/plotille/branch/master/graph/badge.svg?token=OGWI832JNM)](https://codecov.io/gh/tammoippen/plotille)
7-
[![Tested CPython Versions](https://img.shields.io/badge/cpython-3.8%2C%203.9%2C%203.10%2C%203.11%2C%203.12-brightgreen.svg)](https://img.shields.io/badge/cpython-3.8%2C%203.9%2C%203.10%2C%203.11%2C%203.12-brightgreen.svg)
8-
[![Tested PyPy Versions](https://img.shields.io/badge/pypy-3.8%2C%203.9-brightgreen.svg)](https://img.shields.io/badge/pypy-3.8%2C%203.9%2C%203.10-brightgreen.svg)
7+
[![Tested CPython Versions](https://img.shields.io/badge/cpython-3.10%2C%203.11%2C%203.12%2C%203.13%2C%203.14-brightgreen.svg)](https://img.shields.io/badge/cpython-3.10%2C%203.11%2C%203.12%2C%203.13%203.14-brightgreen.svg)
8+
[![Tested PyPy Versions](https://img.shields.io/badge/3.11-brightgreen.svg)](https://img.shields.io/badge/pypy-3.11-brightgreen.svg)
99
[![PyPi version](https://img.shields.io/pypi/v/plotille.svg)](https://pypi.python.org/pypi/plotille)
1010
[![Downloads](https://pepy.tech/badge/plotille/month)](https://pepy.tech/project/plotille)
1111
[![PyPi license](https://img.shields.io/pypi/l/plotille.svg)](https://pypi.python.org/pypi/plotille)
12+
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
1213

1314
Plots, scatter plots, histograms and heatmaps in the terminal using braille dots, and foreground and background colors - with no dependencies. Make complex figures using the Figure class or make fast and simple plots using graphing function - similar to a very small sibling to matplotlib. Or use the canvas to plot dots, lines and images yourself.
1415

@@ -25,7 +26,7 @@ Similar to other libraries:
2526
- like [termgraph](https://github.com/sgeisler/termgraph) (not on pypi), but very different style.
2627
- like [terminalplot](https://github.com/kressi/terminalplot), but with braille, X/Y-axis, histogram, linear interpolation.
2728

28-
Basic support for timeseries plotting is provided with release 3.2: for any `X` or `Y` values you can also add `datetime.datetime`, `pendulum.datetime` or `numpy.datetime64` values. Labels are generated respecting the difference of `x_limits` and `y_limits`.
29+
Basic support for timeseries plotting is provided with release 3.2: for any `X` or `Y` values you can also add `datetime.datetime` or `numpy.datetime64` values. Labels are generated respecting the difference of `x_limits` and `y_limits`.
2930

3031
Support for heatmaps using background colors for figures and displaying images binary with braille, or in color with background colors using the canvas - provided with release 4.0
3132

@@ -613,4 +614,4 @@ In [29]: print(cvs.plot())
613614
614615
If you like the project and want to buy me a coffee, feel free to send some coins ;)
615616
616-
[<img src="https://api.gitsponsors.com/api/badge/img?id=105019800" height="20">](https://api.gitsponsors.com/api/badge/link?p=gkBol1u2+g2pjgZGRaDLy4k0XbPDRXdPWJWnueCUGo/wcSsqyE8nr+n9nvqfeuqXee6JhLARGZS5bP0ZvorS7y6t4INyHLtTrprYh9c+MYkqAZeSqNIf7WL0ZRTI070RVQA3L9QW9IZNFlMbulW+BQ==)
617+
[<img src="https://api.gitsponsors.com/api/badge/img?id=105019800" height="20">](https://api.gitsponsors.com/api/badge/link?p=gkBol1u2+g2pjgZGRaDLy4k0XbPDRXdPWJWnueCUGo/wcSsqyE8nr+n9nvqfeuqXee6JhLARGZS5bP0ZvorS7y6t4INyHLtTrprYh9c+MYkqAZeSqNIf7WL0ZRTI070RVQA3L9QW9IZNFlMbulW+BQ==)

examples/color_example.py

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
# -*- coding: utf-8 -*-
2-
from __future__ import absolute_import, division, print_function, unicode_literals
3-
41
# The MIT License
52

6-
# Copyright (c) 2017 - 2024 Tammo Ippen, tammo.ippen@posteo.de
3+
# Copyright (c) 2017 - 2025 Tammo Ippen, tammo.ippen@posteo.de
74

85
# Permission is hereby granted, free of charge, to any person obtaining a copy
96
# of this software and associated documentation files (the "Software"), to deal
@@ -29,35 +26,59 @@
2926

3027

3128
def main():
32-
print(color('Do not print colors, if `no_color` is set to True', fg='red', no_color=True))
33-
print(color('You can set a foreground', fg='red'))
34-
print(color('and a background.', bg='red'))
35-
print(color('Or both.', fg='black', bg='cyan'))
36-
37-
print(color('Aside from 4-bit / name colors', fg='green', mode='names'))
38-
print(color('you can also set 8-bit colors / 256-color lookup tables', fg=126, bg=87, mode='byte'))
39-
print(color('or go with full 24-bit rgb colors', fg=(50, 50, 50), bg=(166, 237, 240), mode='rgb'))
40-
41-
no_color = os.environ.get('NO_COLOR')
42-
os.environ['NO_COLOR'] = '1'
43-
print(color('The Environment variable `NO_COLOR` will always strip colors.', fg='red'))
29+
print(
30+
color(
31+
"Do not print colors, if `no_color` is set to True", fg="red", no_color=True
32+
)
33+
)
34+
print(color("You can set a foreground", fg="red"))
35+
print(color("and a background.", bg="red"))
36+
print(color("Or both.", fg="black", bg="cyan"))
37+
38+
print(color("Aside from 4-bit / name colors", fg="green", mode="names"))
39+
print(
40+
color(
41+
"you can also set 8-bit colors / 256-color lookup tables",
42+
fg=126,
43+
bg=87,
44+
mode="byte",
45+
)
46+
)
47+
print(
48+
color(
49+
"or go with full 24-bit rgb colors",
50+
fg=(50, 50, 50),
51+
bg=(166, 237, 240),
52+
mode="rgb",
53+
)
54+
)
55+
56+
no_color = os.environ.get("NO_COLOR")
57+
os.environ["NO_COLOR"] = "1"
58+
print(
59+
color("The Environment variable `NO_COLOR` will always strip colors.", fg="red")
60+
)
4461
if no_color:
45-
os.environ['NO_COLOR'] = no_color
62+
os.environ["NO_COLOR"] = no_color
4663
else:
47-
os.environ.pop('NO_COLOR')
48-
49-
force_color = os.environ.get('FORCE_COLOR')
50-
os.environ['FORCE_COLOR'] = '1'
51-
print(color('The Environment variable `FORCE_COLOR` allows to toggle colors,', fg='blue'))
52-
os.environ['FORCE_COLOR'] = '0'
53-
print(color('setting it to 0, none or false, strips color codes', fg='magenta'))
54-
os.environ['FORCE_COLOR'] = '1'
55-
print(color('everything else forces color codes', fg='green'))
64+
os.environ.pop("NO_COLOR")
65+
66+
force_color = os.environ.get("FORCE_COLOR")
67+
os.environ["FORCE_COLOR"] = "1"
68+
print(
69+
color(
70+
"The Environment variable `FORCE_COLOR` allows to toggle colors,", fg="blue"
71+
)
72+
)
73+
os.environ["FORCE_COLOR"] = "0"
74+
print(color("setting it to 0, none or false, strips color codes", fg="magenta"))
75+
os.environ["FORCE_COLOR"] = "1"
76+
print(color("everything else forces color codes", fg="green"))
5677
if force_color:
57-
os.environ['FORCE_COLOR'] = force_color
78+
os.environ["FORCE_COLOR"] = force_color
5879
else:
59-
os.environ.pop('FORCE_COLOR')
80+
os.environ.pop("FORCE_COLOR")
6081

6182

62-
if __name__ == '__main__':
83+
if __name__ == "__main__":
6384
main()

examples/custom_ticks_example.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
# -*- coding: utf-8 -*-
2-
from __future__ import absolute_import, division, print_function, unicode_literals
3-
41
# The MIT License
52

6-
# Copyright (c) 2017 - 2024 Tammo Ippen, tammo.ippen@posteo.de
3+
# Copyright (c) 2017 - 2025 Tammo Ippen, tammo.ippen@posteo.de
74

85
# Permission is hereby granted, free of charge, to any person obtaining a copy
96
# of this software and associated documentation files (the "Software"), to deal
@@ -51,12 +48,12 @@ def mean_y_value(Y, min_, max_):
5148

5249

5350
def str_tick(min_, max_):
54-
return '{:.3f}'.format(min_ + (max_ - min_) / 2)
51+
return f"{min_ + (max_ - min_) / 2:.3f}"
5552

5653

5754
def main():
58-
Y = [0, 10, 20, 20, 21, 25, 30, 32, 40, 44, 50] + [51.3] * 10 # noqa: N806
59-
X = list(range(len(Y))) # noqa: N806
55+
Y = [0, 10, 20, 20, 21, 25, 30, 32, 40, 44, 50] + [51.3] * 10
56+
X = list(range(len(Y)))
6057

6158
fig = plt.Figure()
6259
fig.plot(X, Y)
@@ -82,5 +79,5 @@ def main():
8279
print(fig.show())
8380

8481

85-
if __name__ == '__main__':
82+
if __name__ == "__main__":
8683
main()

examples/ellipse_example.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
# -*- coding: utf-8 -*-
2-
from __future__ import absolute_import, division, print_function, unicode_literals
3-
41
# The MIT License
52

6-
# Copyright (c) 2017 - 2024 Tammo Ippen, tammo.ippen@posteo.de
3+
# Copyright (c) 2017 - 2025 Tammo Ippen, tammo.ippen@posteo.de
74

85
# Permission is hereby granted, free of charge, to any person obtaining a copy
96
# of this software and associated documentation files (the "Software"), to deal
@@ -35,36 +32,42 @@ def main():
3532
fig.width = 50
3633
fig.height = 20
3734

38-
X1, Y1 = plt_data.ellipse(x_center=0, y_center=0, x_amplitude=0.5, y_amplitude=0.5, n=20) # noqa: N806
35+
X1, Y1 = plt_data.ellipse(
36+
x_center=0, y_center=0, x_amplitude=0.5, y_amplitude=0.5, n=20
37+
)
3938
fig.plot(X1, Y1)
4039

4140
print(fig.show(legend=True))
4241

4342
# first set
44-
X2, Y2 = plt_data.ellipse(x_center=0, y_center=0) # noqa: N806
43+
X2, Y2 = plt_data.ellipse(x_center=0, y_center=0)
4544
fig.plot(X2, Y2)
4645

47-
X3, Y3 = plt_data.ellipse(x_center=0, y_center=0, x_amplitude=0.5, y_amplitude=0.5, n=20) # noqa: N806
48-
fig.plot(X3, Y3, label='Ellipse 2')
46+
X3, Y3 = plt_data.ellipse(
47+
x_center=0, y_center=0, x_amplitude=0.5, y_amplitude=0.5, n=20
48+
)
49+
fig.plot(X3, Y3, label="Ellipse 2")
4950

5051
print(fig.show(legend=True))
5152

5253
# second set, offset
5354
fig.clear()
54-
X2, Y2 = plt_data.ellipse(x_center=0, y_center=0) # noqa: N806
55+
X2, Y2 = plt_data.ellipse(x_center=0, y_center=0)
5556
fig.plot(X2, Y2)
5657
fig.set_x_limits(min_=-10, max_=10)
5758
fig.set_y_limits(min_=-10, max_=10)
5859

5960
for xx in [-4, 0, 4]:
6061
for yy in [-4, 0, 4]:
61-
X, Y = plt_data.ellipse(x_center=xx, y_center=yy, x_amplitude=1, y_amplitude=1, n=20) # noqa: N806
62-
fig.plot(X, Y, label=('{},{}'.format(xx, yy)))
62+
X, Y = plt_data.ellipse(
63+
x_center=xx, y_center=yy, x_amplitude=1, y_amplitude=1, n=20
64+
)
65+
fig.plot(X, Y, label=(f"{xx},{yy}"))
6366

6467
fig.scatter([4], [4])
6568

6669
print(fig.show(legend=True))
6770

6871

69-
if __name__ == '__main__':
72+
if __name__ == "__main__":
7073
main()

0 commit comments

Comments
 (0)