Compare commits
5 Commits
2b0702fe36
...
0.8.4
| Author | SHA1 | Date | |
|---|---|---|---|
| 8039fb3d0b | |||
| a12b952343 | |||
| df5262ec05 | |||
| 13e366d1fe | |||
| 4d707b97e4 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -5,6 +5,8 @@ __pycache__/
|
|||||||
.ipynb_checkpoints/
|
.ipynb_checkpoints/
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
.python-version
|
.python-version
|
||||||
|
.venv/
|
||||||
|
.ruff_cache/
|
||||||
|
|
||||||
# vendor and build files
|
# vendor and build files
|
||||||
dist/
|
dist/
|
||||||
|
|||||||
167
README.md
167
README.md
@@ -1,66 +1,70 @@
|
|||||||
# Symconf
|
# Symconf
|
||||||
`symconf` is a CLI tool for managing local application configuration. It implements a
|
`symconf` is a CLI tool for managing local application configuration. It
|
||||||
general model that supports dynamically switching/reloading themes for any application,
|
implements a general model that supports dynamically switching/reloading themes
|
||||||
and provides a basic means of templatizing your config files.
|
for any application, and provides a basic means of templatizing your config
|
||||||
|
files.
|
||||||
|
|
||||||
## Simple example
|
## Simple example
|
||||||
Below is a simple example demonstrating two system-wide theme switches:
|
Below is a simple example demonstrating two system-wide theme switches:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
This GIF shows two `symconf` calls, the first of which applies a `gruvbox` dark theme and
|
This GIF shows two `symconf` calls, the first of which applies a `gruvbox` dark
|
||||||
the second a dark [`monobiome`][1] variant. Each call (of the form `symconf config -m dark -s
|
theme and the second a dark [`monobiome`][1] variant. Each call (of the form
|
||||||
style`) indicates a dark mode preference and a particular color palette that should be
|
`symconf config -m dark -s style`) indicates a dark mode preference and a
|
||||||
used when populating config file templates. Specifically, in this example, invoking
|
particular color palette that should be used when populating config file
|
||||||
`symconf` results in the following app-specific config updates:
|
templates. Specifically, in this example, invoking `symconf` results in the
|
||||||
|
following app-specific config updates:
|
||||||
|
|
||||||
- **GTK**: reacts to the mode setting and sets `prefer-dark` system-wide, changing general
|
- **GTK**: reacts to the mode setting and sets `prefer-dark` system-wide,
|
||||||
GTK-responsive applications like Nautilus and Firefox (and subsequently websites that
|
changing general GTK-responsive applications like Nautilus and Firefox (and
|
||||||
are responsive to `prefers-color-scheme`)
|
subsequently websites that are responsive to `prefers-color-scheme`)
|
||||||
- **kitty**: theme template is re-generated using the specified palette, and `kitty`
|
- **kitty**: theme template is re-generated using the specified palette, and
|
||||||
processes are sent a message to live-reload the new config file
|
`kitty` processes are sent a message to live-reload the new config file
|
||||||
- **neovim**: a `vim` theme file (along with a statusline theme) is generated from the
|
- **neovim**: a `vim` theme file (along with a statusline theme) is generated
|
||||||
chosen palette, and running instances of `neovim` are sent a message to re-source this
|
from the chosen palette, and running instances of `neovim` are sent a message
|
||||||
theme (via `nvim --remote-send`)
|
to re-source this theme (via `nvim --remote-send`)
|
||||||
- **waybar**: bar styles are updated to match the mode setting
|
- **waybar**: bar styles are updated to match the mode setting
|
||||||
- **sway**: the background color and window borders are dynamically set to base palette
|
- **sway**: the background color and window borders are dynamically set to base
|
||||||
colors, and `swaymsg reload` is called
|
palette colors, and `swaymsg reload` is called
|
||||||
- **fzf**: a palette-dependent theme is re-generated and re-exported
|
- **fzf**: a palette-dependent theme is re-generated and re-exported
|
||||||
- **rofi**: launcher text and highlight colors are set according to the mode and palette,
|
- **rofi**: launcher text and highlight colors are set according to the mode
|
||||||
applying on next invocation
|
and palette, applying on next invocation
|
||||||
|
|
||||||
This example highlights the generality of `symconf`, and so long as an app's config can be
|
This example highlights the generality of `symconf`, and so long as an app's
|
||||||
reloaded dynamically, you can use a single `symconf` call to apply themes for an arbitrary
|
config can be reloaded dynamically, you can use a single `symconf` call to
|
||||||
number of apps at once.
|
apply themes for an arbitrary number of apps at once.
|
||||||
|
|
||||||
# Behavior
|
# Behavior
|
||||||
`symconf` uses a simple operational model that symlinks centralized config files to their
|
`symconf` uses a simple operational model that symlinks centralized config
|
||||||
expected locations across the system. This central config directory can then be version
|
files to their expected locations across the system. This central config
|
||||||
controlled, and app config files can be updated in one place.
|
directory can then be version controlled, and app config files can be updated
|
||||||
|
in one place.
|
||||||
|
|
||||||
App config files can either be concrete (fully-specified) or templates (to be populated by
|
App config files can either be concrete (fully-specified) or templates (to be
|
||||||
values conditional on style, e.g., a palette). When `symconf` is executed with a
|
populated by values conditional on style, e.g., a palette). When `symconf` is
|
||||||
particular mode preference (dark or light) and a style (any other indicator of thematic
|
executed with a particular mode preference (dark or light) and a style (any
|
||||||
elements, often simply in the form of a palette like `solarized` or `gruvbox`), it
|
other indicator of thematic elements, often simply in the form of a palette
|
||||||
searches for both concrete and template config files that match and symlinks them to
|
like `solarized` or `gruvbox`), it searches for both concrete and template
|
||||||
registered locations. When necessary, `symconf` will also match and execute scripts to
|
config files that match and symlinks them to registered locations. When
|
||||||
reload apps after updating their configuration.
|
necessary, `symconf` will also match and execute scripts to reload apps after
|
||||||
|
updating their configuration.
|
||||||
|
|
||||||
You can find more details on how `symconf`'s matching scheme works in
|
You can find more details on how `symconf`'s matching scheme works in
|
||||||
[Matching](docs/reference/matching.md).
|
[Matching](docs/reference/matching.md).
|
||||||
|
|
||||||
# Configuring
|
# Configuring
|
||||||
Before using, you must first set up your config directory to house your config files and
|
Before using, you must first set up your config directory to house your config
|
||||||
give `symconf` something to act on. See [Configuring](docs/reference/configuring.md) for
|
files and give `symconf` something to act on. See
|
||||||
details.
|
[Configuring](docs/reference/configuring.md) for details.
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
The recommended way to install `symconf` is via `pipx`, which is particularly well-suited
|
The recommended way to install `symconf` is via `uv`'s "tool" subsystem, which
|
||||||
for managing Python packages meant to be used as CLI programs. With `uv` on your system,
|
is well-suited for managing Python packages meant to be used as CLI programs.
|
||||||
you can install with
|
With `uv` on your system, you can install with
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
uv too install symconf
|
uv tool install symconf
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, you can use `pipx` to similar effect:
|
Alternatively, you can use `pipx` to similar effect:
|
||||||
@@ -74,56 +78,60 @@ You can also install via `pip`, or clone and install locally.
|
|||||||
# Usage
|
# Usage
|
||||||
- `-h --help`: print help message
|
- `-h --help`: print help message
|
||||||
- `-c --config-dir`: set the location of the `symconf` config directory
|
- `-c --config-dir`: set the location of the `symconf` config directory
|
||||||
- `symconf config` is the subcommand used to match and set available config files for
|
- `symconf config` is the subcommand used to match and set available config
|
||||||
registered applications
|
files for registered applications
|
||||||
* `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to consider
|
* `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to
|
||||||
all registered apps.
|
consider all registered apps.
|
||||||
* `-m --mode`: preferred lightness mode/scheme, either `light`, `dark`, `any`, or
|
* `-m --mode`: preferred lightness mode/scheme, either `light`, `dark`,
|
||||||
`none`.
|
`any`, or `none`.
|
||||||
* `-s --style`: style indicator, often the name of a color palette, capturing thematic
|
* `-s --style`: style indicator, often the name of a color palette, capturing
|
||||||
details in a config file to be matched. `any` or `none` are reserved keywords (see
|
thematic details in a config file to be matched. `any` or `none` are
|
||||||
below).
|
reserved keywords (see below).
|
||||||
* `-T --template-vars`: additional groups to use when populating templates, in the form
|
* `-T --template-vars`: additional groups to use when populating templates,
|
||||||
`<group>=<value>`, where `<group>` is a template group with a folder
|
in the form `<group>=<value>`, where `<group>` is a template group with a
|
||||||
`$CONFIG_HOME/groups/<group>/` and `<value>` should correspond to a TOML file in this
|
folder `$CONFIG_HOME/groups/<group>/` and `<value>` should correspond to a
|
||||||
folder (i.e., `<value>.toml`).
|
TOML file in this folder (i.e., `<value>.toml`).
|
||||||
- `symconf generate` is a subcommand that can be used for batch generation of config
|
- `symconf generate` is a subcommand that can be used for batch generation of
|
||||||
files. It accepts the same arguments as `symconf config`, but rather than selecting the
|
config files. It accepts the same arguments as `symconf config`, but rather
|
||||||
best match to be used for the system setting, all matching templates are generated.
|
than selecting the best match to be used for the system setting, all matching
|
||||||
There is one additional required argument:
|
templates are generated. There is one additional required argument:
|
||||||
* `-o --output-dir`: the directory under which generated config files should be written.
|
* `-o --output-dir`: the directory under which generated config files should
|
||||||
App-specific subdirectories are created to house config files for each provided app.
|
be written. App-specific subdirectories are created to house config files
|
||||||
|
for each provided app.
|
||||||
- `symconf install`: runs install scripts for matching apps that specify one
|
- `symconf install`: runs install scripts for matching apps that specify one
|
||||||
* `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to consider
|
* `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to
|
||||||
all registered apps.
|
consider all registered apps.
|
||||||
- `symconf update`: runs update scripts for matching apps that specify one
|
- `symconf update`: runs update scripts for matching apps that specify one
|
||||||
* `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to consider
|
* `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to
|
||||||
all registered apps.
|
consider all registered apps.
|
||||||
|
|
||||||
The keywords `any` and `none` can be used when specifying `--mode`, `--style`, or as a
|
The keywords `any` and `none` can be used when specifying `--mode`, `--style`,
|
||||||
value in `--template-vars` (and we refer to each of these variables as _factors_ that help
|
or as a value in `--template-vars` (and we refer to each of these variables as
|
||||||
determine a config match):
|
_factors_ that help determine a config match):
|
||||||
|
|
||||||
- `any` will match config files with _any_ value for this factor, preferring config files
|
- `any` will match config files with _any_ value for this factor, preferring
|
||||||
with a value `none`, indicating no dependence on the factor. This is the default value
|
config files with a value `none`, indicating no dependence on the factor.
|
||||||
when a factor is left unspecified.
|
This is the default value when a factor is left unspecified.
|
||||||
- `none` will match `"none"` directly for a given factor (so no special behavior), but
|
- `none` will match `"none"` directly for a given factor (so no special
|
||||||
used to indicate that a config file is independent of the factor. For instance,
|
behavior), but used to indicate that a config file is independent of the
|
||||||
|
factor. For instance,
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
symconf config -m light -s none
|
symconf config -m light -s none
|
||||||
```
|
```
|
||||||
|
|
||||||
will match config files that capture the notion of a light mode, but do not depend on or
|
will match config files that capture the notion of a light mode, but do not
|
||||||
provide further thematic components such as a color palette.
|
depend on or provide further thematic components such as a color palette.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
- Set a dark mode for all registered apps, matching any available style/palette component:
|
- Set a dark mode for all registered apps, matching any available style/palette
|
||||||
|
component:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
symconf config -m dark
|
symconf config -m dark
|
||||||
```
|
```
|
||||||
- Set `solarized` theme for `kitty` and match any available mode (light or dark):
|
- Set `solarized` theme for `kitty` and match any available mode (light or
|
||||||
|
dark):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
symconf config -s solarized -a kitty
|
symconf config -s solarized -a kitty
|
||||||
@@ -133,16 +141,17 @@ determine a config match):
|
|||||||
```sh
|
```sh
|
||||||
symconf config -m dark -s gruvbox -apps="kitty,nvim"
|
symconf config -m dark -s gruvbox -apps="kitty,nvim"
|
||||||
```
|
```
|
||||||
- Set a dark `gruvbox` theme for all apps, and attempt to match other template elements:
|
- Set a dark `gruvbox` theme for all apps, and attempt to match other template
|
||||||
|
elements:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
symconf config -m dark -s gruvbox -T font=mono window=sharp
|
symconf config -m dark -s gruvbox -T font=mono window=sharp
|
||||||
```
|
```
|
||||||
|
|
||||||
which would attempt to find and load key-value pairs in the files
|
which would attempt to find and load key-value pairs in the files
|
||||||
`$CONFIG_HOME/groups/font/mono.toml` and `$CONFIG_HOME/groups/window/sharp.toml` to be
|
`$CONFIG_HOME/groups/font/mono.toml` and
|
||||||
used as values when filling templatized config files.
|
`$CONFIG_HOME/groups/window/sharp.toml` to be used as values when filling
|
||||||
|
templatized config files.
|
||||||
|
|
||||||
|
|
||||||
[1]: https://github.com/ologio/monobiome
|
[1]: https://github.com/ologio/monobiome
|
||||||
|
|||||||
44
docs/conf.py
44
docs/conf.py
@@ -3,43 +3,47 @@
|
|||||||
# For the full list of built-in configuration values, see the documentation:
|
# For the full list of built-in configuration values, see the documentation:
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information ------------------------------------------------------
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||||
|
|
||||||
project = 'symconf'
|
project = "symconf"
|
||||||
copyright = '2024, Sam Griesemer'
|
copyright = "2025, Sam Griesemer"
|
||||||
author = 'Sam Griesemer'
|
author = "Sam Griesemer"
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ----------------------------------------------------
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||||
|
|
||||||
extensions = [
|
extensions = [
|
||||||
"sphinx.ext.autodoc",
|
"sphinx.ext.autodoc",
|
||||||
"sphinx.ext.autosummary", # enables a directive to be specified manually that gathers
|
# enables a directive to be specified manually that gathers module/object
|
||||||
# module/object summary details in a table
|
# summary details in a table
|
||||||
"sphinx.ext.viewcode", # allow viewing source in the HTML pages
|
"sphinx.ext.autosummary",
|
||||||
"myst_parser", # only really applies to manual docs; docstrings still need RST-like
|
# allow viewing source in the HTML pages
|
||||||
"sphinx.ext.napoleon", # enables Google-style docstring formats
|
"sphinx.ext.viewcode",
|
||||||
"sphinx_autodoc_typehints", # external extension that allows arg types to be inferred by type hints
|
# only really applies to manual docs; docstrings still need RST-like
|
||||||
|
"myst_parser",
|
||||||
|
# enables Google-style docstring formats
|
||||||
|
"sphinx.ext.napoleon",
|
||||||
|
# external extension that allows arg types to be inferred by type hints
|
||||||
|
"sphinx_autodoc_typehints",
|
||||||
]
|
]
|
||||||
autosummary_generate = True
|
autosummary_generate = True
|
||||||
autosummary_imported_members = True
|
autosummary_imported_members = True
|
||||||
|
|
||||||
# include __init__ definitions in autodoc
|
# include __init__ definitions in autodoc
|
||||||
autodoc_default_options = {
|
autodoc_default_options = {
|
||||||
'special-members': '__init__',
|
"special-members": "__init__",
|
||||||
}
|
}
|
||||||
|
|
||||||
templates_path = ['_templates']
|
templates_path = ["_templates"]
|
||||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
# -- Options for HTML output --------------------------------------------------
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||||
|
|
||||||
html_theme = 'furo'
|
html_theme = "furo"
|
||||||
html_static_path = ['_static']
|
html_static_path = ["_static"]
|
||||||
#html_sidebars = {
|
# html_sidebars = {
|
||||||
# '**': ['/modules.html'],
|
# '**': ['/modules.html'],
|
||||||
#}
|
# }
|
||||||
|
|
||||||
|
|||||||
@@ -1,37 +1,31 @@
|
|||||||
# `symconf` package docs
|
# `symconf` package
|
||||||
|
*General-purpose local application configuration manager*
|
||||||
|
|
||||||
{ref}`genindex`
|
{ref}`genindex`
|
||||||
{ref}`modindex`
|
{ref}`modindex`
|
||||||
{ref}`search`
|
|
||||||
|
|
||||||
## Top-level module overview
|
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
.. autosummary::
|
.. autosummary::
|
||||||
:nosignatures:
|
:nosignatures:
|
||||||
:recursive:
|
:recursive:
|
||||||
|
:caption: Modules
|
||||||
|
|
||||||
symconf.config
|
symconf.config
|
||||||
symconf.template
|
|
||||||
symconf.matching
|
|
||||||
symconf.reader
|
symconf.reader
|
||||||
symconf.runner
|
symconf.runner
|
||||||
```
|
symconf.matching
|
||||||
|
symconf.template
|
||||||
## Auto-reference contents
|
|
||||||
```{toctree}
|
|
||||||
:maxdepth: 3
|
|
||||||
|
|
||||||
_autoref/symconf.rst
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```{toctree}
|
```{toctree}
|
||||||
:maxdepth: 2
|
:maxdepth: 1
|
||||||
:caption: Contents
|
:caption: Contents
|
||||||
|
:hidden:
|
||||||
|
|
||||||
reference/configuring
|
|
||||||
reference/usage
|
|
||||||
reference/archive
|
reference/archive
|
||||||
reference/documentation/index
|
reference/configuring
|
||||||
|
reference/matching
|
||||||
|
reference/usage
|
||||||
```
|
```
|
||||||
|
|
||||||
```{include} ../README.md
|
```{include} ../README.md
|
||||||
|
|||||||
@@ -1,80 +1,89 @@
|
|||||||
# Archive
|
# Archive
|
||||||
The `autoconf` project is an attempt at wrangling the complexity of configuring many
|
The `autoconf` project is an attempt at wrangling the complexity of configuring
|
||||||
applications across one's Linux system. It provides a simple operational model for pulling
|
many applications across one's Linux system. It provides a simple operational
|
||||||
many application config files into one place, as well as generating/setting color schemes
|
model for pulling many application config files into one place, as well as
|
||||||
across apps.
|
generating/setting color schemes across apps.
|
||||||
|
|
||||||
Quick terminology rundown for theme-related items:
|
Quick terminology rundown for theme-related items:
|
||||||
|
|
||||||
- **Theme**: loose term referring generally to the overall aesthetic of a visual setting.
|
- **Theme**: loose term referring generally to the overall aesthetic of a
|
||||||
Ignoring stylistic changes (only applicable to some apps; example here might be a
|
visual setting. Ignoring stylistic changes (only applicable to some apps;
|
||||||
a particular setting of the `waybar` layout), a theme is often just the wrapper term for
|
example here might be a a particular setting of the `waybar` layout), a theme
|
||||||
a choice of color _palette_ and _scheme_. For example, "tone4-light" could be a _theme_
|
is often just the wrapper term for a choice of color _palette_ and _scheme_.
|
||||||
setting for an app like `kitty`, referring to both a palette and scheme.
|
For example, "tone4-light" could be a _theme_ setting for an app like
|
||||||
- **Palette**: a set of base colors used to style text or other aspects of an app's
|
`kitty`, referring to both a palette and scheme.
|
||||||
displayed assets
|
- **Palette**: a set of base colors used to style text or other aspects of an
|
||||||
|
app's displayed assets
|
||||||
- **Scheme**: an indication of lightness, typically either "light" or "dark.
|
- **Scheme**: an indication of lightness, typically either "light" or "dark.
|
||||||
|
|
||||||
As far as managing settings across apps, there are current two useful classifications
|
As far as managing settings across apps, there are current two useful
|
||||||
here:
|
classifications here:
|
||||||
|
|
||||||
1. **Inseparable from theme**: some apps (e.g., `sway`, `waybar`) have color scheme
|
1. **Inseparable from theme**: some apps (e.g., `sway`, `waybar`) have color
|
||||||
components effectively built in to their canonical configuration file. This can make it
|
scheme components effectively built in to their canonical configuration
|
||||||
hard to set themes dynamically, as it would likely require some involved
|
file. This can make it hard to set themes dynamically, as it would likely
|
||||||
matching/substitution rules. This is not a level of complexity I'm willing to embrace,
|
require some involved matching/substitution rules. This is not a level of
|
||||||
so we simply split the config files according to theme and/or scheme.
|
complexity I'm willing to embrace, so we simply split the config files
|
||||||
2. **Can load an external theme file**: some apps (e.g., `kitty`) have a clear mechanism
|
according to theme and/or scheme.
|
||||||
for loading themes. This typically implies some distinct color format, although usually
|
2. **Can load an external theme file**: some apps (e.g., `kitty`) have a clear
|
||||||
somewhat easy to generate (don't have to navigate non-color settings, for instance).
|
mechanism for loading themes. This typically implies some distinct color
|
||||||
Such apps allow for an even less "invasive" config swapping process when setting a new
|
format, although usually somewhat easy to generate (don't have to navigate
|
||||||
theme, as one can just swap out the external theme file.
|
non-color settings, for instance). Such apps allow for an even less
|
||||||
|
"invasive" config swapping process when setting a new theme, as one can just
|
||||||
|
swap out the external theme file.
|
||||||
|
|
||||||
To be clear on operation implications here: apps of type (1) must have _manually
|
To be clear on operation implications here: apps of type (1) must have
|
||||||
maintained_ config variations according the desired themes. General theme settings must
|
_manually maintained_ config variations according the desired themes. General
|
||||||
follow the naming scheme `<app-name>-<palette>-<scheme>.<ext>`. For example, if I wanted to set
|
theme settings must follow the naming scheme
|
||||||
`sway` to a light variation (which, at the time of writing, would just entail changing a
|
`<app-name>-<palette>-<scheme>.<ext>`. For example, if I wanted to set `sway`
|
||||||
single background color), I must have explicitly created a `sway-tone4-light.conf` file
|
to a light variation (which, at the time of writing, would just entail changing
|
||||||
that captures this setting. The canonical config file will then be symlinked to the
|
a single background color), I must have explicitly created a
|
||||||
theme-specific file when the theme is set. (Note that the palette in this example is pretty much
|
`sway-tone4-light.conf` file that captures this setting. The canonical config
|
||||||
irrelevant, but it needs to be present in order to match the overarching setting; here you
|
file will then be symlinked to the theme-specific file when the theme is set.
|
||||||
can just think of the format being `<app-name>-<theme>.<ext>`, where `tone4-light` is the
|
(Note that the palette in this example is pretty much irrelevant, but it needs
|
||||||
provided theme name.)
|
to be present in order to match the overarching setting; here you can just
|
||||||
|
think of the format being `<app-name>-<theme>.<ext>`, where `tone4-light` is
|
||||||
|
the provided theme name.)
|
||||||
|
|
||||||
For apps of type (2), the canonical config file can remain untouched so long as it refers
|
For apps of type (2), the canonical config file can remain untouched so long as
|
||||||
to a fixed, generic theme file. For example, with `kitty`, my config file can point to a
|
it refers to a fixed, generic theme file. For example, with `kitty`, my config
|
||||||
`current-theme.conf` file, which will be symlinked to a specific theme file here in
|
file can point to a `current-theme.conf` file, which will be symlinked to a
|
||||||
`autoconf` when a change is requested. This enables a couple of conveniences:
|
specific theme file here in `autoconf` when a change is requested. This enables
|
||||||
|
a couple of conveniences:
|
||||||
|
|
||||||
- The true config directory on disk remains unpolluted with theme variants.
|
- The true config directory on disk remains unpolluted with theme variants.
|
||||||
- If the set theme is regenerated, there is no intervention necessary to propagate its
|
- If the set theme is regenerated, there is no intervention necessary to
|
||||||
changes to the target app. The symlinked file itself will be updated when the theme
|
propagate its changes to the target app. The symlinked file itself will be
|
||||||
does, ensuring the latest theme version is always immediately available and pointed to
|
updated when the theme does, ensuring the latest theme version is always
|
||||||
by the app.
|
immediately available and pointed to by the app.
|
||||||
|
|
||||||
Keep in mind that some apps may fall into some grey area here, allowing some external
|
Keep in mind that some apps may fall into some grey area here, allowing some
|
||||||
customization but locking down other settings internally. In such instances, there's no
|
external customization but locking down other settings internally. In such
|
||||||
need to overcomplicate things; just stick to explicit config variants under the type (1)
|
instances, there's no need to overcomplicate things; just stick to explicit
|
||||||
umbrella. Type (2) only works for generated themes anyhow; even if the target app can load
|
config variants under the type (1) umbrella. Type (2) only works for generated
|
||||||
an external theme, type (1) should be used if preset themes are fixed.
|
themes anyhow; even if the target app can load an external theme, type (1)
|
||||||
|
should be used if preset themes are fixed.
|
||||||
|
|
||||||
## Naming standards
|
## Naming standards
|
||||||
To keep things simple, we use a few fixed naming standards for setting app config files
|
To keep things simple, we use a few fixed naming standards for setting app
|
||||||
and their themed counterparts. The app registry requires each theme-eligible app to
|
config files and their themed counterparts. The app registry requires each
|
||||||
provide a config directory (`config_dir`), containing some canonical config file
|
theme-eligible app to provide a config directory (`config_dir`), containing
|
||||||
(`config_file`) and to serve as a place for theme-specific config variations. The
|
some canonical config file (`config_file`) and to serve as a place for
|
||||||
following naming schemes must be used in order for theme switching to behave
|
theme-specific config variations. The following naming schemes must be used in
|
||||||
appropriately:
|
order for theme switching to behave appropriately:
|
||||||
|
|
||||||
- When setting a theme for a particular app, the following variables will be available:
|
- When setting a theme for a particular app, the following variables will be
|
||||||
|
available:
|
||||||
* `<app-name>`
|
* `<app-name>`
|
||||||
* `<palette>`
|
* `<palette>`
|
||||||
* `<scheme>`
|
* `<scheme>`
|
||||||
- For apps with `external_theme = False`, config variants must named as
|
- For apps with `external_theme = False`, config variants must named as
|
||||||
`<app-name>-<palette>-<scheme>.<ext>`, where `<ext>` is the app's default config file
|
`<app-name>-<palette>-<scheme>.<ext>`, where `<ext>` is the app's default
|
||||||
extension.
|
config file extension.
|
||||||
- For apps with `external_theme = True`, the file `<config-dir>/current-theme.conf` will
|
- For apps with `external_theme = True`, the file
|
||||||
be used when symlinking the requested theme. The config file thus must point to this
|
`<config-dir>/current-theme.conf` will be used when symlinking the requested
|
||||||
file in order to change with the set theme.
|
theme. The config file thus must point to this file in order to change with
|
||||||
|
the set theme.
|
||||||
|
|
||||||
Additionally, the theme symlink will be created from the file
|
Additionally, the theme symlink will be created from the file
|
||||||
|
|
||||||
@@ -87,147 +96,162 @@ appropriately:
|
|||||||
## Directory structure
|
## Directory structure
|
||||||
|
|
||||||
- `autoconf/`: main repo directory
|
- `autoconf/`: main repo directory
|
||||||
* `config/`: app-specific configuration files. Each folder inside this directory is
|
* `config/`: app-specific configuration files. Each folder inside this
|
||||||
app-specific, and the target of associated copy operations when a config sync is
|
directory is app-specific, and the target of associated copy operations
|
||||||
performed. Nothing in this directory should pertain to any repo functionality; it
|
when a config sync is performed. Nothing in this directory should pertain
|
||||||
should only contain config files that originated elsewhere on the system.
|
to any repo functionality; it should only contain config files that
|
||||||
* `themes/`: app-independent theme data files. Each folder in this directory should
|
originated elsewhere on the system.
|
||||||
correspond to a specific color palette and house any relevant color spec files
|
* `themes/`: app-independent theme data files. Each folder in this
|
||||||
(currently likely be a `colors.json`). Also servers the output location for
|
directory should correspond to a specific color palette and house any
|
||||||
generated theme files
|
relevant color spec files (currently likely be a `colors.json`). Also
|
||||||
* `<palette>/colors.json`: JSON formatted color key-value pairings for palette
|
servers the output location for generated theme files
|
||||||
colors. There's no standard here aside from the filename and format; downstream
|
* `<palette>/colors.json`: JSON formatted color key-value pairings for
|
||||||
app-specific TOML templates can be dependent on any key naming scheme within the
|
palette colors. There's no standard here aside from the filename and
|
||||||
JSON.
|
format; downstream app-specific TOML templates can be dependent on
|
||||||
+ `<palette>/apps/<app-name>/templates/`: houses the TOML maps for the color
|
any key naming scheme within the JSON.
|
||||||
palette `<palette>` under app `<app-name>`. Files `<fname>.toml` will be mapped to
|
+ `<palette>/apps/<app-name>/templates/`: houses the TOML maps for the
|
||||||
`<fname>.conf` in the theme output folder (below), so ensure the naming
|
color palette `<palette>` under app `<app-name>`. Files
|
||||||
standards align with those outlined above.
|
`<fname>.toml` will be mapped to `<fname>.conf` in the theme output
|
||||||
+ `<palette>/apps/<app-name>/generated/`: output directory for generated scheme
|
folder (below), so ensure the naming standards align with those
|
||||||
variants. These are the symlink targets for dynamically set external themes.
|
outlined above.
|
||||||
* `app_registry.toml`: global application "registry" used by sync and theme-setting
|
+ `<palette>/apps/<app-name>/generated/`: output directory for
|
||||||
scripts. This lets apps be dynamically added or removed from being eligible for
|
generated scheme variants. These are the symlink targets for
|
||||||
config-related operations.
|
dynamically set external themes.
|
||||||
|
* `app_registry.toml`: global application "registry" used by sync and
|
||||||
|
theme-setting scripts. This lets apps be dynamically added or removed
|
||||||
|
from being eligible for config-related operations.
|
||||||
|
|
||||||
## Scripts
|
## Scripts
|
||||||
|
|
||||||
`set_theme.py`: sets a theme across select apps.
|
`set_theme.py`: sets a theme across select apps.
|
||||||
|
|
||||||
- Applies to specific app with `-a <app>` , or to all apps in the `app_registry.toml` with
|
- Applies to specific app with `-a <app>` , or to all apps in the
|
||||||
`-a "*"`.
|
`app_registry.toml` with `-a "*"`.
|
||||||
- Uses symlinks to set canonical config files to theme-based variations. Which files get
|
- Uses symlinks to set canonical config files to theme-based variations. Which
|
||||||
set depends on the _app type_ (see above), which really just boils down to whether
|
files get set depends on the _app type_ (see above), which really just boils
|
||||||
theming (1) can be specified with an external format, and (2) if it depends on
|
down to whether theming (1) can be specified with an external format, and (2)
|
||||||
auto-generated theme files from within `autoconf`.
|
if it depends on auto-generated theme files from within `autoconf`.
|
||||||
- Palette and scheme are specified as expected. They are used to infer proper paths
|
- Palette and scheme are specified as expected. They are used to infer proper
|
||||||
according to naming and structure standards.
|
paths according to naming and structure standards.
|
||||||
- Real config files will never be overwritten. To begin setting themes with the script,
|
- Real config files will never be overwritten. To begin setting themes with the
|
||||||
you must delete the canonical config file expected by the app (and specified in the app
|
script, you must delete the canonical config file expected by the app (and
|
||||||
registry) to allow the first symlink to be set. From there on out, symlinks will be
|
specified in the app registry) to allow the first symlink to be set. From
|
||||||
automatically flushed.
|
there on out, symlinks will be automatically flushed.
|
||||||
- A report will be provided on which apps were successfully set to the requested theme,
|
- A report will be provided on which apps were successfully set to the
|
||||||
along with the file stems. A number of checks are in place for the existence of involved
|
requested theme, along with the file stems. A number of checks are in place
|
||||||
files and directories. Overall, the risk of overwritting a real config file is low; we
|
for the existence of involved files and directories. Overall, the risk of
|
||||||
only flush existing symlinks, and if the would-be target for the requested theme (be it
|
overwritting a real config file is low; we only flush existing symlinks, and
|
||||||
from an auto-generated theme file, or from a manually manage config variant) doesn't
|
if the would-be target for the requested theme (be it from an auto-generated
|
||||||
exist, that app's config will be completed skipped. Essentially, everything must be in
|
theme file, or from a manually manage config variant) doesn't exist, that
|
||||||
|
app's config will be completed skipped. Essentially, everything must be in
|
||||||
perfect shape before the symlink trigger is officially pulled.
|
perfect shape before the symlink trigger is officially pulled.
|
||||||
|
|
||||||
|
`gen_theme.py`: generates theme files for palettes by mapping their color
|
||||||
|
definitions through app-specific templates. These templates specific how to
|
||||||
|
relate an app's theme variables to the color names provided by the template.
|
||||||
|
|
||||||
`gen_theme.py`: generates theme files for palettes by mapping their color definitions
|
- An app and palette are the two required parameters. If no template or output
|
||||||
through app-specific templates. These templates specific how to relate an app's theme
|
paths are provided, they will be inferred according to the theme path
|
||||||
variables to the color names provided by the template.
|
standards seen above.
|
||||||
|
- The `--template` argument can be a directory or a file, depending on what
|
||||||
|
theme files you'd like to render.
|
||||||
|
- The `--output` path, if specified, must be a directory. Generated theme files
|
||||||
|
take on a name with the same stem as their source template, but using the
|
||||||
|
`.conf` extension.
|
||||||
|
- The TOML templates should make config variable names to JSON dot-notation
|
||||||
|
accessors. If color definitions are nested, the dot notation should be
|
||||||
|
properly expanded by the script when mapping the colors to keyword values.
|
||||||
|
- There are a number of checks for existing paths, even those inferred (e.g.,
|
||||||
|
template and output) from the palette and app. If the appropriate setup
|
||||||
|
hasn't been followed, the script will fail. Make sure the `theme` folder in
|
||||||
|
question and it's nested `app` directory are correctly setup before running
|
||||||
|
the script. (Perhaps down the line there are some easy auto-setup steps to
|
||||||
|
take here, but I'm not making that jump now.)
|
||||||
|
- TODO: open up different app "writers," or make it easy to extend output
|
||||||
|
syntax based on the app in question. This would like be as simple as mapping
|
||||||
|
app names to line-generating functions, which accept the keyword and color
|
||||||
|
(among other items). This can be fleshed out as needed.
|
||||||
|
|
||||||
- An app and palette are the two required parameters. If no template or output paths are
|
`sync.sh`: copies relevant configuration files from local paths into the
|
||||||
provided, they will be inferred according to the theme path standards seen above.
|
`autoconf` subpath. Markdown files in the docs directory then reference the
|
||||||
- The `--template` argument can be a directory or a file, depending on what theme files
|
local copies of these files, meaning the documentation updates dynamically when
|
||||||
you'd like to render.
|
the configuration files do. That is, the (possibly extracted) config snippets
|
||||||
- The `--output` path, if specified, must be a directory. Generated theme files take on
|
will change with the current state of my system config without any manual
|
||||||
a name with the same stem as their source template, but using the `.conf` extension.
|
intervention of the documentation files.
|
||||||
- The TOML templates should make config variable names to JSON dot-notation accessors. If
|
|
||||||
color definitions are nested, the dot notation should be properly expanded by the script
|
|
||||||
when mapping the colors to keyword values.
|
|
||||||
- There are a number of checks for existing paths, even those inferred (e.g., template and
|
|
||||||
output) from the palette and app. If the appropriate setup hasn't been followed, the
|
|
||||||
script will fail. Make sure the `theme` folder in question and it's nested `app`
|
|
||||||
directory are correctly setup before running the script. (Perhaps down the line there
|
|
||||||
are some easy auto-setup steps to take here, but I'm not making that jump now.)
|
|
||||||
- TODO: open up different app "writers," or make it easy to extend output syntax based on
|
|
||||||
the app in question. This would like be as simple as mapping app names to
|
|
||||||
line-generating functions, which accept the keyword and color (among other items). This
|
|
||||||
can be fleshed out as needed.
|
|
||||||
|
|
||||||
`sync.sh`: copies relevant configuration files from local paths into the `autoconf`
|
|
||||||
subpath. Markdown files in the docs directory then reference the local copies of these
|
|
||||||
files, meaning the documentation updates dynamically when the configuration files do. That
|
|
||||||
is, the (possibly extracted) config snippets will change with the current state of my
|
|
||||||
system config without any manual intervention of the documentation files.
|
|
||||||
|
|
||||||
### Specific theme-setting example
|
### Specific theme-setting example
|
||||||
To make clear how the theme setting script works on my system, the following breaks down
|
To make clear how the theme setting script works on my system, the following
|
||||||
exactly what steps are taken to exert as much scheme control as possible. Everything at this
|
breaks down exactly what steps are taken to exert as much scheme control as
|
||||||
point is wrapped up in a single `make set-<palette>-<scheme>` call; suppose we're
|
possible. Everything at this point is wrapped up in a single `make
|
||||||
currently running the dark scheme (see first image) and I run `make set-tone4-light`:
|
set-<palette>-<scheme>` call; suppose we're currently running the dark scheme
|
||||||
|
(see first image) and I run `make set-tone4-light`:
|
||||||
|
|
||||||

|
](_static/set-theme-1.png)
|
||||||
|
|
||||||
_(Starting point; have a GTK app (GNOME files), `kitty`, and Firefox (with the
|
_(Starting point; have a GTK app (GNOME files), `kitty`, and Firefox (with the
|
||||||
system-dependent default theme set). In Firefox, I have open `localsys` with its
|
system-dependent default theme set). In Firefox, I have open `localsys` with
|
||||||
scheme-mode to set to "auto," which should reflect the theme setting picked up by the
|
its scheme-mode to set to "auto," which should reflect the theme setting picked
|
||||||
browser (and note the white tab icon).)_
|
up by the browser (and note the white tab icon).)_
|
||||||
|
|
||||||
1. `set_theme.py` is invoked. Global settings are applied first, based on my OS (`Linux`),
|
1. `set_theme.py` is invoked. Global settings are applied first, based on my OS
|
||||||
which calls
|
(`Linux`), which calls
|
||||||
|
|
||||||
```
|
```
|
||||||
gsettings set org.gnome.desktop.interface color-scheme 'prefer-light'
|
gsettings set org.gnome.desktop.interface color-scheme 'prefer-light'
|
||||||
```
|
```
|
||||||
|
|
||||||
controlling settings for GTK apps and other `desktop-portal`-aware programs. This
|
controlling settings for GTK apps and other `desktop-portal`-aware programs.
|
||||||
yields the following:
|
This yields the following:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
_(Portal-aware apps changed, config apps not yet set. Scheme-aware sites are updated
|
_(Portal-aware apps changed, config apps not yet set. Scheme-aware sites are
|
||||||
without page refresh.)_
|
updated without page refresh.)_
|
||||||
2. Specific application styles are set. For now the list is small, including `kitty`,
|
2. Specific application styles are set. For now the list is small, including
|
||||||
`waybar`, and `sway`. `kitty` is the only type (2) application here, whereas the other
|
`kitty`, `waybar`, and `sway`. `kitty` is the only type (2) application
|
||||||
two are type (1).
|
here, whereas the other two are type (1).
|
||||||
|
|
||||||
a. For the type (1) apps, the canonical config files as specified in the app registry
|
a. For the type (1) apps, the canonical config files as specified in the app
|
||||||
are symlinked to their light variants. For `sway`, this is `~/.config/sway/config`,
|
registry are symlinked to their light variants. For `sway`, this is
|
||||||
and if we look at the `file`:
|
`~/.config/sway/config`, and if we look at the `file`:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
.config/sway/config: symbolic link to ~/.config/sway/sway-tone4-light
|
.config/sway/config: symbolic link to ~/.config/sway/sway-tone4-light
|
||||||
```
|
```
|
||||||
b. For the type (2) apps, just the `current-theme.conf` file is symlinked to the
|
b. For the type (2) apps, just the `current-theme.conf` file is symlinked to
|
||||||
relevant palette-scheme file. `kitty` is such an app, with a supported theme file
|
the relevant palette-scheme file. `kitty` is such an app, with a
|
||||||
for `tone4`, and those files have been auto-generated via `gen_theme.py`. Looking at
|
supported theme file for `tone4`, and those files have been
|
||||||
this file under the `kitty` config directory:
|
auto-generated via `gen_theme.py`. Looking at this file under the `kitty`
|
||||||
|
config directory:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
.config/kitty/current-theme.conf: symbolic link to ~/Documents/projects/autoconf/autoconf/themes/tone4/apps/kitty/generated/light.conf
|
.config/kitty/current-theme.conf: symbolic link to
|
||||||
|
~/Documents/projects/autoconf/autoconf/themes/tone4/apps/kitty/generated/light.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
The `kitty.conf` file isn't changed, as all palette-related items are specified in
|
The `kitty.conf` file isn't changed, as all palette-related items are
|
||||||
the theme file. (Note that the general notion of a "theme" could include changes to
|
specified in the theme file. (Note that the general notion of a "theme"
|
||||||
other stylistic aspects, like the font family; this would likely require some hybrid
|
could include changes to other stylistic aspects, like the font family;
|
||||||
type 1-2 approach not yet implemented).
|
this would likely require some hybrid type 1-2 approach not yet
|
||||||
3. Live application instances are reloaded, according to the registered `refresh_cmd`s.
|
implemented).
|
||||||
Here the apps with style/config files set in step (2) are reloaded to reflect those
|
3. Live application instances are reloaded, according to the registered
|
||||||
changes. Again, in this example, this is `kitty`, `sway`, and the `waybar`.
|
`refresh_cmd`s. Here the apps with style/config files set in step (2) are
|
||||||
|
reloaded to reflect those changes. Again, in this example, this is `kitty`,
|
||||||
|
`sway`, and the `waybar`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
_(Final light setting: portal-dependent apps _and_ config-based apps changed)_
|
_(Final light setting: portal-dependent apps _and_ config-based apps
|
||||||
4. `set_theme.py` provides a report for the actions taken; in this case, the following was
|
changed)_
|
||||||
printed:
|
4. `set_theme.py` provides a report for the actions taken; in this case, the
|
||||||
|
following was printed:
|
||||||
|
|
||||||

|

|
||||||
_(`set_theme.py` output)_
|
_(`set_theme.py` output)_
|
||||||
|
|||||||
@@ -1,61 +1,64 @@
|
|||||||
# Configuring
|
# Configuring
|
||||||
`symconf` operates on a central directory that houses all of the config files you may wish
|
`symconf` operates on a central directory that houses all of the config files
|
||||||
to apply. The default location for this directory is your `$XDG_CONFIG_HOME` (e.g.,
|
you may wish to apply. The default location for this directory is your
|
||||||
`~/.config/symconf/`), but it can be any location on your system so long as it's specified
|
`$XDG_CONFIG_HOME` (e.g., `~/.config/symconf/`), but it can be any location on
|
||||||
(see more in Usage).
|
your system so long as it's specified (see more in Usage).
|
||||||
|
|
||||||
`symconf` expects you to create two top-level components in your config directory: an
|
`symconf` expects you to create two top-level components in your config
|
||||||
`apps/` directory and an `app_registry.toml` file.
|
directory: an `apps/` directory and an `app_registry.toml` file.
|
||||||
|
|
||||||
**High-level view**:
|
**High-level view**:
|
||||||
|
|
||||||
- `symconf` operates on a single directory that houses all your config files
|
- `symconf` operates on a single directory that houses all your config files
|
||||||
- Config files in this directory must be placed under an `apps/<app-name>/` folder to be
|
- Config files in this directory must be placed under an `apps/<app-name>/`
|
||||||
associated with the app `<app-name>`
|
folder to be associated with the app `<app-name>`
|
||||||
- For apps to be visible, you need an `app_registry.toml` file that tells `symconf` where
|
- For apps to be visible, you need an `app_registry.toml` file that tells
|
||||||
to symlink your files in `apps/`
|
`symconf` where to symlink your files in `apps/`
|
||||||
|
|
||||||
## Apps directory
|
## Apps directory
|
||||||
An `apps/` directory should be created in your config home, with a subdirectory
|
An `apps/` directory should be created in your config home, with a subdirectory
|
||||||
`apps/<app-name>/` for each app with config files that you'd like to be visible to
|
`apps/<app-name>/` for each app with config files that you'd like to be visible
|
||||||
`symconf`. Note that simply populating an app's config folder here will do nothing on its
|
to `symconf`. Note that simply populating an app's config folder here will do
|
||||||
own; the app must also have been registered (discussed in item #2) in order for these
|
nothing on its own; the app must also have been registered (discussed in item
|
||||||
files to be used when `symconf` is invoked. (This just means you can populate your `apps/`
|
#2) in order for these files to be used when `symconf` is invoked. (This just
|
||||||
folder safely without expecting any default behavior. More often than not you'll be
|
means you can populate your `apps/` folder safely without expecting any default
|
||||||
expected to tell `symconf` exactly where your config files should end up, meaning you know
|
behavior. More often than not you'll be expected to tell `symconf` exactly
|
||||||
exactly what it's doing.)
|
where your config files should end up, meaning you know exactly what it's
|
||||||
|
doing.)
|
||||||
|
|
||||||
### User config
|
### User config
|
||||||
Inside your app-specific subdirectory, your managed config files should be placed in a
|
Inside your app-specific subdirectory, your managed config files should be
|
||||||
`user/` subdirectory (distinguishing them from those generated by templates; see more
|
placed in a `user/` subdirectory (distinguishing them from those generated by
|
||||||
in Themes). Your config files themselves are then expected to follow a specific naming
|
templates; see more in Themes). Your config files themselves are then expected
|
||||||
scheme:
|
to follow a specific naming scheme:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
<palette>-<scheme>.<config-name>
|
<palette>-<scheme>.<config-name>
|
||||||
```
|
```
|
||||||
|
|
||||||
This ties your config file to a particular theme setting as needed, and `symconf` will
|
This ties your config file to a particular theme setting as needed, and
|
||||||
apply it if it matches the theme setting you provide when invoked. The specific values are
|
`symconf` will apply it if it matches the theme setting you provide when
|
||||||
as follows:
|
invoked. The specific values are as follows:
|
||||||
|
|
||||||
- `scheme`: can be `light`, `dark`, or `none`. Indicates whether the config file should
|
- `scheme`: can be `light`, `dark`, or `none`. Indicates whether the config
|
||||||
be applied specifically when requesting a light or dark mode. Use `none` to indicate
|
file should be applied specifically when requesting a light or dark mode. Use
|
||||||
that the config file does not have settings specific to a light/dark mode.
|
`none` to indicate that the config file does not have settings specific to a
|
||||||
- `palette`: a "palette name" of your choosing, or `none`. The palette name you use
|
light/dark mode.
|
||||||
here may refer specifically to a color palette used by the config file, but can be
|
- `palette`: a "palette name" of your choosing, or `none`. The palette name you
|
||||||
used generally to indicate any particular group of config settings (e.g., fonts,
|
use here may refer specifically to a color palette used by the config file,
|
||||||
transparency, etc). Use `none` to indicate that the file does not correspond to any
|
but can be used generally to indicate any particular group of config settings
|
||||||
particular style group.
|
(e.g., fonts, transparency, etc). Use `none` to indicate that the file does
|
||||||
- `config-name`: the _name_ of the config file. This should correspond to _same path
|
not correspond to any particular style group.
|
||||||
name_ that is expected by the app being configured. For example, if your app expects a
|
- `config-name`: the _name_ of the config file. This should correspond to _same
|
||||||
config file at `a/b/c/d.conf`, "`d.conf`" is the path name.
|
path name_ that is expected by the app being configured. For example, if your
|
||||||
|
app expects a config file at `a/b/c/d.conf`, "`d.conf`" is the path name.
|
||||||
|
|
||||||
When invoking `symconf` with specific scheme and palette settings (see more in Usage),
|
When invoking `symconf` with specific scheme and palette settings (see more in
|
||||||
appropriate config files can be matched based on how you've named your files.
|
Usage), appropriate config files can be matched based on how you've named your
|
||||||
|
files.
|
||||||
|
|
||||||
For example, suppose I want to set up a simple light/dark mode switch for the `kitty`
|
For example, suppose I want to set up a simple light/dark mode switch for the
|
||||||
terminal emulator. The following tree demonstrates a valid setup:
|
`kitty` terminal emulator. The following tree demonstrates a valid setup:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
<config-home>
|
<config-home>
|
||||||
@@ -66,30 +69,31 @@ terminal emulator. The following tree demonstrates a valid setup:
|
|||||||
└── none-dark.kitty.conf
|
└── none-dark.kitty.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
where `none-light.kitty.conf` may set a light background and `none-dark.kitty.conf` a dark
|
where `none-light.kitty.conf` may set a light background and
|
||||||
one. `none` is used for the `<palette>` part of the name to indicate the configuration does
|
`none-dark.kitty.conf` a dark one. `none` is used for the `<palette>` part of
|
||||||
not pertain to any specific palette and can be matched even if one is not provided. With
|
the name to indicate the configuration does not pertain to any specific palette
|
||||||
an appropriate `app_regsitry.toml` file (see below), invoking
|
and can be matched even if one is not provided. With an appropriate
|
||||||
|
`app_regsitry.toml` file (see below), invoking
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
symconf --theme=light --apps=kitty
|
symconf --theme=light --apps=kitty
|
||||||
```
|
```
|
||||||
|
|
||||||
would symlink `$XDG_CONFIG_HOME/symconf/apps/kitty/user/none-light.kitty.conf` to
|
would symlink `$XDG_CONFIG_HOME/symconf/apps/kitty/user/none-light.kitty.conf`
|
||||||
`~/.config/kitty/kitty.conf`.
|
to `~/.config/kitty/kitty.conf`.
|
||||||
|
|
||||||
### Templatized config
|
### Templatized config
|
||||||
Note the potential inconvenience in needing to manage two separate config files in the
|
Note the potential inconvenience in needing to manage two separate config files
|
||||||
above example, very likely with all but one line of difference. Templating enables
|
in the above example, very likely with all but one line of difference.
|
||||||
populating config template files dynamically with theme-specific variables of your
|
Templating enables populating config template files dynamically with
|
||||||
choosing.
|
theme-specific variables of your choosing.
|
||||||
|
|
||||||
|
|
||||||
### Reload scripts
|
### Reload scripts
|
||||||
After symlinking a new set of config files, it is often necessary to reload the system or
|
After symlinking a new set of config files, it is often necessary to reload the
|
||||||
relevant apps in order for the new config settings to apply. Within an app's subdirectory,
|
system or relevant apps in order for the new config settings to apply. Within
|
||||||
a `call/` folder can be created to hold scripts that should apply based on certain schemes
|
an app's subdirectory, a `call/` folder can be created to hold scripts that
|
||||||
or palettes (matching them in the same way as config files). For example,
|
should apply based on certain schemes or palettes (matching them in the same
|
||||||
|
way as config files). For example,
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
<config-home>
|
<config-home>
|
||||||
@@ -99,22 +103,22 @@ or palettes (matching them in the same way as config files). For example,
|
|||||||
└── none-none.sh
|
└── none-none.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
`none-none.sh` might simply contain `kill -s USR1 $(pgrep kitty)`, which is a way to tell
|
`none-none.sh` might simply contain `kill -s USR1 $(pgrep kitty)`, which is a
|
||||||
all running `kitty` instances to reload their config settings. Again, following the naming
|
way to tell all running `kitty` instances to reload their config settings.
|
||||||
scheme for config files, a script named `none-none.sh` will apply under any scheme or
|
Again, following the naming scheme for config files, a script named
|
||||||
palette specification. Thus, in our light/dark mode switch example, invoking `symconf
|
`none-none.sh` will apply under any scheme or palette specification. Thus, in
|
||||||
--theme=light --apps=kitty` would:
|
our light/dark mode switch example, invoking `symconf --theme=light
|
||||||
|
--apps=kitty` would:
|
||||||
|
|
||||||
1. Search and match the config name `none-light.kitty.conf` and symlink it to
|
1. Search and match the config name `none-light.kitty.conf` and symlink it to
|
||||||
`~/.config/kitty/kitty.conf`.
|
`~/.config/kitty/kitty.conf`.
|
||||||
2. Search and match `none-none.sh` and execute it, applying the new light mode settings to
|
2. Search and match `none-none.sh` and execute it, applying the new light mode
|
||||||
all running `kitty` instances.
|
settings to all running `kitty` instances.
|
||||||
|
|
||||||
|
|
||||||
## App registry
|
## App registry
|
||||||
An `app_registry.toml` file, used to specify the target locations for app-specific
|
An `app_registry.toml` file, used to specify the target locations for
|
||||||
config files. To "register" an app, you simply need to add the following text block to
|
app-specific config files. To "register" an app, you simply need to add the
|
||||||
the `app_registry.toml` file:
|
following text block to the `app_registry.toml` file:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[app.<app-name>]
|
[app.<app-name>]
|
||||||
@@ -128,22 +132,22 @@ config_map = {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
(Note that text in angle brackets refers to values that should be replaced.) This tells
|
(Note that text in angle brackets refers to values that should be replaced.)
|
||||||
`symconf` how it should handle each app's config files. The `<app-name>` (e.g.,
|
This tells `symconf` how it should handle each app's config files. The
|
||||||
`kitty`) should correspond to a subdirectory under `apps/` (e.g., `apps/kitty/`) that
|
`<app-name>` (e.g., `kitty`) should correspond to a subdirectory under `apps/`
|
||||||
holds your config files for that app. As shown, you then need to supply either of the
|
(e.g., `apps/kitty/`) that holds your config files for that app. As shown, you
|
||||||
following options:
|
then need to supply either of the following options:
|
||||||
|
|
||||||
- `config_dir`: specifies a single directory where all of the app's matching config
|
- `config_dir`: specifies a single directory where all of the app's matching
|
||||||
files should be symlinked. In the `kitty` example, this might be `~/.config/kitty`.
|
config files should be symlinked. In the `kitty` example, this might be
|
||||||
This is the simplest and most common option provided most apps expect all of their
|
`~/.config/kitty`. This is the simplest and most common option provided most
|
||||||
config files to be in a single directory.
|
apps expect all of their config files to be in a single directory.
|
||||||
- `config_map`: a dictionary mapping config file _path names_ to the _exact paths_ that
|
- `config_map`: a dictionary mapping config file _path names_ to the _exact
|
||||||
should be created during the symlink process. This is typically needed when an app
|
paths_ that should be created during the symlink process. This is typically
|
||||||
has many config files that need to be set in several disparate locations across your
|
needed when an app has many config files that need to be set in several
|
||||||
system. In the `kitty` example, although not necessary (and in general you should
|
disparate locations across your system. In the `kitty` example, although not
|
||||||
prefer to set `config_dir` when applicable), we could have the following
|
necessary (and in general you should prefer to set `config_dir` when
|
||||||
`config_map`:
|
applicable), we could have the following `config_map`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[app.kitty]
|
[app.kitty]
|
||||||
@@ -152,8 +156,9 @@ following options:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This tells `symconf` to symlink the exact location `~/.config/kitty/kitty.conf` to
|
This tells `symconf` to symlink the exact location
|
||||||
the matching `kitty.conf` under the `apps/kitty` directory.
|
`~/.config/kitty/kitty.conf` to the matching `kitty.conf` under the
|
||||||
|
`apps/kitty` directory.
|
||||||
|
|
||||||
## Directory structure
|
## Directory structure
|
||||||
In total, the structure of your base config directory can look as follows:
|
In total, the structure of your base config directory can look as follows:
|
||||||
|
|||||||
@@ -1,6 +1,170 @@
|
|||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
```{toctree}
|
```sh
|
||||||
:hidden:
|
usage: symconf [-h] [-c CONFIG_DIR] [-v] {config,generate,install,update} ...
|
||||||
|
|
||||||
|
Manage application configuration with symlinks.
|
||||||
|
|
||||||
|
options:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
-c CONFIG_DIR, --config-dir CONFIG_DIR
|
||||||
|
Path to config directory
|
||||||
|
-v, --version Print symconf version
|
||||||
|
|
||||||
|
subcommand actions:
|
||||||
|
{config,generate,install,update}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Additional argument details:
|
||||||
|
|
||||||
|
- `-h --help`: print help message
|
||||||
|
- `-c --config-dir`: the location of the `symconf` config directory. Assumes
|
||||||
|
`$XDG_CONFIG_HOME` (e.g., `~/.config/symconf/`) by default.
|
||||||
|
|
||||||
|
## `config` subcommand
|
||||||
|
The config subcommand applies symlinks for registered application routes that
|
||||||
|
meet specified constraints.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
usage: symconf config [-h] [-s STYLE] [-m MODE] [-a APPS] [-T TEMPLATE_VARS [TEMPLATE_VARS ...]]
|
||||||
|
|
||||||
|
Set config files for registered applications.
|
||||||
|
|
||||||
|
options:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
-s STYLE, --style STYLE
|
||||||
|
Style indicator (often a color palette) capturing thematic details in a config file
|
||||||
|
-m MODE, --mode MODE Preferred lightness mode/scheme, either "light," "dark," "any," or "none."
|
||||||
|
-a APPS, --apps APPS Application target for theme. App must be present in the registry. Use "*" to apply to all registered apps
|
||||||
|
-T TEMPLATE_VARS [TEMPLATE_VARS ...], --template-vars TEMPLATE_VARS [TEMPLATE_VARS ...]
|
||||||
|
Groups to use when populating templates, in the form group=value
|
||||||
|
```
|
||||||
|
|
||||||
|
- `symconf config` is the subcommand used to match and set available config
|
||||||
|
files for registered applications
|
||||||
|
* `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to
|
||||||
|
consider all registered apps.
|
||||||
|
* `-m --mode`: preferred lightness mode/scheme, either `light`, `dark`,
|
||||||
|
`any`, or `none`.
|
||||||
|
* `-s --style`: style indicator, often the name of a color palette, capturing
|
||||||
|
thematic details in a config file to be matched. `any` or `none` are
|
||||||
|
reserved keywords (see below).
|
||||||
|
* `-T --template-vars`: additional groups to use when populating templates,
|
||||||
|
in the form `<group>=<value>`, where `<group>` is a template group with a
|
||||||
|
folder `$CONFIG_HOME/groups/<group>/` and `<value>` should correspond to a
|
||||||
|
TOML file in this folder (i.e., `<value>.toml`).
|
||||||
|
|
||||||
|
|
||||||
|
## `generate` subcommand
|
||||||
|
The generate subcommand fills in templates with theme values matched under
|
||||||
|
provided constraints,
|
||||||
|
|
||||||
|
```sh
|
||||||
|
usage: symconf generate [-h] -o OUTPUT_DIR [-s STYLE] [-m MODE] [-a APPS] [-T TEMPLATE_VARS [TEMPLATE_VARS ...]]
|
||||||
|
|
||||||
|
Generate all template config files for specified apps
|
||||||
|
|
||||||
|
options:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
-o OUTPUT_DIR, --output-dir OUTPUT_DIR
|
||||||
|
Path to write generated template files
|
||||||
|
-s STYLE, --style STYLE
|
||||||
|
Style indicator (often a color palette) capturing thematic details in a config file
|
||||||
|
-m MODE, --mode MODE Preferred lightness mode/scheme, either "light," "dark," "any," or "none."
|
||||||
|
-a APPS, --apps APPS Application target for theme. App must be present in the registry. Use "*" to apply to all registered apps
|
||||||
|
-T TEMPLATE_VARS [TEMPLATE_VARS ...], --template-vars TEMPLATE_VARS [TEMPLATE_VARS ...]
|
||||||
|
Groups to use when populating templates, in the form group=value
|
||||||
|
```
|
||||||
|
|
||||||
|
- `symconf generate` is a subcommand that can be used for batch generation of
|
||||||
|
config files. It accepts the same arguments as `symconf config`, but rather
|
||||||
|
than selecting the best match to be used for the system setting, all matching
|
||||||
|
templates are generated. There is one additional required argument:
|
||||||
|
* `-o --output-dir`: the directory under which generated config files should
|
||||||
|
be written. App-specific subdirectories are created to house config files
|
||||||
|
for each provided app.
|
||||||
|
|
||||||
|
## `install` subcommand
|
||||||
|
The install subcommand runs the `install.sh` scripts for registered apps.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
usage: symconf install [-h] [-a APPS]
|
||||||
|
|
||||||
|
Run install scripts for registered applications.
|
||||||
|
|
||||||
|
options:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
-a APPS, --apps APPS Application target for theme. App must be present in the registry. Use "*" to apply to all registered apps
|
||||||
|
```
|
||||||
|
|
||||||
|
- `symconf install`: runs install scripts for matching apps
|
||||||
|
* `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to
|
||||||
|
consider all registered apps.
|
||||||
|
|
||||||
|
## `update` subcommand
|
||||||
|
The update subcommand runs the `update.sh` scripts for registered apps. This
|
||||||
|
action expects the install process for each matched app to have been run
|
||||||
|
beforehand.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
usage: symconf update [-h] [-a APPS]
|
||||||
|
|
||||||
|
Run update scripts for registered applications.
|
||||||
|
|
||||||
|
options:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
-a APPS, --apps APPS Application target for theme. App must be present in the registry. Use "*" to apply to all registered apps
|
||||||
|
```
|
||||||
|
|
||||||
|
- `symconf update`: runs update scripts for matching apps that specify one
|
||||||
|
* `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to
|
||||||
|
consider all registered apps.
|
||||||
|
|
||||||
|
## Matching factors
|
||||||
|
The keywords `any` and `none` can be used when specifying `--mode`, `--style`,
|
||||||
|
or as a value in `--template-vars` (and we refer to each of these variables as
|
||||||
|
_factors_ that help determine a config match):
|
||||||
|
|
||||||
|
- `any` will match config files with _any_ value for this factor, preferring
|
||||||
|
config files with a value `none`, indicating no dependence on the factor.
|
||||||
|
This is the default value when a factor is left unspecified.
|
||||||
|
- `none` will match `"none"` directly for a given factor (so no special
|
||||||
|
behavior), but used to indicate that a config file is independent of the
|
||||||
|
factor. For instance,
|
||||||
|
|
||||||
|
```sh
|
||||||
|
symconf config -m light -s none
|
||||||
|
```
|
||||||
|
|
||||||
|
will match config files that capture the notion of a light mode, but do not
|
||||||
|
depend on or provide further thematic components such as a color palette.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
- Set a dark mode for all registered apps, matching any available style/palette
|
||||||
|
component:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
symconf config -m dark
|
||||||
|
```
|
||||||
|
- Set `solarized` theme for `kitty` and match any available mode (light or
|
||||||
|
dark):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
symconf config -s solarized -a kitty
|
||||||
|
```
|
||||||
|
- Set a dark `gruvbox` theme for multiple apps (but not all):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
symconf config -m dark -s gruvbox -apps="kitty,nvim"
|
||||||
|
```
|
||||||
|
- Set a dark `gruvbox` theme for all apps, and attempt to match other template
|
||||||
|
elements:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
symconf config -m dark -s gruvbox -T font=mono window=sharp
|
||||||
|
```
|
||||||
|
|
||||||
|
which would attempt to find and load key-value pairs in the files
|
||||||
|
`$CONFIG_HOME/groups/font/mono.toml` and
|
||||||
|
`$CONFIG_HOME/groups/window/sharp.toml` to be used as values when filling
|
||||||
|
templatized config files.
|
||||||
|
|||||||
@@ -1,27 +1,29 @@
|
|||||||
[build-system]
|
[build-system]
|
||||||
requires = ["setuptools", "wheel", "setuptools-git-versioning>=2.0,<3"]
|
requires = ["setuptools", "wheel"]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
[tool.setuptools-git-versioning]
|
|
||||||
enabled = true
|
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "symconf"
|
name = "symconf"
|
||||||
|
version = "0.8.4"
|
||||||
description = "Local app configuration manager"
|
description = "Local app configuration manager"
|
||||||
readme = "README.md"
|
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
dynamic = ["version"]
|
|
||||||
#license = {file = "LICENSE"}
|
|
||||||
authors = [
|
authors = [
|
||||||
{ name="Sam Griesemer", email="samgriesemer+git@gmail.com" },
|
{ name="Sam Griesemer", email="git@olog.io" },
|
||||||
|
]
|
||||||
|
readme = "README.md"
|
||||||
|
license = "MIT"
|
||||||
|
keywords = [
|
||||||
|
"tempate-engine",
|
||||||
|
"theme-switcher",
|
||||||
|
"configuration-files",
|
||||||
]
|
]
|
||||||
keywords = ["config"]
|
|
||||||
classifiers = [
|
classifiers = [
|
||||||
"Programming Language :: Python :: 3.12",
|
"Programming Language :: Python",
|
||||||
"License :: OSI Approved :: MIT License",
|
|
||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
"Development Status :: 3 - Alpha",
|
"Development Status :: 3 - Alpha",
|
||||||
|
|
||||||
"Intended Audience :: Developers",
|
"Intended Audience :: Developers",
|
||||||
|
"Intended Audience :: End Users/Desktop",
|
||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pyxdg",
|
"pyxdg",
|
||||||
@@ -32,15 +34,19 @@ dependencies = [
|
|||||||
symconf = "symconf.__main__:main"
|
symconf = "symconf.__main__:main"
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
tests = ["pytest"]
|
dev = [
|
||||||
docs = [
|
"ipykernel",
|
||||||
|
]
|
||||||
|
doc = [
|
||||||
"sphinx",
|
"sphinx",
|
||||||
"sphinx-togglebutton",
|
"sphinx-togglebutton",
|
||||||
"sphinx-autodoc-typehints",
|
"sphinx-autodoc-typehints",
|
||||||
"furo",
|
"furo",
|
||||||
"myst-parser",
|
"myst-parser",
|
||||||
]
|
]
|
||||||
build = ["build", "twine"]
|
test = [
|
||||||
|
"pytest"
|
||||||
|
]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Homepage = "https://doc.olog.io/symconf"
|
Homepage = "https://doc.olog.io/symconf"
|
||||||
@@ -49,4 +55,20 @@ Repository = "https://git.olog.io/olog/symconf"
|
|||||||
Issues = "https://git.olog.io/olog/symconf/issues"
|
Issues = "https://git.olog.io/olog/symconf/issues"
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
include = ["symconf*"] # pattern to match package names
|
include = ["symconf*"]
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 79
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["ANN", "E", "F", "UP", "B", "SIM", "I", "C4", "PERF"]
|
||||||
|
|
||||||
|
[tool.ruff.lint.isort]
|
||||||
|
length-sort = true
|
||||||
|
order-by-type = false
|
||||||
|
force-sort-within-sections = false
|
||||||
|
|
||||||
|
[tool.ruff.format]
|
||||||
|
quote-style = "double"
|
||||||
|
indent-style = "space"
|
||||||
|
docstring-code-format = true
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
from symconf.runner import Runner
|
from importlib.metadata import version
|
||||||
from symconf.reader import DictReader
|
|
||||||
|
from symconf import util, config, reader, matching, template
|
||||||
from symconf.config import ConfigManager
|
from symconf.config import ConfigManager
|
||||||
|
from symconf.reader import DictReader
|
||||||
|
from symconf.runner import Runner
|
||||||
from symconf.matching import Matcher, FilePart
|
from symconf.matching import Matcher, FilePart
|
||||||
from symconf.template import Template, FileTemplate, TOMLTemplate
|
from symconf.template import Template, FileTemplate, TOMLTemplate
|
||||||
|
|
||||||
from symconf import config
|
__version__ = version("symconf")
|
||||||
from symconf import matching
|
|
||||||
from symconf import reader
|
|
||||||
from symconf import template
|
|
||||||
from symconf import util
|
|
||||||
|
|
||||||
from importlib.metadata import version
|
|
||||||
|
|
||||||
|
|
||||||
__version__ = version('symconf')
|
|
||||||
|
|||||||
@@ -1,179 +1,214 @@
|
|||||||
import argparse
|
from argparse import Namespace, ArgumentParser
|
||||||
from importlib.metadata import version
|
|
||||||
|
|
||||||
from symconf import util, __version__
|
from symconf import util, __version__
|
||||||
from symconf.config import ConfigManager
|
from symconf.config import ConfigManager
|
||||||
|
|
||||||
|
|
||||||
def add_install_subparser(subparsers):
|
def add_install_subparser(subparsers: ArgumentParser) -> None:
|
||||||
def install_apps(args):
|
def install_apps(args: Namespace) -> None:
|
||||||
cm = ConfigManager(args.config_dir)
|
cm = ConfigManager(args.config_dir)
|
||||||
cm.install_apps(apps=args.apps)
|
cm.install_apps(apps=args.apps)
|
||||||
|
|
||||||
parser = subparsers.add_parser(
|
parser = subparsers.add_parser(
|
||||||
'install',
|
"install",
|
||||||
description='Run install scripts for registered applications.'
|
description="Run install scripts for registered applications.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-a', '--apps',
|
"-a",
|
||||||
required = False,
|
"--apps",
|
||||||
default = "*",
|
required=False,
|
||||||
type = lambda s: s.split(',') if s != '*' else s,
|
default="*",
|
||||||
help = 'Application target for theme. App must be present in the registry. ' \
|
type=lambda s: s.split(",") if s != "*" else s,
|
||||||
+ 'Use "*" to apply to all registered apps'
|
help=(
|
||||||
|
"Application target for theme. App must be present in the "
|
||||||
|
'registry. Use "*" to apply to all registered apps'
|
||||||
|
),
|
||||||
)
|
)
|
||||||
parser.set_defaults(func=install_apps)
|
parser.set_defaults(func=install_apps)
|
||||||
|
|
||||||
def add_update_subparser(subparsers):
|
|
||||||
def update_apps(args):
|
def add_update_subparser(subparsers: ArgumentParser) -> None:
|
||||||
|
def update_apps(args: Namespace) -> None:
|
||||||
cm = ConfigManager(args.config_dir)
|
cm = ConfigManager(args.config_dir)
|
||||||
cm.update_apps(apps=args.apps)
|
cm.update_apps(apps=args.apps)
|
||||||
|
|
||||||
parser = subparsers.add_parser(
|
parser = subparsers.add_parser(
|
||||||
'update',
|
"update", description="Run update scripts for registered applications."
|
||||||
description='Run update scripts for registered applications.'
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-a', '--apps',
|
"-a",
|
||||||
required = False,
|
"--apps",
|
||||||
default = '*',
|
required=False,
|
||||||
type = lambda s: s.split(',') if s != '*' else s,
|
default="*",
|
||||||
help = 'Application target for theme. App must be present in the registry. ' \
|
type=lambda s: s.split(",") if s != "*" else s,
|
||||||
+ 'Use "*" to apply to all registered apps'
|
help=(
|
||||||
|
"Application target for theme. App must be present in the "
|
||||||
|
'registry. Use "*" to apply to all registered apps'
|
||||||
|
),
|
||||||
)
|
)
|
||||||
parser.set_defaults(func=update_apps)
|
parser.set_defaults(func=update_apps)
|
||||||
|
|
||||||
def add_config_subparser(subparsers):
|
|
||||||
def configure_apps(args):
|
def add_config_subparser(subparsers: ArgumentParser) -> None:
|
||||||
|
def configure_apps(args: Namespace) -> None:
|
||||||
cm = ConfigManager(args.config_dir)
|
cm = ConfigManager(args.config_dir)
|
||||||
cm.configure_apps(
|
cm.configure_apps(
|
||||||
apps=args.apps,
|
apps=args.apps,
|
||||||
scheme=args.mode,
|
scheme=args.mode,
|
||||||
style=args.style,
|
style=args.style,
|
||||||
**args.template_vars
|
**args.template_vars,
|
||||||
)
|
)
|
||||||
|
|
||||||
parser = subparsers.add_parser(
|
parser = subparsers.add_parser(
|
||||||
'config',
|
"config", description="Set config files for registered applications."
|
||||||
description='Set config files for registered applications.'
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-s', '--style',
|
"-s",
|
||||||
required = False,
|
"--style",
|
||||||
default = 'any',
|
required=False,
|
||||||
help = 'Style indicator (often a color palette) capturing thematic details in '
|
default="any",
|
||||||
'a config file'
|
help=(
|
||||||
|
"Style indicator (often a color palette) capturing "
|
||||||
|
"thematic details in a config file"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-m', '--mode',
|
"-m",
|
||||||
required = False,
|
"--mode",
|
||||||
default = "any",
|
required=False,
|
||||||
help = 'Preferred lightness mode/scheme, either "light," "dark," "any," or "none."'
|
default="any",
|
||||||
|
help=(
|
||||||
|
'Preferred lightness mode/scheme, either "light," "dark," '
|
||||||
|
'"any," or "none."'
|
||||||
|
),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-a', '--apps',
|
"-a",
|
||||||
required = False,
|
"--apps",
|
||||||
default = "*",
|
required=False,
|
||||||
type = lambda s: s.split(',') if s != '*' else s,
|
default="*",
|
||||||
help = 'Application target for theme. App must be present in the registry. ' \
|
type=lambda s: s.split(",") if s != "*" else s,
|
||||||
+ 'Use "*" to apply to all registered apps'
|
help=(
|
||||||
|
"Application target for theme. App must be present in the "
|
||||||
|
'registry. Use "*" to apply to all registered apps'
|
||||||
|
),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-T', '--template-vars',
|
"-T",
|
||||||
required = False,
|
"--template-vars",
|
||||||
nargs='+',
|
required=False,
|
||||||
default = {},
|
nargs="+",
|
||||||
|
default={},
|
||||||
action=util.KVPair,
|
action=util.KVPair,
|
||||||
help='Groups to use when populating templates, in the form group=value'
|
help=(
|
||||||
|
"Groups to use when populating templates, in the form group=value"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
parser.set_defaults(func=configure_apps)
|
parser.set_defaults(func=configure_apps)
|
||||||
|
|
||||||
def add_generate_subparser(subparsers):
|
|
||||||
def generate_apps(args):
|
def add_generate_subparser(subparsers: ArgumentParser) -> None:
|
||||||
|
def generate_apps(args: Namespace) -> None:
|
||||||
cm = ConfigManager(args.config_dir)
|
cm = ConfigManager(args.config_dir)
|
||||||
cm.generate_app_templates(
|
cm.generate_app_templates(
|
||||||
gen_dir=args.output_dir,
|
gen_dir=args.output_dir,
|
||||||
apps=args.apps,
|
apps=args.apps,
|
||||||
scheme=args.mode,
|
scheme=args.mode,
|
||||||
style=args.style,
|
style=args.style,
|
||||||
**args.template_vars
|
**args.template_vars,
|
||||||
)
|
)
|
||||||
|
|
||||||
parser = subparsers.add_parser(
|
parser = subparsers.add_parser(
|
||||||
'generate',
|
"generate",
|
||||||
description='Generate all template config files for specified apps'
|
description="Generate all template config files for specified apps",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-o', '--output-dir',
|
"-o",
|
||||||
required = True,
|
"--output-dir",
|
||||||
type = util.absolute_path,
|
required=True,
|
||||||
help = 'Path to write generated template files'
|
type=util.absolute_path,
|
||||||
|
help="Path to write generated template files",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-s', '--style',
|
"-s",
|
||||||
required = False,
|
"--style",
|
||||||
default = 'any',
|
required=False,
|
||||||
help = 'Style indicator (often a color palette) capturing thematic details in '
|
default="any",
|
||||||
'a config file'
|
help=(
|
||||||
|
"Style indicator (often a color palette) capturing "
|
||||||
|
"thematic details in a config file"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-m', '--mode',
|
"-m",
|
||||||
required = False,
|
"--mode",
|
||||||
default = "any",
|
required=False,
|
||||||
help = 'Preferred lightness mode/scheme, either "light," "dark," "any," or "none."'
|
default="any",
|
||||||
|
help=(
|
||||||
|
'Preferred lightness mode/scheme, either "light," "dark," '
|
||||||
|
'"any," or "none."'
|
||||||
|
),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-a', '--apps',
|
"-a",
|
||||||
required = False,
|
"--apps",
|
||||||
default = "*",
|
required=False,
|
||||||
type = lambda s: s.split(',') if s != '*' else s,
|
default="*",
|
||||||
help = 'Application target for theme. App must be present in the registry. ' \
|
type=lambda s: s.split(",") if s != "*" else s,
|
||||||
+ 'Use "*" to apply to all registered apps'
|
help=(
|
||||||
|
"Application target for theme. App must be present in the "
|
||||||
|
'registry. Use "*" to apply to all registered apps'
|
||||||
|
),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-T', '--template-vars',
|
"-T",
|
||||||
required = False,
|
"--template-vars",
|
||||||
nargs = '+',
|
required=False,
|
||||||
default = {},
|
nargs="+",
|
||||||
action = util.KVPair,
|
default={},
|
||||||
help = 'Groups to use when populating templates, in the form group=value'
|
action=util.KVPair,
|
||||||
|
help=(
|
||||||
|
"Groups to use when populating templates, in the form group=value"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
parser.set_defaults(func=generate_apps)
|
parser.set_defaults(func=generate_apps)
|
||||||
|
|
||||||
|
|
||||||
# central argparse entry point
|
# central argparse entry point
|
||||||
parser = argparse.ArgumentParser(
|
parser = ArgumentParser(
|
||||||
'symconf',
|
"symconf", description="Manage application configuration with symlinks."
|
||||||
description='Manage application configuration with symlinks.'
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-c', '--config-dir',
|
"-c",
|
||||||
default = util.xdg_config_path(),
|
"--config-dir",
|
||||||
type = util.absolute_path,
|
default=util.xdg_config_path(),
|
||||||
help = 'Path to config directory'
|
type=util.absolute_path,
|
||||||
|
help="Path to config directory",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-v', '--version',
|
"-v",
|
||||||
action='version',
|
"--version",
|
||||||
|
action="version",
|
||||||
version=__version__,
|
version=__version__,
|
||||||
help = 'Print symconf version'
|
help="Print symconf version",
|
||||||
)
|
)
|
||||||
|
|
||||||
# add subparsers
|
# add subparsers
|
||||||
subparsers = parser.add_subparsers(title='subcommand actions')
|
subparsers = parser.add_subparsers(title="subcommand actions")
|
||||||
add_config_subparser(subparsers)
|
add_config_subparser(subparsers)
|
||||||
add_generate_subparser(subparsers)
|
add_generate_subparser(subparsers)
|
||||||
add_install_subparser(subparsers)
|
add_install_subparser(subparsers)
|
||||||
add_update_subparser(subparsers)
|
add_update_subparser(subparsers)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if 'func' in args:
|
if "func" in args:
|
||||||
args.func(args)
|
args.func(args)
|
||||||
else:
|
else:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
|||||||
'''
|
"""
|
||||||
Generic combinatorial name-matching subsystem
|
Generic combinatorial name-matching subsystem
|
||||||
|
|
||||||
Config files are expected to have names matching the following spec:
|
Config files are expected to have names matching the following spec:
|
||||||
@@ -7,13 +7,14 @@ Config files are expected to have names matching the following spec:
|
|||||||
|
|
||||||
<style>-<scheme>.<config_pathname>
|
<style>-<scheme>.<config_pathname>
|
||||||
|
|
||||||
- ``config_pathname``: refers to a concrete filename, typically that which is expected by
|
- ``config_pathname``: refers to a concrete filename, typically that which is
|
||||||
the target app (e.g., ``kitty.conf``). In the context of ``config_map`` in the registry,
|
expected by the target app (e.g., ``kitty.conf``). In the context of
|
||||||
however, it merely serves as an identifier, as it can be mapped onto any path.
|
``config_map`` in the registry, however, it merely serves as an identifier,
|
||||||
|
as it can be mapped onto any path.
|
||||||
- ``scheme``: indicates the lightness mode ("light" or "dark")
|
- ``scheme``: indicates the lightness mode ("light" or "dark")
|
||||||
- ``style``: general identifier capturing the stylizations applied to the config file.
|
- ``style``: general identifier capturing the stylizations applied to the
|
||||||
This is typically of the form ``<variant>-<palette>``, i.e., including a reference to a
|
config file. This is typically of the form ``<variant>-<palette>``, i.e.,
|
||||||
particular color palette.
|
including a reference to a particular color palette.
|
||||||
|
|
||||||
For example
|
For example
|
||||||
|
|
||||||
@@ -21,14 +22,14 @@ For example
|
|||||||
|
|
||||||
soft-gruvbox-dark.kitty.conf
|
soft-gruvbox-dark.kitty.conf
|
||||||
|
|
||||||
gets mapped to
|
gets mapped to
|
||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
style -> "soft-gruvbox"
|
style -> "soft-gruvbox"
|
||||||
scheme -> "dark"
|
scheme -> "dark"
|
||||||
pathname -> "kitty.conf"
|
pathname -> "kitty.conf"
|
||||||
'''
|
"""
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -36,33 +37,35 @@ from symconf import util
|
|||||||
|
|
||||||
|
|
||||||
class FilePart:
|
class FilePart:
|
||||||
def __init__(self, path: str | Path):
|
def __init__(self, path: str | Path) -> None:
|
||||||
self.path = util.absolute_path(path)
|
self.path = util.absolute_path(path)
|
||||||
self.pathname = self.path.name
|
self.pathname = self.path.name
|
||||||
|
|
||||||
parts = str(self.pathname).split('.')
|
parts = str(self.pathname).split(".")
|
||||||
if len(parts) < 2:
|
if len(parts) < 2:
|
||||||
raise ValueError(f'Filename "{pathname}" incorrectly formatted, ignoring')
|
raise ValueError(
|
||||||
|
f'Filename "{self.pathname}" incorrectly formatted, ignoring'
|
||||||
|
)
|
||||||
|
|
||||||
self.theme = parts[0]
|
self.theme = parts[0]
|
||||||
self.conf = '.'.join(parts[1:])
|
self.conf = ".".join(parts[1:])
|
||||||
|
|
||||||
theme_split = self.theme.split('-')
|
theme_split = self.theme.split("-")
|
||||||
self.scheme = theme_split[-1]
|
self.scheme = theme_split[-1]
|
||||||
self.style = '-'.join(theme_split[:-1])
|
self.style = "-".join(theme_split[:-1])
|
||||||
|
|
||||||
self.index = -1
|
self.index = -1
|
||||||
|
|
||||||
def set_index(self, idx: int):
|
def set_index(self, idx: int) -> None:
|
||||||
self.index = idx
|
self.index = idx
|
||||||
|
|
||||||
|
|
||||||
class Matcher:
|
class Matcher:
|
||||||
def get_file_parts(
|
def get_file_parts(
|
||||||
self,
|
self,
|
||||||
paths: list[str | Path],
|
paths: list[str | Path],
|
||||||
) -> list[FilePart]:
|
) -> list[FilePart]:
|
||||||
'''
|
"""
|
||||||
Split pathnames into parts for matching.
|
Split pathnames into parts for matching.
|
||||||
|
|
||||||
Pathnames should be of the format
|
Pathnames should be of the format
|
||||||
@@ -71,123 +74,128 @@ class Matcher:
|
|||||||
|
|
||||||
<style>-<scheme>.<config_pathname>
|
<style>-<scheme>.<config_pathname>
|
||||||
|
|
||||||
where ``style`` is typically itself of the form ``<variant>-<palette>``.
|
where ``style`` is typically itself of the form
|
||||||
'''
|
``<variant>-<palette>``.
|
||||||
|
"""
|
||||||
|
|
||||||
file_parts = []
|
file_parts = []
|
||||||
for path in paths:
|
for path in paths:
|
||||||
try:
|
try:
|
||||||
config_file = FilePart(path)
|
config_file = FilePart(path)
|
||||||
file_parts.append(config_file)
|
file_parts.append(config_file)
|
||||||
except ValueError as e:
|
except ValueError:
|
||||||
print(f'Filename "{pathname}" incorrectly formatted, ignoring')
|
print(f'Filename "{path}" incorrectly formatted, ignoring')
|
||||||
|
|
||||||
return file_parts
|
return file_parts
|
||||||
|
|
||||||
def prefix_order(
|
def prefix_order(
|
||||||
self,
|
self,
|
||||||
scheme,
|
scheme: str,
|
||||||
style,
|
style: str,
|
||||||
strict=False,
|
strict: bool = False,
|
||||||
) -> list[tuple[str, str]]:
|
) -> list[tuple[str, str]]:
|
||||||
'''
|
"""
|
||||||
Determine the order of concrete config pathname parts to match, given the
|
Determine the order of concrete config pathname parts to match, given
|
||||||
``scheme`` and ``style`` inputs.
|
the ``scheme`` and ``style`` inputs.
|
||||||
|
|
||||||
There is a unique preferred match order when ``style``, ``scheme``, both, or none
|
There is a unique preferred match order when ``style``, ``scheme``,
|
||||||
are ``any``. In general, when ``any`` is provided for a given factor, it is
|
both, or none are ``any``. In general, when ``any`` is provided for a
|
||||||
best matched by a config file that expresses indifference under that factor.
|
given factor, it is best matched by a config file that expresses
|
||||||
'''
|
indifference under that factor.
|
||||||
|
"""
|
||||||
|
|
||||||
# explicit cases are the most easily managed here, even if a little redundant
|
# explicit cases are the most easily managed here, even if a little
|
||||||
|
# redundant
|
||||||
if strict:
|
if strict:
|
||||||
theme_order = [
|
theme_order = [
|
||||||
(style, scheme),
|
(style, scheme),
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
# inverse order of match relaxation; intention being to overwrite with
|
# inverse order of match relaxation; intention being to overwrite
|
||||||
# results from increasingly relevant groups given the conditions
|
# with results from increasingly relevant groups given the
|
||||||
if style == 'any' and scheme == 'any':
|
# conditions
|
||||||
|
if style == "any" and scheme == "any":
|
||||||
# prefer both be "none", with preference for specific scheme
|
# prefer both be "none", with preference for specific scheme
|
||||||
theme_order = [
|
theme_order = [
|
||||||
(style , scheme),
|
(style, scheme),
|
||||||
(style , 'none'),
|
(style, "none"),
|
||||||
('none' , scheme),
|
("none", scheme),
|
||||||
('none' , 'none'),
|
("none", "none"),
|
||||||
]
|
]
|
||||||
elif style == 'any':
|
elif style == "any":
|
||||||
# prefer style to be "none", then specific, then relax specific scheme
|
# prefer style to be "none", then specific, then relax specific
|
||||||
# to "none"
|
# scheme to "none"
|
||||||
theme_order = [
|
theme_order = [
|
||||||
(style , 'none'),
|
(style, "none"),
|
||||||
('none' , 'none'),
|
("none", "none"),
|
||||||
(style , scheme),
|
(style, scheme),
|
||||||
('none' , scheme),
|
("none", scheme),
|
||||||
]
|
]
|
||||||
elif scheme == 'any':
|
elif scheme == "any":
|
||||||
# prefer scheme to be "none", then specific, then relax specific style
|
# prefer scheme to be "none", then specific, then relax
|
||||||
# to "none"
|
# specific style to "none"
|
||||||
theme_order = [
|
theme_order = [
|
||||||
('none' , scheme),
|
("none", scheme),
|
||||||
('none' , 'none'),
|
("none", "none"),
|
||||||
(style , scheme),
|
(style, scheme),
|
||||||
(style , 'none'),
|
(style, "none"),
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
# neither component is any; prefer most specific
|
# neither component is any; prefer most specific
|
||||||
theme_order = [
|
theme_order = [
|
||||||
('none' , 'none'),
|
("none", "none"),
|
||||||
('none' , scheme),
|
("none", scheme),
|
||||||
(style , 'none'),
|
(style, "none"),
|
||||||
(style , scheme),
|
(style, scheme),
|
||||||
]
|
]
|
||||||
|
|
||||||
return theme_order
|
return theme_order
|
||||||
|
|
||||||
def match_paths(
|
def match_paths(
|
||||||
self,
|
self,
|
||||||
paths: list[str | Path],
|
paths: list[str | Path],
|
||||||
prefix_order: list[tuple[str, str]],
|
prefix_order: list[tuple[str, str]],
|
||||||
) -> list[FilePart]:
|
) -> list[FilePart]:
|
||||||
'''
|
"""
|
||||||
Find and return FilePart matches according to the provided prefix order.
|
Find and return FilePart matches according to the provided prefix
|
||||||
|
order.
|
||||||
|
|
||||||
The prefix order specifies all valid style-scheme combos that can be considered as
|
The prefix order specifies all valid style-scheme combos that can be
|
||||||
"consistent" with some user input (and is computed external to this method). For
|
considered as "consistent" with some user input (and is computed
|
||||||
example, it could be
|
external to this method). For example, it could be
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
[
|
[("none", "none")("none", "dark")]
|
||||||
('none', 'none')
|
|
||||||
('none', 'dark')
|
|
||||||
]
|
|
||||||
|
|
||||||
indicating that either ``none-none.<config>`` or ``none-dark.<config>`` would be
|
indicating that either ``none-none.<config>`` or ``none-dark.<config>``
|
||||||
considered matching pathnames, with the latter being preferred.
|
would be considered matching pathnames, with the latter being
|
||||||
|
preferred.
|
||||||
|
|
||||||
|
This method exists because we need a way to allow any of the combos in
|
||||||
|
the prefix order to match the candidate files. We don't know a priori
|
||||||
|
how good of a match will be available, so we consider each file for
|
||||||
|
each of the prefixes, and take the latest/best match for each unique
|
||||||
|
config pathname (allowing for a "soft" match).
|
||||||
|
|
||||||
This method exists because we need a way to allow any of the combos in the prefix
|
|
||||||
order to match the candidate files. We don't know a priori how good of a match
|
|
||||||
will be available, so we consider each file for each of the prefixes, and take the
|
|
||||||
latest/best match for each unique config pathname (allowing for a "soft" match).
|
|
||||||
|
|
||||||
.. admonition:: Checking for matches
|
.. admonition:: Checking for matches
|
||||||
|
|
||||||
When thinking about how best to structure this method, it initially felt like
|
When thinking about how best to structure this method, it initially
|
||||||
indexing factors of the FileParts would make the most sense, preventing the
|
felt like indexing factors of the FileParts would make the most
|
||||||
inner loop that needs to inspect each FilePart for each element of the prefix
|
sense, preventing the inner loop that needs to inspect each
|
||||||
order. But indexing the file parts and checking against prefixes isn't so
|
FilePart for each element of the prefix order. But indexing the
|
||||||
straightforward, as we'd still need to check matches by factor. For instance,
|
file parts and checking against prefixes isn't so straightforward,
|
||||||
if we index by style-scheme, either are allowed to be "any," so we'd need to
|
as we'd still need to check matches by factor. For instance, if we
|
||||||
check for the 4 valid combos and join the matching lists. If we index by both
|
index by style-scheme, either are allowed to be "any," so we'd need
|
||||||
factors individually, we may have several files associated with a given key,
|
to check for the 4 valid combos and join the matching lists. If we
|
||||||
and then need to coordinate the checks across both to ensure they belong to
|
index by both factors individually, we may have several files
|
||||||
the same file.
|
associated with a given key, and then need to coordinate the checks
|
||||||
|
across both to ensure they belong to the same file.
|
||||||
|
|
||||||
In any case, you should be able to do this in a way that's a bit more
|
In any case, you should be able to do this in a way that's a bit
|
||||||
efficient, but the loop and the simple conditionals is just much simpler to
|
more efficient, but the loop and the simple conditionals is just
|
||||||
follow. We're also talking about at most 10s of files, so it really doesn't
|
much simpler to follow. We're also talking about at most 10s of
|
||||||
matter.
|
files, so it really doesn't matter.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
pathnames:
|
pathnames:
|
||||||
@@ -195,51 +203,53 @@ class Matcher:
|
|||||||
style:
|
style:
|
||||||
prefix_order:
|
prefix_order:
|
||||||
strict:
|
strict:
|
||||||
'''
|
"""
|
||||||
|
|
||||||
file_parts = self.get_file_parts(paths)
|
file_parts = self.get_file_parts(paths)
|
||||||
|
|
||||||
ordered_matches = []
|
ordered_matches = []
|
||||||
for i, (style_prefix, scheme_prefix) in enumerate(prefix_order):
|
for i, (style_prefix, scheme_prefix) in enumerate(prefix_order):
|
||||||
for fp in file_parts:
|
for fp in file_parts:
|
||||||
style_match = style_prefix == fp.style or style_prefix == 'any'
|
style_match = style_prefix == fp.style or style_prefix == "any"
|
||||||
scheme_match = scheme_prefix == fp.scheme or scheme_prefix == 'any'
|
scheme_match = (
|
||||||
|
scheme_prefix == fp.scheme or scheme_prefix == "any"
|
||||||
|
)
|
||||||
|
|
||||||
if style_match and scheme_match:
|
if style_match and scheme_match:
|
||||||
fp.set_index(i+1)
|
fp.set_index(i + 1)
|
||||||
ordered_matches.append(fp)
|
ordered_matches.append(fp)
|
||||||
|
|
||||||
return ordered_matches
|
return ordered_matches
|
||||||
|
|
||||||
def relaxed_match(
|
def relaxed_match(self, match_list: list[FilePart]) -> list[FilePart]:
|
||||||
self,
|
"""
|
||||||
match_list: list[FilePart]
|
|
||||||
) -> list[FilePart]:
|
|
||||||
'''
|
|
||||||
Isolate the best match in a match list and find its relaxed variants.
|
Isolate the best match in a match list and find its relaxed variants.
|
||||||
|
|
||||||
This method allows us to use the ``match_paths()`` method for matching templates
|
This method allows us to use the ``match_paths()`` method for matching
|
||||||
rather than direct user config files. In the latter case, we want to symlink the
|
templates rather than direct user config files. In the latter case, we
|
||||||
single best config file match for each stem, across all stems with matching
|
want to symlink the single best config file match for each stem, across
|
||||||
prefixes (e.g., ``none-dark.config.a`` and ``solarized-dark.config.b`` have two
|
all stems with matching prefixes (e.g., ``none-dark.config.a`` and
|
||||||
separate stems with prefixes that could match ``scheme=dark, style=any`` query).
|
``solarized-dark.config.b`` have two separate stems with prefixes that
|
||||||
We can find these files by just indexing the ``match_path`` outputs (i.e., all
|
could match ``scheme=dark, style=any`` query). We can find these files
|
||||||
matches) by config pathname and taking the one that appears latest (under the
|
by just indexing the ``match_path`` outputs (i.e., all matches) by
|
||||||
|
config pathname and taking the one that appears latest (under the
|
||||||
prefix order) for each unique value.
|
prefix order) for each unique value.
|
||||||
|
|
||||||
In the template matching case, we want only a single best file match, period
|
In the template matching case, we want only a single best file match,
|
||||||
(there's really no notion of "config stems," it's just the prefixes). Once that
|
period (there's really no notion of "config stems," it's just the
|
||||||
match has been found, we can then "relax" either the scheme or style (or both) to
|
prefixes). Once that match has been found, we can then "relax" either
|
||||||
``none``, and if the corresponding files exist, we use those as parts of the
|
the scheme or style (or both) to ``none``, and if the corresponding
|
||||||
template keys. For example, if we match ``solarized-dark.toml``, we would also
|
files exist, we use those as parts of the template keys. For example,
|
||||||
consider the values in ``none-dark.toml`` if available. The TOML values that are
|
if we match ``solarized-dark.toml``, we would also consider the values
|
||||||
defined in the most specific (i.e., better under the prefix order) match are
|
in ``none-dark.toml`` if available. The TOML values that are defined in
|
||||||
loaded "on top of" those less specific matches, overwriting keys when there's a
|
the most specific (i.e., better under the prefix order) match are
|
||||||
conflict. ``none-dark.toml``, for instance, might define a general dark scheme
|
loaded "on top of" those less specific matches, overwriting keys when
|
||||||
background color, but a more specific definition in ``solarized-dark.toml`` would
|
there's a conflict. ``none-dark.toml``, for instance, might define a
|
||||||
take precedent. These TOML files would be stacked before using the resulting
|
general dark scheme background color, but a more specific definition in
|
||||||
dictionary to populate config templates.
|
``solarized-dark.toml`` would take precedent. These TOML files would be
|
||||||
'''
|
stacked before using the resulting dictionary to populate config
|
||||||
|
templates.
|
||||||
|
"""
|
||||||
|
|
||||||
if not match_list:
|
if not match_list:
|
||||||
return []
|
return []
|
||||||
@@ -248,11 +258,10 @@ class Matcher:
|
|||||||
match = match_list[-1]
|
match = match_list[-1]
|
||||||
|
|
||||||
for fp in match_list:
|
for fp in match_list:
|
||||||
style_match = fp.style == match.style or fp.style == 'none'
|
style_match = fp.style == match.style or fp.style == "none"
|
||||||
scheme_match = fp.scheme == match.scheme or fp.scheme == 'none'
|
scheme_match = fp.scheme == match.scheme or fp.scheme == "none"
|
||||||
|
|
||||||
if style_match and scheme_match:
|
if style_match and scheme_match:
|
||||||
relaxed_map[fp.pathname] = fp
|
relaxed_map[fp.pathname] = fp
|
||||||
|
|
||||||
return list(relaxed_map.values())
|
return list(relaxed_map.values())
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +1,44 @@
|
|||||||
'''
|
"""
|
||||||
Simplified management for nested dictionaries
|
Simplified management for nested dictionaries
|
||||||
'''
|
"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import pprint
|
import pprint
|
||||||
import tomllib
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import logging
|
||||||
|
import tomllib
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from symconf.util import deep_update
|
from symconf.util import deep_update
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DictReader:
|
class DictReader:
|
||||||
def __init__(self, toml_path=None):
|
def __init__(self, toml_path: str | None = None) -> None:
|
||||||
self._config = {}
|
self._config = {}
|
||||||
self.toml_path = toml_path
|
self.toml_path = toml_path
|
||||||
|
|
||||||
if toml_path is not None:
|
if toml_path is not None:
|
||||||
self._config = self._load_toml(toml_path)
|
self._config = self._load_toml(toml_path)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return pprint.pformat(self._config, indent=4)
|
return pprint.pformat(self._config, indent=4)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _load_toml(toml_path) -> dict[str, Any]:
|
def _load_toml(toml_path: str) -> dict[str, Any]:
|
||||||
return tomllib.loads(Path(toml_path).read_text())
|
return tomllib.loads(Path(toml_path).read_text())
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, config_dict):
|
def from_dict(cls, config_dict: dict) -> "DictReader":
|
||||||
new_instance = cls()
|
new_instance = cls()
|
||||||
new_instance._config = copy.deepcopy(config_dict)
|
new_instance._config = copy.deepcopy(config_dict)
|
||||||
return new_instance
|
return new_instance
|
||||||
|
|
||||||
def update(self, config, in_place=False):
|
def update(
|
||||||
|
self, config: "DictReader", in_place: bool = False
|
||||||
|
) -> "DictReader":
|
||||||
new_config = deep_update(self._config, config._config)
|
new_config = deep_update(self._config, config._config)
|
||||||
|
|
||||||
if in_place:
|
if in_place:
|
||||||
@@ -42,13 +47,14 @@ class DictReader:
|
|||||||
|
|
||||||
return self.from_dict(new_config)
|
return self.from_dict(new_config)
|
||||||
|
|
||||||
def copy(self):
|
def copy(self) -> "DictReader":
|
||||||
return self.from_dict(copy.deepcopy(self._config))
|
return self.from_dict(copy.deepcopy(self._config))
|
||||||
|
|
||||||
def get_subconfig(self, key): pass
|
def get_subconfig(self, key: str) -> None: # "DictReader":
|
||||||
|
pass
|
||||||
|
|
||||||
def get(self, key, default=None):
|
def get(self, key: str, default: str | None = None) -> str | None:
|
||||||
keys = key.split('.')
|
keys = key.split(".")
|
||||||
|
|
||||||
subconfig = self._config
|
subconfig = self._config
|
||||||
for subkey in keys[:-1]:
|
for subkey in keys[:-1]:
|
||||||
@@ -59,8 +65,8 @@ class DictReader:
|
|||||||
|
|
||||||
return subconfig.get(keys[-1], default)
|
return subconfig.get(keys[-1], default)
|
||||||
|
|
||||||
def set(self, key, value):
|
def set(self, key: str, value: str | None) -> bool:
|
||||||
keys = key.split('.')
|
keys = key.split(".")
|
||||||
|
|
||||||
subconfig = self._config
|
subconfig = self._config
|
||||||
for subkey in keys[:-1]:
|
for subkey in keys[:-1]:
|
||||||
@@ -69,7 +75,8 @@ class DictReader:
|
|||||||
|
|
||||||
if type(subconfig) is not dict:
|
if type(subconfig) is not dict:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'Attempting to set nested key with an existing non-dict parent'
|
"Attempting to set nested key with an "
|
||||||
|
"existing non-dict parent"
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -79,20 +86,20 @@ class DictReader:
|
|||||||
subconfig[subkey] = subdict
|
subconfig[subkey] = subdict
|
||||||
subconfig = subdict
|
subconfig = subdict
|
||||||
|
|
||||||
subconfig.update({ keys[-1]: value })
|
subconfig.update({keys[-1]: value})
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def generate_hash(self, exclude_keys=None):
|
def generate_hash(self, exclude_keys: list[str] | None = None) -> str:
|
||||||
inst_copy = self.copy()
|
inst_copy = self.copy()
|
||||||
|
|
||||||
if exclude_keys is not None:
|
if exclude_keys is not None:
|
||||||
for key in exclude_keys:
|
for key in exclude_keys:
|
||||||
inst_copy.set(key, None)
|
inst_copy.set(key, None)
|
||||||
|
|
||||||
items = inst_copy._config.items()
|
items = inst_copy._config.items()
|
||||||
|
|
||||||
# create hash from config options
|
# create hash from config options
|
||||||
config_str = str(sorted(items))
|
config_str = str(sorted(items))
|
||||||
|
|
||||||
return hashlib.md5(config_str.encode()).hexdigest()
|
return hashlib.md5(config_str.encode()).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,54 +1,53 @@
|
|||||||
'''
|
"""
|
||||||
Handle job/script execution
|
Handle job/script execution
|
||||||
'''
|
"""
|
||||||
|
|
||||||
import stat
|
import stat
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from colorama import Fore, Back, Style
|
from colorama import Fore, Style
|
||||||
|
|
||||||
from symconf.util import printc, color_text
|
from symconf.util import color_text
|
||||||
|
|
||||||
|
|
||||||
class Runner:
|
class Runner:
|
||||||
def run_script(
|
def run_script(
|
||||||
self,
|
self,
|
||||||
script: str | Path,
|
script: str | Path,
|
||||||
):
|
) -> str | None:
|
||||||
script_path = Path(script)
|
script_path = Path(script)
|
||||||
|
|
||||||
if script_path.stat().st_mode & stat.S_IXUSR == 0:
|
if script_path.stat().st_mode & stat.S_IXUSR == 0:
|
||||||
print(
|
print(
|
||||||
color_text("│", Fore.BLUE),
|
color_text("│", Fore.BLUE),
|
||||||
color_text(
|
color_text(
|
||||||
f' > script "{script_path.name}" missing execute permissions, skipping',
|
f' > script "{script_path.name}" missing '
|
||||||
Fore.RED + Style.DIM
|
"execute permissions, skipping",
|
||||||
)
|
Fore.RED + Style.DIM,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
print(
|
print(
|
||||||
color_text("│", Fore.BLUE),
|
color_text("│", Fore.BLUE),
|
||||||
color_text(
|
color_text(f' > running script "{script_path.name}"', Fore.BLUE),
|
||||||
f' > running script "{script_path.name}"',
|
|
||||||
Fore.BLUE
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
output = subprocess.check_output(str(script_path), shell=True)
|
output = subprocess.check_output(str(script_path), shell=True)
|
||||||
|
|
||||||
if output:
|
if output:
|
||||||
fmt_output = output.decode().strip().replace(
|
fmt_output = (
|
||||||
'\n',
|
output.decode()
|
||||||
f'\n{Fore.BLUE}{Style.NORMAL}│{Style.DIM} '
|
.strip()
|
||||||
|
.replace("\n", f"\n{Fore.BLUE}{Style.NORMAL}│{Style.DIM} ")
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
color_text("│", Fore.BLUE),
|
color_text("│", Fore.BLUE),
|
||||||
color_text(
|
color_text(
|
||||||
f' captured script output "{fmt_output}"',
|
f' captured script output "{fmt_output}"',
|
||||||
Fore.BLUE + Style.DIM
|
Fore.BLUE + Style.DIM,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
return output
|
return output
|
||||||
@@ -56,7 +55,7 @@ class Runner:
|
|||||||
def run_many(
|
def run_many(
|
||||||
self,
|
self,
|
||||||
script_list: list[str | Path],
|
script_list: list[str | Path],
|
||||||
):
|
) -> list[str | None]:
|
||||||
outputs = []
|
outputs = []
|
||||||
for script in script_list:
|
for script in script_list:
|
||||||
output = self.run_script(script)
|
output = self.run_script(script)
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
'''
|
"""
|
||||||
Support for basic config templates
|
Support for basic config templates
|
||||||
'''
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import tomllib
|
import tomllib
|
||||||
|
from typing import Any
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from symconf import util
|
from symconf import util
|
||||||
@@ -13,37 +14,35 @@ from symconf.reader import DictReader
|
|||||||
class Template:
|
class Template:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
template_str : str,
|
template_str: str,
|
||||||
key_pattern : str = r'f{{(\S+?)}}',
|
key_pattern: str = r"f{{(\S+?)}}",
|
||||||
exe_pattern : str = r'x{{((?:(?!x{{).)*)}}',
|
exe_pattern: str = r"x{{((?:(?!x{{).)*)}}",
|
||||||
):
|
) -> None:
|
||||||
self.template_str = template_str
|
self.template_str = template_str
|
||||||
self.key_pattern = key_pattern
|
self.key_pattern = key_pattern
|
||||||
self.exe_pattern = exe_pattern
|
self.exe_pattern = exe_pattern
|
||||||
|
|
||||||
def fill(
|
def fill(
|
||||||
self,
|
self,
|
||||||
template_dict : dict,
|
template_dict: dict,
|
||||||
) -> str:
|
) -> str:
|
||||||
dr = DictReader.from_dict(template_dict)
|
dr = DictReader.from_dict(template_dict)
|
||||||
|
|
||||||
exe_filled = re.sub(
|
exe_filled = re.sub(
|
||||||
self.exe_pattern,
|
self.exe_pattern,
|
||||||
lambda m: self._exe_fill(m, dr),
|
lambda m: self._exe_fill(m, dr),
|
||||||
self.template_str
|
self.template_str,
|
||||||
)
|
)
|
||||||
|
|
||||||
key_filled = re.sub(
|
key_filled = re.sub(
|
||||||
self.key_pattern,
|
self.key_pattern, lambda m: self._key_fill(m, dr), exe_filled
|
||||||
lambda m: self._key_fill(m, dr),
|
|
||||||
exe_filled
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return key_filled
|
return key_filled
|
||||||
|
|
||||||
def _key_fill(
|
def _key_fill(
|
||||||
self,
|
self,
|
||||||
match,
|
match: re.Match,
|
||||||
dict_reader: DictReader,
|
dict_reader: DictReader,
|
||||||
) -> str:
|
) -> str:
|
||||||
key = match.group(1)
|
key = match.group(1)
|
||||||
@@ -52,13 +51,13 @@ class Template:
|
|||||||
|
|
||||||
def _exe_fill(
|
def _exe_fill(
|
||||||
self,
|
self,
|
||||||
match,
|
match: re.Match,
|
||||||
dict_reader: DictReader,
|
dict_reader: DictReader,
|
||||||
) -> str:
|
) -> str:
|
||||||
key_fill = re.sub(
|
key_fill = re.sub(
|
||||||
self.key_pattern,
|
self.key_pattern,
|
||||||
lambda m: f'"{self._key_fill(m, dict_reader)}"',
|
lambda m: f'"{self._key_fill(m, dict_reader)}"',
|
||||||
match.group(1)
|
match.group(1),
|
||||||
)
|
)
|
||||||
|
|
||||||
return str(eval(key_fill))
|
return str(eval(key_fill))
|
||||||
@@ -67,12 +66,12 @@ class Template:
|
|||||||
class FileTemplate(Template):
|
class FileTemplate(Template):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
path: Path,
|
path: Path,
|
||||||
key_pattern: str = r'f{{(\S+?)}}',
|
key_pattern: str = r"f{{(\S+?)}}",
|
||||||
exe_pattern : str = r'x{{((?:(?!x{{).)*)}}',
|
exe_pattern: str = r"x{{((?:(?!x{{).)*)}}",
|
||||||
):
|
) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
path.open('r').read(),
|
path.open("r").read(),
|
||||||
key_pattern=key_pattern,
|
key_pattern=key_pattern,
|
||||||
exe_pattern=exe_pattern,
|
exe_pattern=exe_pattern,
|
||||||
)
|
)
|
||||||
@@ -81,32 +80,30 @@ class FileTemplate(Template):
|
|||||||
class TOMLTemplate(FileTemplate):
|
class TOMLTemplate(FileTemplate):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
toml_path: Path,
|
toml_path: Path,
|
||||||
key_pattern: str = r'f{{(\S+?)}}',
|
key_pattern: str = r"f{{(\S+?)}}",
|
||||||
exe_pattern : str = r'x{{((?:(?!x{{).)*)}}',
|
exe_pattern: str = r"x{{((?:(?!x{{).)*)}}",
|
||||||
):
|
) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
toml_path,
|
toml_path,
|
||||||
key_pattern=key_pattern,
|
key_pattern=key_pattern,
|
||||||
exe_pattern=exe_pattern,
|
exe_pattern=exe_pattern,
|
||||||
)
|
)
|
||||||
|
|
||||||
def fill(
|
def fill_dict(
|
||||||
self,
|
self,
|
||||||
template_dict : dict,
|
template_dict: dict,
|
||||||
) -> str:
|
) -> dict[str, Any]:
|
||||||
filled_template = super().fill(template_dict)
|
filled_template = super().fill(template_dict)
|
||||||
toml_dict = tomllib.loads(filled_template)
|
toml_dict = tomllib.loads(filled_template)
|
||||||
|
|
||||||
return toml_dict
|
return toml_dict
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def stack_toml(
|
def stack_toml(path_list: list[Path]) -> dict:
|
||||||
path_list: list[Path]
|
|
||||||
) -> dict:
|
|
||||||
stacked_dict = {}
|
stacked_dict = {}
|
||||||
for toml_path in path_list:
|
for toml_path in path_list:
|
||||||
updated_map = tomllib.load(toml_path.open('rb'))
|
updated_map = tomllib.load(toml_path.open("rb"))
|
||||||
stacked_dict = util.deep_update(stacked_dict, updated_map)
|
stacked_dict = util.deep_update(stacked_dict, updated_map)
|
||||||
|
|
||||||
return stacked_dict
|
return stacked_dict
|
||||||
|
|||||||
@@ -1,34 +1,35 @@
|
|||||||
import re
|
import re
|
||||||
import argparse
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from argparse import Action, Namespace, ArgumentParser
|
||||||
|
|
||||||
from xdg import BaseDirectory
|
from xdg import BaseDirectory
|
||||||
from colorama import Fore, Back, Style
|
from colorama import Back, Fore, Style
|
||||||
from colorama.ansi import AnsiFore, AnsiBack, AnsiStyle
|
from colorama.ansi import AnsiCodes
|
||||||
|
|
||||||
|
|
||||||
def color_text(text, *colorama_args):
|
def color_text(text: str, *colorama_args: AnsiCodes) -> str:
|
||||||
'''
|
"""
|
||||||
Colorama text helper function
|
Colorama text helper function
|
||||||
|
|
||||||
Note: we attempt to preserve expected nested behavior by only resetting the groups
|
Note: we attempt to preserve expected nested behavior by only resetting the
|
||||||
(Fore, Back, Style) affected the styles passed in. This works when an outer call is
|
groups (Fore, Back, Style) affected the styles passed in. This works when
|
||||||
changing styles in one group, and an inner call is changing styles in another, but
|
an outer call is changing styles in one group, and an inner call is
|
||||||
*not* when affected groups overlap.
|
changing styles in another, but *not* when affected groups overlap.
|
||||||
|
|
||||||
For example, if an outer call is setting the foreground color (e.g., ``Fore.GREEN``),
|
For example, if an outer call is setting the foreground color (e.g.,
|
||||||
nested calls on the text being passed into the function can modify and reset the
|
``Fore.GREEN``), nested calls on the text being passed into the function
|
||||||
background or style with affecting the foreground. The primary use case here is
|
can modify and reset the background or style with affecting the foreground.
|
||||||
styling a group of text a single color, but applying ``BRIGHT`` or ``DIM`` styles only
|
The primary use case here is styling a group of text a single color, but
|
||||||
to some text elements within. If we didn't reset by group, the outer coloration
|
applying ``BRIGHT`` or ``DIM`` styles only to some text elements within. If
|
||||||
request will be "canceled out" as soon as the first inner call is made (since the
|
we didn't reset by group, the outer coloration request will be "canceled
|
||||||
unconditional behavior just employs ``Style.RESET_ALL``).
|
out" as soon as the first inner call is made (since the unconditional
|
||||||
'''
|
behavior just employs ``Style.RESET_ALL``).
|
||||||
|
"""
|
||||||
|
|
||||||
# reverse map colorama Ansi codes
|
# reverse map colorama Ansi codes
|
||||||
resets = []
|
resets = []
|
||||||
for carg in colorama_args:
|
for carg in colorama_args:
|
||||||
match = re.match(r'.*\[(\d+)m', carg)
|
match = re.match(r".*\[(\d+)m", carg)
|
||||||
if match:
|
if match:
|
||||||
intv = int(match.group(1))
|
intv = int(match.group(1))
|
||||||
if (intv >= 30 and intv <= 39) or (intv >= 90 and intv <= 97):
|
if (intv >= 30 and intv <= 39) or (intv >= 90 and intv <= 97):
|
||||||
@@ -40,44 +41,62 @@ def color_text(text, *colorama_args):
|
|||||||
|
|
||||||
return f"{''.join(colorama_args)}{text}{''.join(resets)}"
|
return f"{''.join(colorama_args)}{text}{''.join(resets)}"
|
||||||
|
|
||||||
def printc(text, *colorama_args):
|
|
||||||
|
def printc(text: str, *colorama_args: AnsiCodes) -> None:
|
||||||
print(color_text(text, *colorama_args))
|
print(color_text(text, *colorama_args))
|
||||||
|
|
||||||
|
|
||||||
def absolute_path(path: str | Path) -> Path:
|
def absolute_path(path: str | Path) -> Path:
|
||||||
return Path(path).expanduser().absolute()
|
return Path(path).expanduser().absolute()
|
||||||
|
|
||||||
def xdg_config_path():
|
|
||||||
return Path(BaseDirectory.save_config_path('symconf'))
|
def xdg_config_path() -> Path:
|
||||||
|
return Path(BaseDirectory.save_config_path("symconf"))
|
||||||
|
|
||||||
|
|
||||||
def to_tilde_path(path: Path) -> Path:
|
def to_tilde_path(path: Path) -> Path:
|
||||||
'''
|
"""
|
||||||
Abbreviate an absolute path by replacing HOME with "~", if applicable.
|
Abbreviate an absolute path by replacing HOME with "~", if applicable.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return Path(f"~/{path.relative_to(Path.home())}")
|
return Path(f"~/{path.relative_to(Path.home())}")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
def deep_update(mapping: dict, *updating_mappings: dict) -> dict:
|
def deep_update(mapping: dict, *updating_mappings: dict) -> dict:
|
||||||
'''Code adapted from pydantic'''
|
"""Code adapted from pydantic"""
|
||||||
|
|
||||||
updated_mapping = mapping.copy()
|
updated_mapping = mapping.copy()
|
||||||
for updating_mapping in updating_mappings:
|
for updating_mapping in updating_mappings:
|
||||||
for k, v in updating_mapping.items():
|
for k, v in updating_mapping.items():
|
||||||
if k in updated_mapping and isinstance(updated_mapping[k], dict) and isinstance(v, dict):
|
if (
|
||||||
|
k in updated_mapping
|
||||||
|
and isinstance(updated_mapping[k], dict)
|
||||||
|
and isinstance(v, dict)
|
||||||
|
):
|
||||||
updated_mapping[k] = deep_update(updated_mapping[k], v)
|
updated_mapping[k] = deep_update(updated_mapping[k], v)
|
||||||
else:
|
else:
|
||||||
updated_mapping[k] = v
|
updated_mapping[k] = v
|
||||||
return updated_mapping
|
return updated_mapping
|
||||||
|
|
||||||
|
|
||||||
class KVPair(argparse.Action):
|
class KVPair(Action):
|
||||||
def __call__(self, parser, namespace, values, option_string=None):
|
def __call__(
|
||||||
|
self,
|
||||||
|
parser: ArgumentParser,
|
||||||
|
namespace: Namespace,
|
||||||
|
values: list[str],
|
||||||
|
option_string: str | None = None,
|
||||||
|
) -> None:
|
||||||
kv_dict = getattr(namespace, self.dest, {})
|
kv_dict = getattr(namespace, self.dest, {})
|
||||||
|
|
||||||
if kv_dict is None:
|
if kv_dict is None:
|
||||||
kv_dict = {}
|
kv_dict = {}
|
||||||
|
|
||||||
for value in values:
|
for value in values:
|
||||||
key, val = value.split('=', 1)
|
key, val = value.split("=", 1)
|
||||||
kv_dict[key] = val
|
kv_dict[key] = val
|
||||||
|
|
||||||
setattr(namespace, self.dest, kv_dict)
|
setattr(namespace, self.dest, kv_dict)
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
def test_imports():
|
|
||||||
from symconf.runner import Runner
|
|
||||||
from symconf.reader import DictReader
|
|
||||||
from symconf.config import ConfigManager
|
|
||||||
from symconf.matching import Matcher, FilePart
|
|
||||||
from symconf.template import Template, FileTemplate, TOMLTemplate
|
|
||||||
|
|
||||||
from symconf import config
|
|
||||||
from symconf import reader
|
|
||||||
from symconf import util
|
|
||||||
@@ -2,64 +2,64 @@ from pathlib import Path
|
|||||||
|
|
||||||
from symconf import ConfigManager
|
from symconf import ConfigManager
|
||||||
|
|
||||||
|
config_dir = Path(__file__, "..", "test-config-dir/").resolve()
|
||||||
config_dir = Path(
|
|
||||||
__file__, '..', 'test-config-dir/'
|
|
||||||
).resolve()
|
|
||||||
cm = ConfigManager(config_dir)
|
cm = ConfigManager(config_dir)
|
||||||
|
|
||||||
|
|
||||||
def test_matching_configs_exact():
|
def test_matching_configs_exact() -> None:
|
||||||
'''
|
"""
|
||||||
Test matching exact style and scheme. Given strict mode not set (allowing relaxation
|
Test matching exact style and scheme. Given strict mode not set (allowing
|
||||||
to "none"), the order of matching should be
|
relaxation to "none"), the order of matching should be
|
||||||
|
|
||||||
1. (none, none) :: none-none.aaa
|
1. (none, none) :: none-none.aaa
|
||||||
2. (none, scheme) :: none-light.aaa
|
2. (none, scheme) :: none-light.aaa
|
||||||
3. (style, none) :: test-none.aaa
|
3. (style, none) :: test-none.aaa
|
||||||
4. (style, scheme) :: test-light.ccc
|
4. (style, scheme) :: test-light.ccc
|
||||||
|
|
||||||
Yielding "test-light.aaa", "test-light.ccc" (unique only on config pathname).
|
Yielding "test-light.aaa", "test-light.ccc" (unique only on config
|
||||||
'''
|
pathname).
|
||||||
|
"""
|
||||||
any_light = cm.get_matching_configs(
|
any_light = cm.get_matching_configs(
|
||||||
'test',
|
"test",
|
||||||
style='test',
|
style="test",
|
||||||
scheme='light',
|
scheme="light",
|
||||||
)
|
)
|
||||||
print(any_light)
|
print(any_light)
|
||||||
|
|
||||||
assert len(any_light) == 2
|
assert len(any_light) == 2
|
||||||
assert any_light['aaa'].pathname == 'test-none.aaa'
|
assert any_light["aaa"].pathname == "test-none.aaa"
|
||||||
assert any_light['ccc'].pathname == 'test-light.ccc'
|
assert any_light["ccc"].pathname == "test-light.ccc"
|
||||||
|
|
||||||
def test_matching_configs_any_style():
|
|
||||||
'''
|
def test_matching_configs_any_style() -> None:
|
||||||
Test matching "any" style and exact scheme. Given strict mode not set (allowing
|
"""
|
||||||
relaxation to "none"), the order of matching should be
|
Test matching "any" style and exact scheme. Given strict mode not set
|
||||||
|
(allowing relaxation to "none"), the order of matching should be
|
||||||
|
|
||||||
1. (style, none) :: none-none.aaa, test-none.aaa
|
1. (style, none) :: none-none.aaa, test-none.aaa
|
||||||
2. (none, none) :: none-none.aaa
|
2. (none, none) :: none-none.aaa
|
||||||
3. (style, scheme) :: test-dark.bbb
|
3. (style, scheme) :: test-dark.bbb
|
||||||
4. (none, scheme) :: (nothing)
|
4. (none, scheme) :: (nothing)
|
||||||
|
|
||||||
Yielding "none-none.aaa" (should always overwrite "test-none.aaa" due to "any"'s
|
Yielding "none-none.aaa" (should always overwrite "test-none.aaa" due to
|
||||||
preference for non-specific matches, i.e., "none"s), "test-none.ddd", "test-dark.bbb"
|
"any"'s preference for non-specific matches, i.e., "none"s),
|
||||||
(unique only on config pathname).
|
"test-none.ddd", "test-dark.bbb" (unique only on config pathname).
|
||||||
'''
|
"""
|
||||||
any_dark = cm.get_matching_configs(
|
any_dark = cm.get_matching_configs(
|
||||||
'test',
|
"test",
|
||||||
style='any',
|
style="any",
|
||||||
scheme='dark',
|
scheme="dark",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert len(any_dark) == 2
|
assert len(any_dark) == 2
|
||||||
assert any_dark['aaa'].pathname == 'none-none.aaa'
|
assert any_dark["aaa"].pathname == "none-none.aaa"
|
||||||
assert any_dark['bbb'].pathname == 'test-dark.bbb'
|
assert any_dark["bbb"].pathname == "test-dark.bbb"
|
||||||
|
|
||||||
def test_matching_configs_any_scheme():
|
|
||||||
'''
|
def test_matching_configs_any_scheme() -> None:
|
||||||
Test matching exact style and "any" scheme. Given strict mode not set (allowing
|
"""
|
||||||
relaxation to "none"), the order of matching should be
|
Test matching exact style and "any" scheme. Given strict mode not set
|
||||||
|
(allowing relaxation to "none"), the order of matching should be
|
||||||
|
|
||||||
1. (none, scheme) :: none-light.aaa & none-none.aaa
|
1. (none, scheme) :: none-light.aaa & none-none.aaa
|
||||||
2. (none, none) :: none-none.aaa
|
2. (none, none) :: none-none.aaa
|
||||||
@@ -67,54 +67,64 @@ def test_matching_configs_any_scheme():
|
|||||||
4. (style, none) :: test-none.aaa
|
4. (style, none) :: test-none.aaa
|
||||||
|
|
||||||
Yielding "test-none.aaa", "test-light.ccc", "test-dark.bbb"
|
Yielding "test-none.aaa", "test-light.ccc", "test-dark.bbb"
|
||||||
'''
|
"""
|
||||||
test_any = cm.get_matching_configs(
|
test_any = cm.get_matching_configs(
|
||||||
'test',
|
"test",
|
||||||
style='test',
|
style="test",
|
||||||
scheme='any',
|
scheme="any",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert len(test_any) == 3
|
assert len(test_any) == 3
|
||||||
assert test_any['aaa'].pathname == 'test-none.aaa'
|
assert test_any["aaa"].pathname == "test-none.aaa"
|
||||||
assert test_any['bbb'].pathname == 'test-dark.bbb'
|
assert test_any["bbb"].pathname == "test-dark.bbb"
|
||||||
assert test_any['ccc'].pathname == 'test-light.ccc'
|
assert test_any["ccc"].pathname == "test-light.ccc"
|
||||||
|
|
||||||
def test_matching_scripts():
|
|
||||||
'''
|
def test_matching_scripts() -> None:
|
||||||
Test matching exact style and scheme. Given strict mode not set (allowing relaxation
|
"""
|
||||||
to "none"), the order of matching should be
|
Test matching exact style and scheme. Given strict mode not set (allowing
|
||||||
|
relaxation to "none"), the order of matching should be
|
||||||
|
|
||||||
1. (none, none) :: none-none.sh
|
1. (none, none) :: none-none.sh
|
||||||
2. (none, scheme) :: none-light.sh
|
2. (none, scheme) :: none-light.sh
|
||||||
3. (style, none) :: test-none.sh
|
3. (style, none) :: test-none.sh
|
||||||
4. (style, scheme) :: (nothing)
|
4. (style, scheme) :: (nothing)
|
||||||
|
|
||||||
Yielding (ordered by dec specificity) "test-none.sh" as primary match, then relaxation
|
Yielding (ordered by dec specificity) "test-none.sh" as primary match, then
|
||||||
match "none-none.sh".
|
relaxation match "none-none.sh".
|
||||||
'''
|
"""
|
||||||
test_any = cm.get_matching_scripts(
|
test_any = cm.get_matching_scripts(
|
||||||
'test',
|
"test",
|
||||||
style='test',
|
style="test",
|
||||||
scheme='any',
|
scheme="any",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert len(test_any) == 2
|
assert len(test_any) == 2
|
||||||
assert list(map(lambda p:p.pathname, test_any)) == ['test-none.sh', 'none-none.sh']
|
assert [p.pathname for p in test_any] == [
|
||||||
|
"test-none.sh",
|
||||||
|
"none-none.sh",
|
||||||
|
]
|
||||||
|
|
||||||
any_light = cm.get_matching_scripts(
|
any_light = cm.get_matching_scripts(
|
||||||
'test',
|
"test",
|
||||||
style='any',
|
style="any",
|
||||||
scheme='light',
|
scheme="light",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert len(any_light) == 2
|
assert len(any_light) == 2
|
||||||
assert list(map(lambda p:p.pathname, any_light)) == ['none-light.sh', 'none-none.sh']
|
assert [p.pathname for p in any_light] == [
|
||||||
|
"none-light.sh",
|
||||||
|
"none-none.sh",
|
||||||
|
]
|
||||||
|
|
||||||
any_dark = cm.get_matching_scripts(
|
any_dark = cm.get_matching_scripts(
|
||||||
'test',
|
"test",
|
||||||
style='any',
|
style="any",
|
||||||
scheme='dark',
|
scheme="dark",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert len(any_dark) == 2
|
assert len(any_dark) == 2
|
||||||
assert list(map(lambda p:p.pathname, any_dark)) == ['test-none.sh', 'none-none.sh']
|
assert [p.pathname for p in any_dark] == [
|
||||||
|
"test-none.sh",
|
||||||
|
"none-none.sh",
|
||||||
|
]
|
||||||
|
|||||||
@@ -2,30 +2,47 @@ from pathlib import Path
|
|||||||
|
|
||||||
from symconf import Template, TOMLTemplate
|
from symconf import Template, TOMLTemplate
|
||||||
|
|
||||||
def test_template_fill():
|
|
||||||
|
def test_template_fill() -> None:
|
||||||
# test simple replacment
|
# test simple replacment
|
||||||
assert Template('f{{a}} - f{{b}}').fill({
|
assert (
|
||||||
'a': 1,
|
Template("f{{a}} - f{{b}}").fill(
|
||||||
'b': 2,
|
{
|
||||||
}) == '1 - 2'
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
== "1 - 2"
|
||||||
|
)
|
||||||
|
|
||||||
# test nested brackets (using default pattern)
|
# test nested brackets (using default pattern)
|
||||||
assert Template('{{ f{{a}} - f{{b}} }}').fill({
|
assert (
|
||||||
'a': 1,
|
Template("{{ f{{a}} - f{{b}} }}").fill(
|
||||||
'b': 2,
|
{
|
||||||
}) == '{{ 1 - 2 }}'
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
== "{{ 1 - 2 }}"
|
||||||
|
)
|
||||||
|
|
||||||
# test tight nested brackets (requires greedy quantifier)
|
# test tight nested brackets (requires greedy quantifier)
|
||||||
assert Template('{{f{{a}} - f{{b}}}}').fill({
|
assert (
|
||||||
'a': 1,
|
Template("{{f{{a}} - f{{b}}}}").fill(
|
||||||
'b': 2,
|
{
|
||||||
}) == '{{1 - 2}}'
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
== "{{1 - 2}}"
|
||||||
|
)
|
||||||
|
|
||||||
def test_toml_template_fill():
|
|
||||||
|
def test_toml_template_fill() -> None:
|
||||||
test_group_dir = Path(
|
test_group_dir = Path(
|
||||||
__file__, '..', 'test-config-dir/groups/test/'
|
__file__, "..", "test-config-dir/groups/test/"
|
||||||
).resolve()
|
).resolve()
|
||||||
|
|
||||||
stacked_dict = TOMLTemplate.stack_toml(test_group_dir.iterdir())
|
stacked_dict = TOMLTemplate.stack_toml(test_group_dir.iterdir())
|
||||||
|
|
||||||
assert stacked_dict == {'base':'aaa','concrete':'zzz'}
|
assert stacked_dict == {"base": "aaa", "concrete": "zzz"}
|
||||||
|
|||||||
603
uv.lock
generated
603
uv.lock
generated
@@ -23,6 +23,24 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" },
|
{ url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "appnope"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "asttokens"
|
||||||
|
version = "3.0.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "babel"
|
name = "babel"
|
||||||
version = "2.17.0"
|
version = "2.17.0"
|
||||||
@@ -45,20 +63,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/04/eb/f4151e0c7377a6e08a38108609ba5cede57986802757848688aeedd1b9e8/beautifulsoup4-4.13.5-py3-none-any.whl", hash = "sha256:642085eaa22233aceadff9c69651bc51e8bf3f874fb6d7104ece2beb24b47c4a", size = 105113, upload-time = "2025-08-24T14:06:14.884Z" },
|
{ url = "https://files.pythonhosted.org/packages/04/eb/f4151e0c7377a6e08a38108609ba5cede57986802757848688aeedd1b9e8/beautifulsoup4-4.13.5-py3-none-any.whl", hash = "sha256:642085eaa22233aceadff9c69651bc51e8bf3f874fb6d7104ece2beb24b47c4a", size = 105113, upload-time = "2025-08-24T14:06:14.884Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "build"
|
|
||||||
version = "1.3.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "colorama", marker = "os_name == 'nt'" },
|
|
||||||
{ name = "packaging" },
|
|
||||||
{ name = "pyproject-hooks" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/25/1c/23e33405a7c9eac261dff640926b8b5adaed6a6eb3e1767d441ed611d0c0/build-1.3.0.tar.gz", hash = "sha256:698edd0ea270bde950f53aed21f3a0135672206f3911e0176261a31e0e07b397", size = 48544, upload-time = "2025-08-01T21:27:09.268Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl", hash = "sha256:7145f0b5061ba90a1500d60bd1b13ca0a8a4cebdd0cc16ed8adf1c0e739f43b4", size = 23382, upload-time = "2025-08-01T21:27:07.844Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "certifi"
|
name = "certifi"
|
||||||
version = "2025.8.3"
|
version = "2025.8.3"
|
||||||
@@ -77,6 +81,8 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" },
|
{ url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" },
|
{ url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" },
|
{ url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" },
|
||||||
@@ -84,6 +90,11 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" },
|
{ url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" },
|
{ url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" },
|
{ url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" },
|
{ url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" },
|
{ url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" },
|
{ url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" },
|
||||||
@@ -91,18 +102,31 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" },
|
{ url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" },
|
{ url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" },
|
{ url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" },
|
{ url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" },
|
{ url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" },
|
{ url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" },
|
{ url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" },
|
{ url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" },
|
{ url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" },
|
{ url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" },
|
{ url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" },
|
{ url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" },
|
{ url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" },
|
{ url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" },
|
{ url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -157,47 +181,42 @@ wheels = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cryptography"
|
name = "comm"
|
||||||
version = "46.0.1"
|
version = "0.2.3"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" }
|
||||||
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/a9/62/e3664e6ffd7743e1694b244dde70b43a394f6f7fbcacf7014a8ff5197c73/cryptography-46.0.1.tar.gz", hash = "sha256:ed570874e88f213437f5cf758f9ef26cbfc3f336d889b1e592ee11283bb8d1c7", size = 749198, upload-time = "2025-09-17T00:10:35.797Z" }
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/22/59/9ae689a25047e0601adfcb159ec4f83c0b4149fdb5c3030cc94cd218141d/cryptography-46.0.1-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0ff483716be32690c14636e54a1f6e2e1b7bf8e22ca50b989f88fa1b2d287080", size = 4308182, upload-time = "2025-09-17T00:08:39.388Z" },
|
{ url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c4/ee/ca6cc9df7118f2fcd142c76b1da0f14340d77518c05b1ebfbbabca6b9e7d/cryptography-46.0.1-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9873bf7c1f2a6330bdfe8621e7ce64b725784f9f0c3a6a55c3047af5849f920e", size = 4572393, upload-time = "2025-09-17T00:08:41.663Z" },
|
]
|
||||||
{ url = "https://files.pythonhosted.org/packages/7f/a3/0f5296f63815d8e985922b05c31f77ce44787b3127a67c0b7f70f115c45f/cryptography-46.0.1-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0dfb7c88d4462a0cfdd0d87a3c245a7bc3feb59de101f6ff88194f740f72eda6", size = 4308400, upload-time = "2025-09-17T00:08:43.559Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/5d/8c/74fcda3e4e01be1d32775d5b4dd841acaac3c1b8fa4d0774c7ac8d52463d/cryptography-46.0.1-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e22801b61613ebdebf7deb18b507919e107547a1d39a3b57f5f855032dd7cfb8", size = 4015786, upload-time = "2025-09-17T00:08:45.758Z" },
|
[[package]]
|
||||||
{ url = "https://files.pythonhosted.org/packages/dc/b8/85d23287baeef273b0834481a3dd55bbed3a53587e3b8d9f0898235b8f91/cryptography-46.0.1-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:757af4f6341ce7a1e47c326ca2a81f41d236070217e5fbbad61bbfe299d55d28", size = 4982606, upload-time = "2025-09-17T00:08:47.602Z" },
|
name = "debugpy"
|
||||||
{ url = "https://files.pythonhosted.org/packages/e5/d3/de61ad5b52433b389afca0bc70f02a7a1f074651221f599ce368da0fe437/cryptography-46.0.1-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f7a24ea78de345cfa7f6a8d3bde8b242c7fac27f2bd78fa23474ca38dfaeeab9", size = 4604234, upload-time = "2025-09-17T00:08:49.879Z" },
|
version = "1.8.19"
|
||||||
{ url = "https://files.pythonhosted.org/packages/dc/1f/dbd4d6570d84748439237a7478d124ee0134bf166ad129267b7ed8ea6d22/cryptography-46.0.1-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e8776dac9e660c22241b6587fae51a67b4b0147daa4d176b172c3ff768ad736", size = 4307669, upload-time = "2025-09-17T00:08:52.321Z" },
|
source = { registry = "https://pypi.org/simple" }
|
||||||
{ url = "https://files.pythonhosted.org/packages/ec/fd/ca0a14ce7f0bfe92fa727aacaf2217eb25eb7e4ed513b14d8e03b26e63ed/cryptography-46.0.1-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9f40642a140c0c8649987027867242b801486865277cbabc8c6059ddef16dc8b", size = 4947579, upload-time = "2025-09-17T00:08:54.697Z" },
|
sdist = { url = "https://files.pythonhosted.org/packages/73/75/9e12d4d42349b817cd545b89247696c67917aab907012ae5b64bbfea3199/debugpy-1.8.19.tar.gz", hash = "sha256:eea7e5987445ab0b5ed258093722d5ecb8bb72217c5c9b1e21f64efe23ddebdb", size = 1644590, upload-time = "2025-12-15T21:53:28.044Z" }
|
||||||
{ url = "https://files.pythonhosted.org/packages/89/6b/09c30543bb93401f6f88fce556b3bdbb21e55ae14912c04b7bf355f5f96c/cryptography-46.0.1-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:449ef2b321bec7d97ef2c944173275ebdab78f3abdd005400cc409e27cd159ab", size = 4603669, upload-time = "2025-09-17T00:08:57.16Z" },
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/23/9a/38cb01cb09ce0adceda9fc627c9cf98eb890fc8d50cacbe79b011df20f8a/cryptography-46.0.1-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2dd339ba3345b908fa3141ddba4025568fa6fd398eabce3ef72a29ac2d73ad75", size = 4435828, upload-time = "2025-09-17T00:08:59.606Z" },
|
{ url = "https://files.pythonhosted.org/packages/4a/15/d762e5263d9e25b763b78be72dc084c7a32113a0bac119e2f7acae7700ed/debugpy-1.8.19-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:bccb1540a49cde77edc7ce7d9d075c1dbeb2414751bc0048c7a11e1b597a4c2e", size = 2549995, upload-time = "2025-12-15T21:53:43.773Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/0f/53/435b5c36a78d06ae0bef96d666209b0ecd8f8181bfe4dda46536705df59e/cryptography-46.0.1-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7411c910fb2a412053cf33cfad0153ee20d27e256c6c3f14d7d7d1d9fec59fd5", size = 4709553, upload-time = "2025-09-17T00:09:01.832Z" },
|
{ url = "https://files.pythonhosted.org/packages/a7/88/f7d25c68b18873b7c53d7c156ca7a7ffd8e77073aa0eac170a9b679cf786/debugpy-1.8.19-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:e9c68d9a382ec754dc05ed1d1b4ed5bd824b9f7c1a8cd1083adb84b3c93501de", size = 4309891, upload-time = "2025-12-15T21:53:45.26Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/26/34/0ff0bb2d2c79f25a2a63109f3b76b9108a906dd2a2eb5c1d460b9938adbb/cryptography-46.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9babb7818fdd71394e576cf26c5452df77a355eac1a27ddfa24096665a27f8fd", size = 4293515, upload-time = "2025-09-17T00:09:12.861Z" },
|
{ url = "https://files.pythonhosted.org/packages/c5/4f/a65e973aba3865794da65f71971dca01ae66666132c7b2647182d5be0c5f/debugpy-1.8.19-cp312-cp312-win32.whl", hash = "sha256:6599cab8a783d1496ae9984c52cb13b7c4a3bd06a8e6c33446832a5d97ce0bee", size = 5286355, upload-time = "2025-12-15T21:53:46.763Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/df/b7/d4f848aee24ecd1be01db6c42c4a270069a4f02a105d9c57e143daf6cf0f/cryptography-46.0.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9f2c4cc63be3ef43c0221861177cee5d14b505cd4d4599a89e2cd273c4d3542a", size = 4545619, upload-time = "2025-09-17T00:09:15.397Z" },
|
{ url = "https://files.pythonhosted.org/packages/d8/3a/d3d8b48fec96e3d824e404bf428276fb8419dfa766f78f10b08da1cb2986/debugpy-1.8.19-cp312-cp312-win_amd64.whl", hash = "sha256:66e3d2fd8f2035a8f111eb127fa508469dfa40928a89b460b41fd988684dc83d", size = 5328239, upload-time = "2025-12-15T21:53:48.868Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/44/a5/42fedefc754fd1901e2d95a69815ea4ec8a9eed31f4c4361fcab80288661/cryptography-46.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:41c281a74df173876da1dc9a9b6953d387f06e3d3ed9284e3baae3ab3f40883a", size = 4299160, upload-time = "2025-09-17T00:09:17.155Z" },
|
{ url = "https://files.pythonhosted.org/packages/71/3d/388035a31a59c26f1ecc8d86af607d0c42e20ef80074147cd07b180c4349/debugpy-1.8.19-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:91e35db2672a0abaf325f4868fcac9c1674a0d9ad9bb8a8c849c03a5ebba3e6d", size = 2538859, upload-time = "2025-12-15T21:53:50.478Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/86/a1/cd21174f56e769c831fbbd6399a1b7519b0ff6280acec1b826d7b072640c/cryptography-46.0.1-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0a17377fa52563d730248ba1f68185461fff36e8bc75d8787a7dd2e20a802b7a", size = 3994491, upload-time = "2025-09-17T00:09:18.971Z" },
|
{ url = "https://files.pythonhosted.org/packages/4a/19/c93a0772d0962294f083dbdb113af1a7427bb632d36e5314297068f55db7/debugpy-1.8.19-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:85016a73ab84dea1c1f1dcd88ec692993bcbe4532d1b49ecb5f3c688ae50c606", size = 4292575, upload-time = "2025-12-15T21:53:51.821Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8d/2f/a8cbfa1c029987ddc746fd966711d4fa71efc891d37fbe9f030fe5ab4eec/cryptography-46.0.1-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:0d1922d9280e08cde90b518a10cd66831f632960a8d08cb3418922d83fce6f12", size = 4960157, upload-time = "2025-09-17T00:09:20.923Z" },
|
{ url = "https://files.pythonhosted.org/packages/5c/56/09e48ab796b0a77e3d7dc250f95251832b8bf6838c9632f6100c98bdf426/debugpy-1.8.19-cp313-cp313-win32.whl", hash = "sha256:b605f17e89ba0ecee994391194285fada89cee111cfcd29d6f2ee11cbdc40976", size = 5286209, upload-time = "2025-12-15T21:53:53.602Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/67/ae/63a84e6789e0d5a2502edf06b552bcb0fa9ff16147265d5c44a211942abe/cryptography-46.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:af84e8e99f1a82cea149e253014ea9dc89f75b82c87bb6c7242203186f465129", size = 4577263, upload-time = "2025-09-17T00:09:23.356Z" },
|
{ url = "https://files.pythonhosted.org/packages/fb/4e/931480b9552c7d0feebe40c73725dd7703dcc578ba9efc14fe0e6d31cfd1/debugpy-1.8.19-cp313-cp313-win_amd64.whl", hash = "sha256:c30639998a9f9cd9699b4b621942c0179a6527f083c72351f95c6ab1728d5b73", size = 5328206, upload-time = "2025-12-15T21:53:55.433Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ef/8f/1b9fa8e92bd9cbcb3b7e1e593a5232f2c1e6f9bd72b919c1a6b37d315f92/cryptography-46.0.1-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:ef648d2c690703501714588b2ba640facd50fd16548133b11b2859e8655a69da", size = 4298703, upload-time = "2025-09-17T00:09:25.566Z" },
|
{ url = "https://files.pythonhosted.org/packages/f6/b9/cbec520c3a00508327476c7fce26fbafef98f412707e511eb9d19a2ef467/debugpy-1.8.19-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:1e8c4d1bd230067bf1bbcdbd6032e5a57068638eb28b9153d008ecde288152af", size = 2537372, upload-time = "2025-12-15T21:53:57.318Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c3/af/bb95db070e73fea3fae31d8a69ac1463d89d1c084220f549b00dd01094a8/cryptography-46.0.1-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:e94eb5fa32a8a9f9bf991f424f002913e3dd7c699ef552db9b14ba6a76a6313b", size = 4926363, upload-time = "2025-09-17T00:09:27.451Z" },
|
{ url = "https://files.pythonhosted.org/packages/88/5e/cf4e4dc712a141e10d58405c58c8268554aec3c35c09cdcda7535ff13f76/debugpy-1.8.19-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:d40c016c1f538dbf1762936e3aeb43a89b965069d9f60f9e39d35d9d25e6b809", size = 4268729, upload-time = "2025-12-15T21:53:58.712Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f5/3b/d8fb17ffeb3a83157a1cc0aa5c60691d062aceecba09c2e5e77ebfc1870c/cryptography-46.0.1-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:534b96c0831855e29fc3b069b085fd185aa5353033631a585d5cd4dd5d40d657", size = 4576958, upload-time = "2025-09-17T00:09:29.924Z" },
|
{ url = "https://files.pythonhosted.org/packages/82/a3/c91a087ab21f1047db328c1d3eb5d1ff0e52de9e74f9f6f6fa14cdd93d58/debugpy-1.8.19-cp314-cp314-win32.whl", hash = "sha256:0601708223fe1cd0e27c6cce67a899d92c7d68e73690211e6788a4b0e1903f5b", size = 5286388, upload-time = "2025-12-15T21:54:00.687Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d9/46/86bc3a05c10c8aa88c8ae7e953a8b4e407c57823ed201dbcba55c4d655f4/cryptography-46.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f9b55038b5c6c47559aa33626d8ecd092f354e23de3c6975e4bb205df128a2a0", size = 4422507, upload-time = "2025-09-17T00:09:32.222Z" },
|
{ url = "https://files.pythonhosted.org/packages/17/b8/bfdc30b6e94f1eff09f2dc9cc1f9cd1c6cde3d996bcbd36ce2d9a4956e99/debugpy-1.8.19-cp314-cp314-win_amd64.whl", hash = "sha256:8e19a725f5d486f20e53a1dde2ab8bb2c9607c40c00a42ab646def962b41125f", size = 5327741, upload-time = "2025-12-15T21:54:02.148Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/a8/4e/387e5a21dfd2b4198e74968a541cfd6128f66f8ec94ed971776e15091ac3/cryptography-46.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ec13b7105117dbc9afd023300fb9954d72ca855c274fe563e72428ece10191c0", size = 4683964, upload-time = "2025-09-17T00:09:34.118Z" },
|
{ url = "https://files.pythonhosted.org/packages/25/3e/e27078370414ef35fafad2c06d182110073daaeb5d3bf734b0b1eeefe452/debugpy-1.8.19-py2.py3-none-any.whl", hash = "sha256:360ffd231a780abbc414ba0f005dad409e71c78637efe8f2bd75837132a41d38", size = 5292321, upload-time = "2025-12-15T21:54:16.024Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/56/3e/13ce6eab9ad6eba1b15a7bd476f005a4c1b3f299f4c2f32b22408b0edccf/cryptography-46.0.1-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9ed64e5083fa806709e74fc5ea067dfef9090e5b7a2320a49be3c9df3583a2d8", size = 4301110, upload-time = "2025-09-17T00:09:45.614Z" },
|
]
|
||||||
{ url = "https://files.pythonhosted.org/packages/a2/67/65dc233c1ddd688073cf7b136b06ff4b84bf517ba5529607c9d79720fc67/cryptography-46.0.1-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:341fb7a26bc9d6093c1b124b9f13acc283d2d51da440b98b55ab3f79f2522ead", size = 4562369, upload-time = "2025-09-17T00:09:47.601Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/17/db/d64ae4c6f4e98c3dac5bf35dd4d103f4c7c345703e43560113e5e8e31b2b/cryptography-46.0.1-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6ef1488967e729948d424d09c94753d0167ce59afba8d0f6c07a22b629c557b2", size = 4302126, upload-time = "2025-09-17T00:09:49.335Z" },
|
[[package]]
|
||||||
{ url = "https://files.pythonhosted.org/packages/3d/19/5f1eea17d4805ebdc2e685b7b02800c4f63f3dd46cfa8d4c18373fea46c8/cryptography-46.0.1-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7823bc7cdf0b747ecfb096d004cc41573c2f5c7e3a29861603a2871b43d3ef32", size = 4009431, upload-time = "2025-09-17T00:09:51.239Z" },
|
name = "decorator"
|
||||||
{ url = "https://files.pythonhosted.org/packages/81/b5/229ba6088fe7abccbfe4c5edb96c7a5ad547fac5fdd0d40aa6ea540b2985/cryptography-46.0.1-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:f736ab8036796f5a119ff8211deda416f8c15ce03776db704a7a4e17381cb2ef", size = 4980739, upload-time = "2025-09-17T00:09:54.181Z" },
|
version = "5.2.1"
|
||||||
{ url = "https://files.pythonhosted.org/packages/3a/9c/50aa38907b201e74bc43c572f9603fa82b58e831bd13c245613a23cff736/cryptography-46.0.1-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:e46710a240a41d594953012213ea8ca398cd2448fbc5d0f1be8160b5511104a0", size = 4592289, upload-time = "2025-09-17T00:09:56.731Z" },
|
source = { registry = "https://pypi.org/simple" }
|
||||||
{ url = "https://files.pythonhosted.org/packages/5a/33/229858f8a5bb22f82468bb285e9f4c44a31978d5f5830bb4ea1cf8a4e454/cryptography-46.0.1-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:84ef1f145de5aee82ea2447224dc23f065ff4cc5791bb3b506615957a6ba8128", size = 4301815, upload-time = "2025-09-17T00:09:58.548Z" },
|
sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" }
|
||||||
{ url = "https://files.pythonhosted.org/packages/52/cb/b76b2c87fbd6ed4a231884bea3ce073406ba8e2dae9defad910d33cbf408/cryptography-46.0.1-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9394c7d5a7565ac5f7d9ba38b2617448eba384d7b107b262d63890079fad77ca", size = 4943251, upload-time = "2025-09-17T00:10:00.475Z" },
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/94/0f/f66125ecf88e4cb5b8017ff43f3a87ede2d064cb54a1c5893f9da9d65093/cryptography-46.0.1-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:ed957044e368ed295257ae3d212b95456bd9756df490e1ac4538857f67531fcc", size = 4591247, upload-time = "2025-09-17T00:10:02.874Z" },
|
{ url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f6/22/9f3134ae436b63b463cfdf0ff506a0570da6873adb4bf8c19b8a5b4bac64/cryptography-46.0.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f7de12fa0eee6234de9a9ce0ffcfa6ce97361db7a50b09b65c63ac58e5f22fc7", size = 4428534, upload-time = "2025-09-17T00:10:04.994Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/89/39/e6042bcb2638650b0005c752c38ea830cbfbcbb1830e4d64d530000aa8dc/cryptography-46.0.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7fab1187b6c6b2f11a326f33b036f7168f5b996aedd0c059f9738915e4e8f53a", size = 4699541, upload-time = "2025-09-17T00:10:06.925Z" },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -209,6 +228,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" },
|
{ url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "executing"
|
||||||
|
version = "2.2.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "furo"
|
name = "furo"
|
||||||
version = "2025.9.25"
|
version = "2025.9.25"
|
||||||
@@ -225,18 +253,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/ba/69/964b55f389c289e16ba2a5dfe587c3c462aac09e24123f09ddf703889584/furo-2025.9.25-py3-none-any.whl", hash = "sha256:2937f68e823b8e37b410c972c371bc2b1d88026709534927158e0cb3fac95afe", size = 340409, upload-time = "2025-09-25T21:37:17.244Z" },
|
{ url = "https://files.pythonhosted.org/packages/ba/69/964b55f389c289e16ba2a5dfe587c3c462aac09e24123f09ddf703889584/furo-2025.9.25-py3-none-any.whl", hash = "sha256:2937f68e823b8e37b410c972c371bc2b1d88026709534927158e0cb3fac95afe", size = 340409, upload-time = "2025-09-25T21:37:17.244Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "id"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "requests" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/22/11/102da08f88412d875fa2f1a9a469ff7ad4c874b0ca6fed0048fe385bdb3d/id-1.5.0.tar.gz", hash = "sha256:292cb8a49eacbbdbce97244f47a97b4c62540169c976552e497fd57df0734c1d", size = 15237, upload-time = "2024-12-04T19:53:05.575Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9f/cb/18326d2d89ad3b0dd143da971e77afd1e6ca6674f1b1c3df4b6bec6279fc/id-1.5.0-py3-none-any.whl", hash = "sha256:f1434e1cef91f2cbb8a4ec64663d5a23b9ed43ef44c4c957d02583d61714c658", size = 13611, upload-time = "2024-12-04T19:53:03.02Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.10"
|
version = "3.10"
|
||||||
@@ -265,45 +281,72 @@ wheels = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jaraco-classes"
|
name = "ipykernel"
|
||||||
version = "3.4.0"
|
version = "7.1.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "more-itertools" },
|
{ name = "appnope", marker = "sys_platform == 'darwin'" },
|
||||||
|
{ name = "comm" },
|
||||||
|
{ name = "debugpy" },
|
||||||
|
{ name = "ipython" },
|
||||||
|
{ name = "jupyter-client" },
|
||||||
|
{ name = "jupyter-core" },
|
||||||
|
{ name = "matplotlib-inline" },
|
||||||
|
{ name = "nest-asyncio" },
|
||||||
|
{ name = "packaging" },
|
||||||
|
{ name = "psutil" },
|
||||||
|
{ name = "pyzmq" },
|
||||||
|
{ name = "tornado" },
|
||||||
|
{ name = "traitlets" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/b9/a4/4948be6eb88628505b83a1f2f40d90254cab66abf2043b3c40fa07dfce0f/ipykernel-7.1.0.tar.gz", hash = "sha256:58a3fc88533d5930c3546dc7eac66c6d288acde4f801e2001e65edc5dc9cf0db", size = 174579, upload-time = "2025-10-27T09:46:39.471Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" },
|
{ url = "https://files.pythonhosted.org/packages/a3/17/20c2552266728ceba271967b87919664ecc0e33efca29c3efc6baf88c5f9/ipykernel-7.1.0-py3-none-any.whl", hash = "sha256:763b5ec6c5b7776f6a8d7ce09b267693b4e5ce75cb50ae696aaefb3c85e1ea4c", size = 117968, upload-time = "2025-10-27T09:46:37.805Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jaraco-context"
|
name = "ipython"
|
||||||
version = "6.0.1"
|
version = "9.8.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/df/ad/f3777b81bf0b6e7bc7514a1656d3e637b2e8e15fab2ce3235730b3e7a4e6/jaraco_context-6.0.1.tar.gz", hash = "sha256:9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3", size = 13912, upload-time = "2024-08-20T03:39:27.358Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ff/db/0c52c4cf5e4bd9f5d7135ec7669a3a767af21b3a308e1ed3674881e52b62/jaraco.context-6.0.1-py3-none-any.whl", hash = "sha256:f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4", size = 6825, upload-time = "2024-08-20T03:39:25.966Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jaraco-functools"
|
|
||||||
version = "4.3.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "more-itertools" },
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||||
|
{ name = "decorator" },
|
||||||
|
{ name = "ipython-pygments-lexers" },
|
||||||
|
{ name = "jedi" },
|
||||||
|
{ name = "matplotlib-inline" },
|
||||||
|
{ name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
|
||||||
|
{ name = "prompt-toolkit" },
|
||||||
|
{ name = "pygments" },
|
||||||
|
{ name = "stack-data" },
|
||||||
|
{ name = "traitlets" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/f7/ed/1aa2d585304ec07262e1a83a9889880701079dde796ac7b1d1826f40c63d/jaraco_functools-4.3.0.tar.gz", hash = "sha256:cfd13ad0dd2c47a3600b439ef72d8615d482cedcff1632930d6f28924d92f294", size = 19755, upload-time = "2025-08-18T20:05:09.91Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/12/51/a703c030f4928646d390b4971af4938a1b10c9dfce694f0d99a0bb073cb2/ipython-9.8.0.tar.gz", hash = "sha256:8e4ce129a627eb9dd221c41b1d2cdaed4ef7c9da8c17c63f6f578fe231141f83", size = 4424940, upload-time = "2025-12-03T10:18:24.353Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/b4/09/726f168acad366b11e420df31bf1c702a54d373a83f968d94141a8c3fde0/jaraco_functools-4.3.0-py3-none-any.whl", hash = "sha256:227ff8ed6f7b8f62c56deff101545fa7543cf2c8e7b82a7c2116e672f29c26e8", size = 10408, upload-time = "2025-08-18T20:05:08.69Z" },
|
{ url = "https://files.pythonhosted.org/packages/f1/df/8ee1c5dd1e3308b5d5b2f2dfea323bb2f3827da8d654abb6642051199049/ipython-9.8.0-py3-none-any.whl", hash = "sha256:ebe6d1d58d7d988fbf23ff8ff6d8e1622cfdb194daf4b7b73b792c4ec3b85385", size = 621374, upload-time = "2025-12-03T10:18:22.335Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jeepney"
|
name = "ipython-pygments-lexers"
|
||||||
version = "0.9.0"
|
version = "1.1.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" }
|
dependencies = [
|
||||||
|
{ name = "pygments" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" },
|
{ url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jedi"
|
||||||
|
version = "0.19.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "parso" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287, upload-time = "2024-11-11T01:41:42.873Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -319,20 +362,32 @@ wheels = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "keyring"
|
name = "jupyter-client"
|
||||||
version = "25.6.0"
|
version = "8.7.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "jaraco-classes" },
|
{ name = "jupyter-core" },
|
||||||
{ name = "jaraco-context" },
|
{ name = "python-dateutil" },
|
||||||
{ name = "jaraco-functools" },
|
{ name = "pyzmq" },
|
||||||
{ name = "jeepney", marker = "sys_platform == 'linux'" },
|
{ name = "tornado" },
|
||||||
{ name = "pywin32-ctypes", marker = "sys_platform == 'win32'" },
|
{ name = "traitlets" },
|
||||||
{ name = "secretstorage", marker = "sys_platform == 'linux'" },
|
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/70/09/d904a6e96f76ff214be59e7aa6ef7190008f52a0ab6689760a98de0bf37d/keyring-25.6.0.tar.gz", hash = "sha256:0b39998aa941431eb3d9b0d4b2460bc773b9df6fed7621c2dfb291a7e0187a66", size = 62750, upload-time = "2024-12-25T15:26:45.782Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/a6/27/d10de45e8ad4ce872372c4a3a37b7b35b6b064f6f023a5c14ffcced4d59d/jupyter_client-8.7.0.tar.gz", hash = "sha256:3357212d9cbe01209e59190f67a3a7e1f387a4f4e88d1e0433ad84d7b262531d", size = 344691, upload-time = "2025-12-09T18:37:01.953Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/d3/32/da7f44bcb1105d3e88a0b74ebdca50c59121d2ddf71c9e34ba47df7f3a56/keyring-25.6.0-py3-none-any.whl", hash = "sha256:552a3f7af126ece7ed5c89753650eec89c7eaae8617d0aa4d9ad2b75111266bd", size = 39085, upload-time = "2024-12-25T15:26:44.377Z" },
|
{ url = "https://files.pythonhosted.org/packages/bb/f5/fddaec430367be9d62a7ed125530e133bfd4a1c0350fe221149ee0f2b526/jupyter_client-8.7.0-py3-none-any.whl", hash = "sha256:3671a94fd25e62f5f2f554f5e95389c2294d89822378a5f2dd24353e1494a9e0", size = 106215, upload-time = "2025-12-09T18:37:00.024Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jupyter-core"
|
||||||
|
version = "5.9.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "platformdirs" },
|
||||||
|
{ name = "traitlets" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814, upload-time = "2025-10-16T19:19:18.444Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032, upload-time = "2025-10-16T19:19:16.783Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -385,6 +440,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" },
|
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matplotlib-inline"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "traitlets" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/c7/74/97e72a36efd4ae2bccb3463284300f8953f199b5ffbc04cbbb0ec78f74b1/matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe", size = 8110, upload-time = "2025-10-23T09:00:22.126Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mdit-py-plugins"
|
name = "mdit-py-plugins"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@@ -406,15 +473,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
|
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "more-itertools"
|
|
||||||
version = "10.8.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ea/5d/38b681d3fce7a266dd9ab73c66959406d565b3e85f21d5e66e1181d93721/more_itertools-10.8.0.tar.gz", hash = "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd", size = 137431, upload-time = "2025-09-02T15:23:11.018Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "myst-parser"
|
name = "myst-parser"
|
||||||
version = "4.0.1"
|
version = "4.0.1"
|
||||||
@@ -433,36 +491,12 @@ wheels = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nh3"
|
name = "nest-asyncio"
|
||||||
version = "0.3.0"
|
version = "1.6.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/c3/a4/96cff0977357f60f06ec4368c4c7a7a26cccfe7c9fcd54f5378bf0428fd3/nh3-0.3.0.tar.gz", hash = "sha256:d8ba24cb31525492ea71b6aac11a4adac91d828aadeff7c4586541bf5dc34d2f", size = 19655, upload-time = "2025-07-17T14:43:37.05Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/b4/11/340b7a551916a4b2b68c54799d710f86cf3838a4abaad8e74d35360343bb/nh3-0.3.0-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a537ece1bf513e5a88d8cff8a872e12fe8d0f42ef71dd15a5e7520fecd191bbb", size = 1427992, upload-time = "2025-07-17T14:43:06.848Z" },
|
{ url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ad/7f/7c6b8358cf1222921747844ab0eef81129e9970b952fcb814df417159fb9/nh3-0.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c915060a2c8131bef6a29f78debc29ba40859b6dbe2362ef9e5fd44f11487c2", size = 798194, upload-time = "2025-07-17T14:43:08.263Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/63/da/c5fd472b700ba37d2df630a9e0d8cc156033551ceb8b4c49cc8a5f606b68/nh3-0.3.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba0caa8aa184196daa6e574d997a33867d6d10234018012d35f86d46024a2a95", size = 837884, upload-time = "2025-07-17T14:43:09.233Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/4c/3c/cba7b26ccc0ef150c81646478aa32f9c9535234f54845603c838a1dc955c/nh3-0.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:80fe20171c6da69c7978ecba33b638e951b85fb92059259edd285ff108b82a6d", size = 996365, upload-time = "2025-07-17T14:43:10.243Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/f3/ba/59e204d90727c25b253856e456ea61265ca810cda8ee802c35f3fadaab00/nh3-0.3.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:e90883f9f85288f423c77b3f5a6f4486375636f25f793165112679a7b6363b35", size = 1071042, upload-time = "2025-07-17T14:43:11.57Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/10/71/2fb1834c10fab6d9291d62c95192ea2f4c7518bd32ad6c46aab5d095cb87/nh3-0.3.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:0649464ac8eee018644aacbc103874ccbfac80e3035643c3acaab4287e36e7f5", size = 995737, upload-time = "2025-07-17T14:43:12.659Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/33/c1/8f8ccc2492a000b6156dce68a43253fcff8b4ce70ab4216d08f90a2ac998/nh3-0.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1adeb1062a1c2974bc75b8d1ecb014c5fd4daf2df646bbe2831f7c23659793f9", size = 980552, upload-time = "2025-07-17T14:43:13.763Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/2f/d6/f1c6e091cbe8700401c736c2bc3980c46dca770a2cf6a3b48a175114058e/nh3-0.3.0-cp313-cp313t-win32.whl", hash = "sha256:7275fdffaab10cc5801bf026e3c089d8de40a997afc9e41b981f7ac48c5aa7d5", size = 593618, upload-time = "2025-07-17T14:43:15.098Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/23/1e/80a8c517655dd40bb13363fc4d9e66b2f13245763faab1a20f1df67165a7/nh3-0.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:423201bbdf3164a9e09aa01e540adbb94c9962cc177d5b1cbb385f5e1e79216e", size = 598948, upload-time = "2025-07-17T14:43:16.064Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9a/e0/af86d2a974c87a4ba7f19bc3b44a8eaa3da480de264138fec82fe17b340b/nh3-0.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:16f8670201f7e8e0e05ed1a590eb84bfa51b01a69dd5caf1d3ea57733de6a52f", size = 580479, upload-time = "2025-07-17T14:43:17.038Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0c/e0/cf1543e798ba86d838952e8be4cb8d18e22999be2a24b112a671f1c04fd6/nh3-0.3.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:ec6cfdd2e0399cb79ba4dcffb2332b94d9696c52272ff9d48a630c5dca5e325a", size = 1442218, upload-time = "2025-07-17T14:43:18.087Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/5c/86/a96b1453c107b815f9ab8fac5412407c33cc5c7580a4daf57aabeb41b774/nh3-0.3.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5e7185599f89b0e391e2f29cc12dc2e206167380cea49b33beda4891be2fe1", size = 823791, upload-time = "2025-07-17T14:43:19.721Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/97/33/11e7273b663839626f714cb68f6eb49899da5a0d9b6bc47b41fe870259c2/nh3-0.3.0-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:389d93d59b8214d51c400fb5b07866c2a4f79e4e14b071ad66c92184fec3a392", size = 811143, upload-time = "2025-07-17T14:43:20.779Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/6a/1b/b15bd1ce201a1a610aeb44afd478d55ac018b4475920a3118ffd806e2483/nh3-0.3.0-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:e9e6a7e4d38f7e8dda9edd1433af5170c597336c1a74b4693c5cb75ab2b30f2a", size = 1064661, upload-time = "2025-07-17T14:43:21.839Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8f/14/079670fb2e848c4ba2476c5a7a2d1319826053f4f0368f61fca9bb4227ae/nh3-0.3.0-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7852f038a054e0096dac12b8141191e02e93e0b4608c4b993ec7d4ffafea4e49", size = 997061, upload-time = "2025-07-17T14:43:23.179Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a3/e5/ac7fc565f5d8bce7f979d1afd68e8cb415020d62fa6507133281c7d49f91/nh3-0.3.0-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af5aa8127f62bbf03d68f67a956627b1bd0469703a35b3dad28d0c1195e6c7fb", size = 924761, upload-time = "2025-07-17T14:43:24.23Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/39/2c/6394301428b2017a9d5644af25f487fa557d06bc8a491769accec7524d9a/nh3-0.3.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f416c35efee3e6a6c9ab7716d9e57aa0a49981be915963a82697952cba1353e1", size = 803959, upload-time = "2025-07-17T14:43:26.377Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/4e/9a/344b9f9c4bd1c2413a397f38ee6a3d5db30f1a507d4976e046226f12b297/nh3-0.3.0-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:37d3003d98dedca6cd762bf88f2e70b67f05100f6b949ffe540e189cc06887f9", size = 844073, upload-time = "2025-07-17T14:43:27.375Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/66/3f/cd37f76c8ca277b02a84aa20d7bd60fbac85b4e2cbdae77cb759b22de58b/nh3-0.3.0-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:634e34e6162e0408e14fb61d5e69dbaea32f59e847cfcfa41b66100a6b796f62", size = 1000680, upload-time = "2025-07-17T14:43:28.452Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ee/db/7aa11b44bae4e7474feb1201d8dee04fabe5651c7cb51409ebda94a4ed67/nh3-0.3.0-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:b0612ccf5de8a480cf08f047b08f9d3fecc12e63d2ee91769cb19d7290614c23", size = 1076613, upload-time = "2025-07-17T14:43:30.031Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/97/03/03f79f7e5178eb1ad5083af84faff471e866801beb980cc72943a4397368/nh3-0.3.0-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:c7a32a7f0d89f7d30cb8f4a84bdbd56d1eb88b78a2434534f62c71dac538c450", size = 1001418, upload-time = "2025-07-17T14:43:31.429Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ce/55/1974bcc16884a397ee699cebd3914e1f59be64ab305533347ca2d983756f/nh3-0.3.0-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3f1b4f8a264a0c86ea01da0d0c390fe295ea0bcacc52c2103aca286f6884f518", size = 986499, upload-time = "2025-07-17T14:43:32.459Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c9/50/76936ec021fe1f3270c03278b8af5f2079038116b5d0bfe8538ffe699d69/nh3-0.3.0-cp38-abi3-win32.whl", hash = "sha256:6d68fa277b4a3cf04e5c4b84dd0c6149ff7d56c12b3e3fab304c525b850f613d", size = 599000, upload-time = "2025-07-17T14:43:33.852Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8c/ae/324b165d904dc1672eee5f5661c0a68d4bab5b59fbb07afb6d8d19a30b45/nh3-0.3.0-cp38-abi3-win_amd64.whl", hash = "sha256:bae63772408fd63ad836ec569a7c8f444dd32863d0c67f6e0b25ebbd606afa95", size = 604530, upload-time = "2025-07-17T14:43:34.95Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/5b/76/3165e84e5266d146d967a6cc784ff2fbf6ddd00985a55ec006b72bc39d5d/nh3-0.3.0-cp38-abi3-win_arm64.whl", hash = "sha256:d97d3efd61404af7e5721a0e74d81cdbfc6e5f97e11e731bb6d090e30a7b62b2", size = 585971, upload-time = "2025-07-17T14:43:35.936Z" },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -474,6 +508,36 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
|
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parso"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d4/de/53e0bcf53d13e005bd8c92e7855142494f41171b34c2536b86187474184d/parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a", size = 401205, upload-time = "2025-08-23T15:15:28.028Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887", size = 106668, upload-time = "2025-08-23T15:15:25.663Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pexpect"
|
||||||
|
version = "4.9.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "ptyprocess" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "platformdirs"
|
||||||
|
version = "4.5.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pluggy"
|
name = "pluggy"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
@@ -483,6 +547,62 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prompt-toolkit"
|
||||||
|
version = "3.0.52"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "wcwidth" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "psutil"
|
||||||
|
version = "7.1.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/e1/88/bdd0a41e5857d5d703287598cbf08dad90aed56774ea52ae071bae9071b6/psutil-7.1.3.tar.gz", hash = "sha256:6c86281738d77335af7aec228328e944b30930899ea760ecf33a4dba66be5e74", size = 489059, upload-time = "2025-11-02T12:25:54.619Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bd/93/0c49e776b8734fef56ec9c5c57f923922f2cf0497d62e0f419465f28f3d0/psutil-7.1.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0005da714eee687b4b8decd3d6cc7c6db36215c9e74e5ad2264b90c3df7d92dc", size = 239751, upload-time = "2025-11-02T12:25:58.161Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6f/8d/b31e39c769e70780f007969815195a55c81a63efebdd4dbe9e7a113adb2f/psutil-7.1.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:19644c85dcb987e35eeeaefdc3915d059dac7bd1167cdcdbf27e0ce2df0c08c0", size = 240368, upload-time = "2025-11-02T12:26:00.491Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/62/61/23fd4acc3c9eebbf6b6c78bcd89e5d020cfde4acf0a9233e9d4e3fa698b4/psutil-7.1.3-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95ef04cf2e5ba0ab9eaafc4a11eaae91b44f4ef5541acd2ee91d9108d00d59a7", size = 287134, upload-time = "2025-11-02T12:26:02.613Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/30/1c/f921a009ea9ceb51aa355cb0cc118f68d354db36eae18174bab63affb3e6/psutil-7.1.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1068c303be3a72f8e18e412c5b2a8f6d31750fb152f9cb106b54090296c9d251", size = 289904, upload-time = "2025-11-02T12:26:05.207Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a6/82/62d68066e13e46a5116df187d319d1724b3f437ddd0f958756fc052677f4/psutil-7.1.3-cp313-cp313t-win_amd64.whl", hash = "sha256:18349c5c24b06ac5612c0428ec2a0331c26443d259e2a0144a9b24b4395b58fa", size = 249642, upload-time = "2025-11-02T12:26:07.447Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/df/ad/c1cd5fe965c14a0392112f68362cfceb5230819dbb5b1888950d18a11d9f/psutil-7.1.3-cp313-cp313t-win_arm64.whl", hash = "sha256:c525ffa774fe4496282fb0b1187725793de3e7c6b29e41562733cae9ada151ee", size = 245518, upload-time = "2025-11-02T12:26:09.719Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2e/bb/6670bded3e3236eb4287c7bcdc167e9fae6e1e9286e437f7111caed2f909/psutil-7.1.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b403da1df4d6d43973dc004d19cee3b848e998ae3154cc8097d139b77156c353", size = 239843, upload-time = "2025-11-02T12:26:11.968Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b8/66/853d50e75a38c9a7370ddbeefabdd3d3116b9c31ef94dc92c6729bc36bec/psutil-7.1.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ad81425efc5e75da3f39b3e636293360ad8d0b49bed7df824c79764fb4ba9b8b", size = 240369, upload-time = "2025-11-02T12:26:14.358Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/41/bd/313aba97cb5bfb26916dc29cf0646cbe4dd6a89ca69e8c6edce654876d39/psutil-7.1.3-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f33a3702e167783a9213db10ad29650ebf383946e91bc77f28a5eb083496bc9", size = 288210, upload-time = "2025-11-02T12:26:16.699Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c2/fa/76e3c06e760927a0cfb5705eb38164254de34e9bd86db656d4dbaa228b04/psutil-7.1.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fac9cd332c67f4422504297889da5ab7e05fd11e3c4392140f7370f4208ded1f", size = 291182, upload-time = "2025-11-02T12:26:18.848Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0f/1d/5774a91607035ee5078b8fd747686ebec28a962f178712de100d00b78a32/psutil-7.1.3-cp314-cp314t-win_amd64.whl", hash = "sha256:3792983e23b69843aea49c8f5b8f115572c5ab64c153bada5270086a2123c7e7", size = 250466, upload-time = "2025-11-02T12:26:21.183Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/00/ca/e426584bacb43a5cb1ac91fae1937f478cd8fbe5e4ff96574e698a2c77cd/psutil-7.1.3-cp314-cp314t-win_arm64.whl", hash = "sha256:31d77fcedb7529f27bb3a0472bea9334349f9a04160e8e6e5020f22c59893264", size = 245756, upload-time = "2025-11-02T12:26:23.148Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ef/94/46b9154a800253e7ecff5aaacdf8ebf43db99de4a2dfa18575b02548654e/psutil-7.1.3-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2bdbcd0e58ca14996a42adf3621a6244f1bb2e2e528886959c72cf1e326677ab", size = 238359, upload-time = "2025-11-02T12:26:25.284Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/68/3a/9f93cff5c025029a36d9a92fef47220ab4692ee7f2be0fba9f92813d0cb8/psutil-7.1.3-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:bc31fa00f1fbc3c3802141eede66f3a2d51d89716a194bf2cd6fc68310a19880", size = 239171, upload-time = "2025-11-02T12:26:27.23Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ce/b1/5f49af514f76431ba4eea935b8ad3725cdeb397e9245ab919dbc1d1dc20f/psutil-7.1.3-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3bb428f9f05c1225a558f53e30ccbad9930b11c3fc206836242de1091d3e7dd3", size = 263261, upload-time = "2025-11-02T12:26:29.48Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e0/95/992c8816a74016eb095e73585d747e0a8ea21a061ed3689474fabb29a395/psutil-7.1.3-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56d974e02ca2c8eb4812c3f76c30e28836fffc311d55d979f1465c1feeb2b68b", size = 264635, upload-time = "2025-11-02T12:26:31.74Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/55/4c/c3ed1a622b6ae2fd3c945a366e64eb35247a31e4db16cf5095e269e8eb3c/psutil-7.1.3-cp37-abi3-win_amd64.whl", hash = "sha256:f39c2c19fe824b47484b96f9692932248a54c43799a84282cfe58d05a6449efd", size = 247633, upload-time = "2025-11-02T12:26:33.887Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c9/ad/33b2ccec09bf96c2b2ef3f9a6f66baac8253d7565d8839e024a6b905d45d/psutil-7.1.3-cp37-abi3-win_arm64.whl", hash = "sha256:bd0d69cee829226a761e92f28140bec9a5ee9d5b4fb4b0cc589068dbfff559b1", size = 244608, upload-time = "2025-11-02T12:26:36.136Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ptyprocess"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pure-eval"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pycparser"
|
name = "pycparser"
|
||||||
version = "2.23"
|
version = "2.23"
|
||||||
@@ -501,15 +621,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
|
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyproject-hooks"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228, upload-time = "2024-09-29T09:24:13.293Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216, upload-time = "2024-09-29T09:24:11.978Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "8.4.2"
|
version = "8.4.2"
|
||||||
@@ -527,12 +638,15 @@ wheels = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pywin32-ctypes"
|
name = "python-dateutil"
|
||||||
version = "0.2.3"
|
version = "2.9.0.post0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" }
|
dependencies = [
|
||||||
|
{ name = "six" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" },
|
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -591,17 +705,46 @@ wheels = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "readme-renderer"
|
name = "pyzmq"
|
||||||
version = "44.0"
|
version = "27.1.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "docutils" },
|
{ name = "cffi", marker = "implementation_name == 'pypy'" },
|
||||||
{ name = "nh3" },
|
|
||||||
{ name = "pygments" },
|
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz", hash = "sha256:8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1", size = 32056, upload-time = "2024-07-08T15:00:57.805Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl", hash = "sha256:2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151", size = 13310, upload-time = "2024-07-08T15:00:56.577Z" },
|
{ url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -619,40 +762,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
|
{ url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "requests-toolbelt"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "requests" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888, upload-time = "2023-05-01T04:11:33.229Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rfc3986"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/85/40/1520d68bfa07ab5a6f065a186815fb6610c86fe957bc065754e47f7b0840/rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c", size = 49026, upload-time = "2022-01-10T00:52:30.832Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl", hash = "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", size = 31326, upload-time = "2022-01-10T00:52:29.594Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rich"
|
|
||||||
version = "14.1.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "markdown-it-py" },
|
|
||||||
{ name = "pygments" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/fe/75/af448d8e52bf1d8fa6a9d089ca6c07ff4453d86c65c145d0a300bb073b9b/rich-14.1.0.tar.gz", hash = "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8", size = 224441, upload-time = "2025-07-25T07:32:58.125Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e3/30/3c4d035596d3cf444529e0b2953ad0466f6049528a879d27534700580395/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", size = 243368, upload-time = "2025-07-25T07:32:56.73Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roman-numerals-py"
|
name = "roman-numerals-py"
|
||||||
version = "3.1.0"
|
version = "3.1.0"
|
||||||
@@ -662,19 +771,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742, upload-time = "2025-02-22T07:34:52.422Z" },
|
{ url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742, upload-time = "2025-02-22T07:34:52.422Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "secretstorage"
|
|
||||||
version = "3.4.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "cryptography" },
|
|
||||||
{ name = "jeepney" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/31/9f/11ef35cf1027c1339552ea7bfe6aaa74a8516d8b5caf6e7d338daf54fd80/secretstorage-3.4.0.tar.gz", hash = "sha256:c46e216d6815aff8a8a18706a2fbfd8d53fcbb0dce99301881687a1b0289ef7c", size = 19748, upload-time = "2025-09-09T16:42:13.859Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/91/ff/2e2eed29e02c14a5cb6c57f09b2d5b40e65d6cc71f45b52e0be295ccbc2f/secretstorage-3.4.0-py3-none-any.whl", hash = "sha256:0e3b6265c2c63509fb7415717607e4b2c9ab767b7f344a57473b779ca13bd02e", size = 15272, upload-time = "2025-09-09T16:42:12.744Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "setuptools"
|
name = "setuptools"
|
||||||
version = "80.9.0"
|
version = "80.9.0"
|
||||||
@@ -684,6 +780,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" },
|
{ url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "six"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "snowballstemmer"
|
name = "snowballstemmer"
|
||||||
version = "3.0.1"
|
version = "3.0.1"
|
||||||
@@ -823,8 +928,23 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" },
|
{ url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stack-data"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "asttokens" },
|
||||||
|
{ name = "executing" },
|
||||||
|
{ name = "pure-eval" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symconf"
|
name = "symconf"
|
||||||
|
version = "0.8.4"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "colorama" },
|
{ name = "colorama" },
|
||||||
@@ -832,54 +952,64 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[package.optional-dependencies]
|
[package.optional-dependencies]
|
||||||
build = [
|
dev = [
|
||||||
{ name = "build" },
|
{ name = "pytest" },
|
||||||
{ name = "twine" },
|
|
||||||
]
|
]
|
||||||
docs = [
|
doc = [
|
||||||
{ name = "furo" },
|
{ name = "furo" },
|
||||||
{ name = "myst-parser" },
|
{ name = "myst-parser" },
|
||||||
{ name = "sphinx" },
|
{ name = "sphinx" },
|
||||||
{ name = "sphinx-autodoc-typehints" },
|
{ name = "sphinx-autodoc-typehints" },
|
||||||
{ name = "sphinx-togglebutton" },
|
{ name = "sphinx-togglebutton" },
|
||||||
]
|
]
|
||||||
tests = [
|
|
||||||
{ name = "pytest" },
|
[package.dev-dependencies]
|
||||||
|
dev = [
|
||||||
|
{ name = "ipykernel" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
{ name = "build", marker = "extra == 'build'" },
|
|
||||||
{ name = "colorama" },
|
{ name = "colorama" },
|
||||||
{ name = "furo", marker = "extra == 'docs'" },
|
{ name = "furo", marker = "extra == 'doc'" },
|
||||||
{ name = "myst-parser", marker = "extra == 'docs'" },
|
{ name = "myst-parser", marker = "extra == 'doc'" },
|
||||||
{ name = "pytest", marker = "extra == 'tests'" },
|
{ name = "pytest", marker = "extra == 'dev'" },
|
||||||
{ name = "pyxdg" },
|
{ name = "pyxdg" },
|
||||||
{ name = "sphinx", marker = "extra == 'docs'" },
|
{ name = "sphinx", marker = "extra == 'doc'" },
|
||||||
{ name = "sphinx-autodoc-typehints", marker = "extra == 'docs'" },
|
{ name = "sphinx-autodoc-typehints", marker = "extra == 'doc'" },
|
||||||
{ name = "sphinx-togglebutton", marker = "extra == 'docs'" },
|
{ name = "sphinx-togglebutton", marker = "extra == 'doc'" },
|
||||||
{ name = "twine", marker = "extra == 'build'" },
|
|
||||||
]
|
]
|
||||||
provides-extras = ["tests", "docs", "build"]
|
provides-extras = ["dev", "doc"]
|
||||||
|
|
||||||
|
[package.metadata.requires-dev]
|
||||||
|
dev = [{ name = "ipykernel" }]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "twine"
|
name = "tornado"
|
||||||
version = "6.2.0"
|
version = "6.5.4"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
sdist = { url = "https://files.pythonhosted.org/packages/37/1d/0a336abf618272d53f62ebe274f712e213f5a03c0b2339575430b8362ef2/tornado-6.5.4.tar.gz", hash = "sha256:a22fa9047405d03260b483980635f0b041989d8bcc9a313f8fe18b411d84b1d7", size = 513632, upload-time = "2025-12-15T19:21:03.836Z" }
|
||||||
{ name = "id" },
|
|
||||||
{ name = "keyring", marker = "platform_machine != 'ppc64le' and platform_machine != 's390x'" },
|
|
||||||
{ name = "packaging" },
|
|
||||||
{ name = "readme-renderer" },
|
|
||||||
{ name = "requests" },
|
|
||||||
{ name = "requests-toolbelt" },
|
|
||||||
{ name = "rfc3986" },
|
|
||||||
{ name = "rich" },
|
|
||||||
{ name = "urllib3" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/e0/a8/949edebe3a82774c1ec34f637f5dd82d1cf22c25e963b7d63771083bbee5/twine-6.2.0.tar.gz", hash = "sha256:e5ed0d2fd70c9959770dce51c8f39c8945c574e18173a7b81802dab51b4b75cf", size = 172262, upload-time = "2025-09-04T15:43:17.255Z" }
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/3a/7a/882d99539b19b1490cac5d77c67338d126e4122c8276bf640e411650c830/twine-6.2.0-py3-none-any.whl", hash = "sha256:418ebf08ccda9a8caaebe414433b0ba5e25eb5e4a927667122fbe8f829f985d8", size = 42727, upload-time = "2025-09-04T15:43:15.994Z" },
|
{ url = "https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9", size = 443909, upload-time = "2025-12-15T19:20:48.382Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/db/7e/f7b8d8c4453f305a51f80dbb49014257bb7d28ccb4bbb8dd328ea995ecad/tornado-6.5.4-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2d50f63dda1d2cac3ae1fa23d254e16b5e38153758470e9956cbc3d813d40843", size = 442163, upload-time = "2025-12-15T19:20:49.791Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ba/b5/206f82d51e1bfa940ba366a8d2f83904b15942c45a78dd978b599870ab44/tornado-6.5.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17", size = 445746, upload-time = "2025-12-15T19:20:51.491Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8e/9d/1a3338e0bd30ada6ad4356c13a0a6c35fbc859063fa7eddb309183364ac1/tornado-6.5.4-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50ff0a58b0dc97939d29da29cd624da010e7f804746621c78d14b80238669335", size = 445083, upload-time = "2025-12-15T19:20:52.778Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f", size = 445315, upload-time = "2025-12-15T19:20:53.996Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/27/07/2273972f69ca63dbc139694a3fc4684edec3ea3f9efabf77ed32483b875c/tornado-6.5.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9c86b1643b33a4cd415f8d0fe53045f913bf07b4a3ef646b735a6a86047dda84", size = 446003, upload-time = "2025-12-15T19:20:56.101Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d1/83/41c52e47502bf7260044413b6770d1a48dda2f0246f95ee1384a3cd9c44a/tornado-6.5.4-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:6eb82872335a53dd063a4f10917b3efd28270b56a33db69009606a0312660a6f", size = 445412, upload-time = "2025-12-15T19:20:57.398Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/10/c7/bc96917f06cbee182d44735d4ecde9c432e25b84f4c2086143013e7b9e52/tornado-6.5.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6076d5dda368c9328ff41ab5d9dd3608e695e8225d1cd0fd1e006f05da3635a8", size = 445392, upload-time = "2025-12-15T19:20:58.692Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0c/1a/d7592328d037d36f2d2462f4bc1fbb383eec9278bc786c1b111cbbd44cfa/tornado-6.5.4-cp39-abi3-win32.whl", hash = "sha256:1768110f2411d5cd281bac0a090f707223ce77fd110424361092859e089b38d1", size = 446481, upload-time = "2025-12-15T19:21:00.008Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d6/6d/c69be695a0a64fd37a97db12355a035a6d90f79067a3cf936ec2b1dc38cd/tornado-6.5.4-cp39-abi3-win_amd64.whl", hash = "sha256:fa07d31e0cd85c60713f2b995da613588aa03e1303d75705dca6af8babc18ddc", size = 446886, upload-time = "2025-12-15T19:21:01.287Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/50/49/8dc3fd90902f70084bd2cd059d576ddb4f8bb44c2c7c0e33a11422acb17e/tornado-6.5.4-cp39-abi3-win_arm64.whl", hash = "sha256:053e6e16701eb6cbe641f308f4c1a9541f91b6261991160391bfc342e8a551a1", size = 445910, upload-time = "2025-12-15T19:21:02.571Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "traitlets"
|
||||||
|
version = "5.14.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621, upload-time = "2024-04-19T11:11:49.746Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -900,6 +1030,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" },
|
{ url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wcwidth"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wheel"
|
name = "wheel"
|
||||||
version = "0.45.1"
|
version = "0.45.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user