mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-18 02:24:18 +00:00
Merge changes from topic "hm/handoff" into integration
* changes: build: make poetry use existing lock file feat(arm): add fw handoff support for RESET_TO_BL31 feat(tlc): add host tool for static TL generation
This commit is contained in:
commit
47add9d3ed
22 changed files with 3176 additions and 271 deletions
|
@ -1444,6 +1444,9 @@ subsections:
|
|||
- title: R/ZG Layout Tool
|
||||
scope: rzg-layout
|
||||
|
||||
- title: Transfer List Compiler
|
||||
scope: tlc
|
||||
|
||||
- title: Dependencies
|
||||
scope: deps
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@ Tools
|
|||
:caption: Contents
|
||||
|
||||
memory-layout-tool
|
||||
transfer-list-compiler
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2023, Arm Limited. All rights reserved.*
|
||||
*Copyright (c) 2023-2024, Arm Limited. All rights reserved.*
|
||||
|
|
194
docs/tools/transfer-list-compiler.rst
Normal file
194
docs/tools/transfer-list-compiler.rst
Normal file
|
@ -0,0 +1,194 @@
|
|||
Transfer List Compiler
|
||||
======================
|
||||
|
||||
The Transfer List Compiler (tlc) is a host tool used by TF-A to generate transfer
|
||||
lists compliant with the v0.9 of the `Firmware Handoff specification`_. It enables
|
||||
developers to statically generate transfer list blobs containing any number of
|
||||
transfer entries.
|
||||
|
||||
Getting Started
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
``tlc`` is installed by default with TF-A's poetry environment. All of it's
|
||||
dependencies are listed in `tools/tlc/pyproject.toml`_.
|
||||
|
||||
To install ``tlc`` seperately, run the following command:
|
||||
|
||||
.. code::
|
||||
|
||||
make -C tools/tlc install
|
||||
|
||||
Creating a Transfer List
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To create an empty TL, you can use the ``create`` command.
|
||||
|
||||
.. code::
|
||||
|
||||
tlc create tl.bin
|
||||
|
||||
This commands generates a binary blob representing an empty TL, shown in the
|
||||
hexdump below.
|
||||
|
||||
.. code::
|
||||
|
||||
$ hexdump tl.bin | head
|
||||
0000000 b10b 4a0f 01a6 0318 0018 0000 1000 0000
|
||||
0000010 0001 0000 0000 0000
|
||||
|
||||
A common use-case this tool supports is the addition of TE's via the option
|
||||
``--entry``. This takes as input the tag ID and path to a binary blob to be
|
||||
included in the transfer list. The snippet below shows how to include an FDT in
|
||||
the TL.
|
||||
|
||||
.. code::
|
||||
|
||||
tlc create --entry 1 fdt.dtb tl.bin
|
||||
|
||||
Alternatively, addition of a device tree is supported through the option
|
||||
``--fdt``. This has the same effect as passing the device tree and it's tag ID
|
||||
through the ``--entry`` option.
|
||||
|
||||
.. code::
|
||||
|
||||
tlc create --fdt fdt.dtb tl.bin
|
||||
|
||||
.. note::
|
||||
|
||||
``tlc`` makes no effort to verify the contents of a binary blob against the
|
||||
provided tag ID. It only checks that the tags provided as input are within
|
||||
range and that there is sufficient memory to include their TE's.
|
||||
|
||||
Printing the contents of a TL
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Support is provided for dumping the contents of a TL via the ``info`` command.
|
||||
This prints the header of the TL and all included TE's.
|
||||
|
||||
.. code::
|
||||
|
||||
$ tlc info tl.bin
|
||||
signature 0x4a0fb10b
|
||||
checksum 0xe1
|
||||
version 0x1
|
||||
hdr_size 0x18
|
||||
alignment 0x3
|
||||
size 0x2a6f
|
||||
total_size 0x4e20
|
||||
flags 0x1
|
||||
----
|
||||
id 0x1
|
||||
data_size 0x2a47
|
||||
hdr_size 0x8
|
||||
offset 0x18
|
||||
----
|
||||
id 0x0
|
||||
data_size 0x0
|
||||
hdr_size 0x8
|
||||
offset 0x2a68
|
||||
|
||||
The example above shows the dump produced by ``tlc`` for a 20Kb TL containing a
|
||||
device tree (tag_id=1) and a NULL entry (tag_id=0).
|
||||
|
||||
Modifying the contents of an existing TL
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
`tlc` supports removal of one or more entries from a TL through the ``remove``
|
||||
command. It takes as argument the filename, and one or more tag ID's, passed
|
||||
through the ``--tags`` option. It produces a valid TL blob without those
|
||||
entries.
|
||||
|
||||
|
||||
For example, using the same blob as in the section above, we can remove the FDT
|
||||
TE with the command.
|
||||
|
||||
.. code::
|
||||
|
||||
$ tlc remove --tags 1 tl.bin
|
||||
|
||||
Using the ``info`` command, shows the the TE has been remove:
|
||||
|
||||
.. code::
|
||||
|
||||
$ tlc info tl.bin
|
||||
|
||||
signature 0x4a0fb10b
|
||||
checksum 0x38
|
||||
version 0x1
|
||||
hdr_size 0x18
|
||||
alignment 0x3
|
||||
size 0x20
|
||||
total_size 0x4e20
|
||||
flags 0x1
|
||||
----
|
||||
id 0x0
|
||||
data_size 0x0
|
||||
hdr_size 0x8
|
||||
offset 0x18
|
||||
|
||||
Note that more than one entry can be removed at a time. The ``--tags`` option
|
||||
accepts multiple tag ID's.
|
||||
|
||||
Conversely, TE's can be added to an existing TL. This is achieved through the
|
||||
`add` command.
|
||||
|
||||
.. code::
|
||||
|
||||
$ tlc add --entry 1 fdt.dtb tl.bin
|
||||
|
||||
|
||||
The result of this modification is shown below:
|
||||
|
||||
.. code::
|
||||
|
||||
$ tlc info tl.bin
|
||||
|
||||
signature 0x4a0fb10b
|
||||
checksum 0xe1
|
||||
version 0x1
|
||||
hdr_size 0x18
|
||||
alignment 0x3
|
||||
size 0x2a6f
|
||||
total_size 0x4e20
|
||||
flags 0x1
|
||||
----
|
||||
id 0x0
|
||||
data_size 0x0
|
||||
hdr_size 0x8
|
||||
offset 0x18
|
||||
----
|
||||
id 0x1
|
||||
data_size 0x2a47
|
||||
hdr_size 0x8
|
||||
offset 0x20
|
||||
|
||||
Unpacking a Transfer List
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Given a transfer list, ``tlc`` also provides a mechanism for extracting TE data.
|
||||
Running the command ``unpack``, yields binary files containing data from all the TE's.
|
||||
|
||||
.. code::
|
||||
|
||||
$ tlc create --size 20000 --fdt build/fvp/debug/fdts/fvp-base-gicv3-psci.dtb tl.bin
|
||||
$ tlc unpack tl.bin
|
||||
$ file te_1.bin
|
||||
te_1.bin: Device Tree Blob version 17, size=10823, boot CPU=0, string block size=851, DT structure block size=9900
|
||||
|
||||
Validate a Transfer List
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``tlc validate`` provides a quick and simple mechanism for checking wether the TL
|
||||
is compliant with version of the specification supported by the tool. It
|
||||
performs the following checks:
|
||||
|
||||
#. Validates the signature.
|
||||
#. Ensures that the specified version is greater than or equal to the tool’s current version.
|
||||
#. Verifies alignment criteria for all TE’s.
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2024, Arm Limited. All rights reserved.*
|
||||
|
||||
.. _Firmware Handoff specification: https://github.com/FirmwareHandoff/firmware_handoff/
|
||||
.. _tools/tlc/pyproject.toml: https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/heads/master/tools/tlc/pyproject.toml
|
|
@ -210,7 +210,7 @@ const mmap_region_t plat_arm_mmap[] = {
|
|||
#ifdef MAP_FW_NS_HANDOFF
|
||||
MAP_FW_NS_HANDOFF,
|
||||
#endif
|
||||
#ifdef MAP_EL3_FW_HANDOFF
|
||||
#if defined(MAP_EL3_FW_HANDOFF) && !RESET_TO_BL31
|
||||
MAP_EL3_FW_HANDOFF,
|
||||
#endif
|
||||
{ 0 }
|
||||
|
|
|
@ -323,10 +323,6 @@ else
|
|||
BL31_SOURCES += drivers/delay_timer/generic_delay_timer.c
|
||||
endif
|
||||
|
||||
ifeq (${TRANSFER_LIST}, 1)
|
||||
include lib/transfer_list/transfer_list.mk
|
||||
endif
|
||||
|
||||
# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
|
||||
ifdef UNIX_MK
|
||||
FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
|
||||
|
@ -386,6 +382,17 @@ $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config,${FVP_TB_FW_CO
|
|||
$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG}))
|
||||
endif
|
||||
|
||||
ifeq (${TRANSFER_LIST}, 1)
|
||||
include lib/transfer_list/transfer_list.mk
|
||||
|
||||
ifeq ($(RESET_TO_BL31), 1)
|
||||
HW_CONFIG := ${FVP_HW_CONFIG}
|
||||
FW_HANDOFF_SIZE := 20000
|
||||
|
||||
$(eval $(call add_define,ARM_PRELOADED_DTB_OFFSET))
|
||||
endif
|
||||
endif
|
||||
|
||||
# Enable dynamic mitigation support by default
|
||||
DYNAMIC_WORKAROUND_CVE_2018_3639 := 1
|
||||
|
||||
|
|
|
@ -128,6 +128,24 @@ struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type)
|
|||
void __init arm_bl31_early_platform_setup(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
#if RESET_TO_BL31
|
||||
/* Populate entry point information for BL33 */
|
||||
SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
|
||||
/*
|
||||
* Tell BL31 where the non-trusted software image
|
||||
* is located and the entry state information
|
||||
*/
|
||||
bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
|
||||
|
||||
bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
|
||||
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
|
||||
|
||||
bl33_image_ep_info.args.arg0 =
|
||||
FW_NS_HANDOFF_BASE + ARM_PRELOADED_DTB_OFFSET;
|
||||
bl33_image_ep_info.args.arg1 = TRANSFER_LIST_SIGNATURE |
|
||||
REGISTER_CONVENTION_VERSION_MASK;
|
||||
bl33_image_ep_info.args.arg3 = FW_NS_HANDOFF_BASE;
|
||||
#else
|
||||
struct transfer_list_entry *te = NULL;
|
||||
struct entry_point_info *ep;
|
||||
|
||||
|
@ -160,6 +178,7 @@ void __init arm_bl31_early_platform_setup(u_register_t arg0, u_register_t arg1,
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif /* RESET_TO_BL31 */
|
||||
}
|
||||
#else
|
||||
void __init arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_config,
|
||||
|
@ -501,7 +520,7 @@ void __init bl31_plat_arch_setup(void)
|
|||
|
||||
arm_bl31_plat_arch_setup();
|
||||
|
||||
#if TRANSFER_LIST && !RESET_TO_BL2
|
||||
#if TRANSFER_LIST && !(RESET_TO_BL2 || RESET_TO_BL31)
|
||||
te = transfer_list_find(secure_tl, TL_TAG_FDT);
|
||||
assert(te != NULL);
|
||||
|
||||
|
|
|
@ -458,3 +458,17 @@ ifeq (${RECLAIM_INIT_CODE}, 1)
|
|||
$(error To reclaim init code xlat tables v2 must be used)
|
||||
endif
|
||||
endif
|
||||
|
||||
TRANSFER_LIST_BIN := ${BUILD_PLAT}/tl.bin
|
||||
|
||||
.PHONY: tl
|
||||
tl: ${HW_CONFIG}
|
||||
@echo " TLC ${TRANSFER_LIST_BIN}"
|
||||
$(Q)${PYTHON} -m tools.tlc.tlc create --fdt ${HW_CONFIG} -s ${FW_HANDOFF_SIZE} ${TRANSFER_LIST_BIN}
|
||||
$(Q)$(eval ARM_PRELOADED_DTB_OFFSET := `tlc info --fdt-offset ${TRANSFER_LIST_BIN}`)
|
||||
|
||||
ifeq (${TRANSFER_LIST}, 1)
|
||||
ifeq (${RESET_TO_BL31}, 1)
|
||||
bl31: tl
|
||||
endif
|
||||
endif
|
||||
|
|
648
poetry.lock
generated
648
poetry.lock
generated
|
@ -1,4 +1,4 @@
|
|||
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "alabaster"
|
||||
|
@ -13,57 +13,58 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "anytree"
|
||||
version = "2.8.0"
|
||||
description = "Powerful and Lightweight Python Tree Data Structure.."
|
||||
version = "2.12.1"
|
||||
description = "Powerful and Lightweight Python Tree Data Structure with various plugins"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
python-versions = ">=3.7.2,<4"
|
||||
files = [
|
||||
{file = "anytree-2.8.0-py2.py3-none-any.whl", hash = "sha256:14c55ac77492b11532395049a03b773d14c7e30b22aa012e337b1e983de31521"},
|
||||
{file = "anytree-2.8.0.tar.gz", hash = "sha256:3f0f93f355a91bc3e6245319bf4c1d50e3416cc7a35cc1133c1ff38306bbccab"},
|
||||
{file = "anytree-2.12.1-py3-none-any.whl", hash = "sha256:5ea9e61caf96db1e5b3d0a914378d2cd83c269dfce1fb8242ce96589fa3382f0"},
|
||||
{file = "anytree-2.12.1.tar.gz", hash = "sha256:244def434ccf31b668ed282954e5d315b4e066c4940b94aff4a7962d85947830"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
six = ">=1.9.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["check-manifest"]
|
||||
test = ["coverage"]
|
||||
six = "*"
|
||||
|
||||
[[package]]
|
||||
name = "babel"
|
||||
version = "2.12.1"
|
||||
version = "2.15.0"
|
||||
description = "Internationalization utilities"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"},
|
||||
{file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"},
|
||||
{file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"},
|
||||
{file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""}
|
||||
|
||||
[package.extras]
|
||||
dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
|
||||
|
||||
[[package]]
|
||||
name = "build"
|
||||
version = "0.10.0"
|
||||
version = "1.2.1"
|
||||
description = "A simple, correct Python build frontend"
|
||||
optional = false
|
||||
python-versions = ">= 3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "build-0.10.0-py3-none-any.whl", hash = "sha256:af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171"},
|
||||
{file = "build-0.10.0.tar.gz", hash = "sha256:d5b71264afdb5951d6704482aac78de887c80691c52b88a9ad195983ca2c9269"},
|
||||
{file = "build-1.2.1-py3-none-any.whl", hash = "sha256:75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4"},
|
||||
{file = "build-1.2.1.tar.gz", hash = "sha256:526263f4870c26f26c433545579475377b2b7588b6f1eac76a001e873ae3e19d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "os_name == \"nt\""}
|
||||
packaging = ">=19.0"
|
||||
importlib-metadata = {version = ">=4.6", markers = "python_full_version < \"3.10.2\""}
|
||||
packaging = ">=19.1"
|
||||
pyproject_hooks = "*"
|
||||
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2021.08.31)", "sphinx (>=4.0,<5.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)"]
|
||||
test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "toml (>=0.10.0)", "wheel (>=0.36.0)"]
|
||||
typing = ["importlib-metadata (>=5.1)", "mypy (==0.991)", "tomli", "typing-extensions (>=3.7.4.3)"]
|
||||
docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"]
|
||||
test = ["build[uv,virtualenv]", "filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"]
|
||||
typing = ["build[uv]", "importlib-metadata (>=5.1)", "mypy (>=1.9.0,<1.10.0)", "tomli", "typing-extensions (>=3.7.4.3)"]
|
||||
uv = ["uv (>=0.1.18)"]
|
||||
virtualenv = ["virtualenv (>=20.0.35)"]
|
||||
|
||||
[[package]]
|
||||
|
@ -79,97 +80,112 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.1.0"
|
||||
version = "3.3.2"
|
||||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
|
||||
{file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
|
||||
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
|
||||
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.1.3"
|
||||
version = "8.1.7"
|
||||
description = "Composable command line interface toolkit"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
|
||||
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
||||
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
|
||||
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -186,6 +202,20 @@ files = [
|
|||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "commonmark"
|
||||
version = "0.9.1"
|
||||
description = "Python parser for the CommonMark Markdown spec"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
|
||||
{file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "docutils"
|
||||
version = "0.18.1"
|
||||
|
@ -221,22 +251,22 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
version = "6.6.0"
|
||||
version = "8.1.0"
|
||||
description = "Read metadata from Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
|
||||
{file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
|
||||
{file = "importlib_metadata-8.1.0-py3-none-any.whl", hash = "sha256:3cd29f739ed65973840b068e3132135ce954c254d48b5b640484467ef7ab3c8c"},
|
||||
{file = "importlib_metadata-8.1.0.tar.gz", hash = "sha256:fcdcb1d5ead7bdf3dd32657bb94ebe9d2aabfe89a19782ddc32da5041d6ebfb4"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
zipp = ">=0.5"
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
||||
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
||||
perf = ["ipython"]
|
||||
testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
|
||||
test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "jinja2"
|
||||
|
@ -281,61 +311,71 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
|
|||
|
||||
[[package]]
|
||||
name = "markupsafe"
|
||||
version = "2.1.2"
|
||||
version = "2.1.5"
|
||||
description = "Safely add untrusted strings to HTML/XML markup."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"},
|
||||
{file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
|
||||
{file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"},
|
||||
{file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"},
|
||||
{file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"},
|
||||
{file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"},
|
||||
{file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"},
|
||||
{file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"},
|
||||
{file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"},
|
||||
{file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"},
|
||||
{file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"},
|
||||
{file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"},
|
||||
{file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"},
|
||||
{file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"},
|
||||
{file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"},
|
||||
{file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"},
|
||||
{file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"},
|
||||
{file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"},
|
||||
{file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"},
|
||||
{file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"},
|
||||
{file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"},
|
||||
{file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"},
|
||||
{file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"},
|
||||
{file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"},
|
||||
{file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"},
|
||||
{file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"},
|
||||
{file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"},
|
||||
{file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"},
|
||||
{file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"},
|
||||
{file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"},
|
||||
{file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"},
|
||||
{file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"},
|
||||
{file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"},
|
||||
{file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"},
|
||||
{file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"},
|
||||
{file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"},
|
||||
{file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"},
|
||||
{file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"},
|
||||
{file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"},
|
||||
{file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"},
|
||||
{file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"},
|
||||
{file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"},
|
||||
{file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"},
|
||||
{file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"},
|
||||
{file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"},
|
||||
{file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"},
|
||||
{file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"},
|
||||
{file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"},
|
||||
{file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"},
|
||||
{file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"},
|
||||
{file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"},
|
||||
{file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"},
|
||||
{file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"},
|
||||
{file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"},
|
||||
{file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"},
|
||||
{file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"},
|
||||
{file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"},
|
||||
{file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"},
|
||||
{file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"},
|
||||
{file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"},
|
||||
{file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"},
|
||||
{file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -396,35 +436,35 @@ testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov",
|
|||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "23.1"
|
||||
version = "24.1"
|
||||
description = "Core utilities for Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
|
||||
{file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
|
||||
{file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
|
||||
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pip"
|
||||
version = "23.3"
|
||||
version = "24.1.2"
|
||||
description = "The PyPA recommended tool for installing Python packages."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pip-23.3-py3-none-any.whl", hash = "sha256:bc38bb52bc286514f8f7cb3a1ba5ed100b76aaef29b521d48574329331c5ae7b"},
|
||||
{file = "pip-23.3.tar.gz", hash = "sha256:bb7d4f69f488432e4e96394612f43ab43dd478d073ef7422604a570f7157561e"},
|
||||
{file = "pip-24.1.2-py3-none-any.whl", hash = "sha256:7cd207eed4c60b0f411b444cd1464198fe186671c323b6cd6d433ed80fc9d247"},
|
||||
{file = "pip-24.1.2.tar.gz", hash = "sha256:e5458a0b89f2755e0ee8c0c77613fe5273e05f337907874d64f13171a898a7ff"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pip-tools"
|
||||
version = "6.13.0"
|
||||
version = "6.14.0"
|
||||
description = "pip-tools keeps your pinned dependencies fresh."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pip-tools-6.13.0.tar.gz", hash = "sha256:61d46bd2eb8016ed4a924e196e6e5b0a268cd3babd79e593048720db23522bb1"},
|
||||
{file = "pip_tools-6.13.0-py3-none-any.whl", hash = "sha256:50943f151d87e752abddec8158622c34ad7f292e193836e90e30d87da60b19d9"},
|
||||
{file = "pip-tools-6.14.0.tar.gz", hash = "sha256:06366be0e08d86b416407333e998b4d305d5bd925151b08942ed149380ba3e47"},
|
||||
{file = "pip_tools-6.14.0-py3-none-any.whl", hash = "sha256:c5ad042cd27c0b343b10db1db7f77a7d087beafbec59ae6df1bba4d3368dfe8c"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -432,28 +472,29 @@ build = "*"
|
|||
click = ">=8"
|
||||
pip = ">=22.2"
|
||||
setuptools = "*"
|
||||
tomli = {version = "*", markers = "python_version < \"3.11\""}
|
||||
wheel = "*"
|
||||
|
||||
[package.extras]
|
||||
coverage = ["pytest-cov"]
|
||||
testing = ["flit-core (>=2,<4)", "poetry-core (>=1.0.0)", "pytest (>=7.2.0)", "pytest-rerunfailures", "pytest-xdist"]
|
||||
coverage = ["covdefaults", "pytest-cov"]
|
||||
testing = ["flit-core (>=2,<4)", "poetry-core (>=1.0.0)", "pytest (>=7.2.0)", "pytest-rerunfailures", "pytest-xdist", "tomli-w"]
|
||||
|
||||
[[package]]
|
||||
name = "prettytable"
|
||||
version = "3.7.0"
|
||||
version = "3.10.2"
|
||||
description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "prettytable-3.7.0-py3-none-any.whl", hash = "sha256:f4aaf2ed6e6062a82fd2e6e5289bbbe705ec2788fe401a3a1f62a1cea55526d2"},
|
||||
{file = "prettytable-3.7.0.tar.gz", hash = "sha256:ef8334ee40b7ec721651fc4d37ecc7bb2ef55fde5098d994438f0dfdaa385c0c"},
|
||||
{file = "prettytable-3.10.2-py3-none-any.whl", hash = "sha256:1cbfdeb4bcc73976a778a0fb33cb6d752e75396f16574dcb3e2d6332fd93c76a"},
|
||||
{file = "prettytable-3.10.2.tar.gz", hash = "sha256:29ec6c34260191d42cd4928c28d56adec360ac2b1208a26c7e4f14b90cc8bc84"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
wcwidth = "*"
|
||||
|
||||
[package.extras]
|
||||
tests = ["pytest", "pytest-cov", "pytest-lazy-fixture"]
|
||||
tests = ["pytest", "pytest-cov", "pytest-lazy-fixtures"]
|
||||
|
||||
[[package]]
|
||||
name = "pyelftools"
|
||||
|
@ -468,101 +509,109 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.15.1"
|
||||
version = "2.18.0"
|
||||
description = "Pygments is a syntax highlighting package written in Python."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
|
||||
{file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
|
||||
{file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
|
||||
{file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
plugins = ["importlib-metadata"]
|
||||
windows-terminal = ["colorama (>=0.4.6)"]
|
||||
|
||||
[[package]]
|
||||
name = "pyproject-hooks"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
description = "Wrappers to call pyproject.toml-based build backend hooks."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pyproject_hooks-1.0.0-py3-none-any.whl", hash = "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8"},
|
||||
{file = "pyproject_hooks-1.0.0.tar.gz", hash = "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5"},
|
||||
{file = "pyproject_hooks-1.1.0-py3-none-any.whl", hash = "sha256:7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2"},
|
||||
{file = "pyproject_hooks-1.1.0.tar.gz", hash = "sha256:4b37730834edbd6bd37f26ece6b44802fb1c1ee2ece0e54ddff8bfc06db86965"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2023.3"
|
||||
version = "2024.1"
|
||||
description = "World timezone definitions, modern and historical"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"},
|
||||
{file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"},
|
||||
{file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"},
|
||||
{file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0"
|
||||
version = "6.0.1"
|
||||
description = "YAML parser and emitter for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
|
||||
{file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
|
||||
{file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
|
||||
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
|
||||
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
|
||||
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
|
||||
{file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
|
||||
{file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
|
||||
{file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
|
||||
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.2"
|
||||
version = "2.32.3"
|
||||
description = "Python HTTP for Humans."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"},
|
||||
{file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"},
|
||||
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
|
||||
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -575,20 +624,51 @@ urllib3 = ">=1.21.1,<3"
|
|||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||
|
||||
[[package]]
|
||||
name = "rich"
|
||||
version = "10.16.2"
|
||||
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
||||
optional = false
|
||||
python-versions = ">=3.6.2,<4.0.0"
|
||||
files = [
|
||||
{file = "rich-10.16.2-py3-none-any.whl", hash = "sha256:c59d73bd804c90f747c8d7b1d023b88f2a9ac2454224a4aeaf959b21eeb42d03"},
|
||||
{file = "rich-10.16.2.tar.gz", hash = "sha256:720974689960e06c2efdb54327f8bf0cdbdf4eae4ad73b6c94213cad405c371b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = ">=0.4.0,<0.5.0"
|
||||
commonmark = ">=0.9.0,<0.10.0"
|
||||
pygments = ">=2.6.0,<3.0.0"
|
||||
|
||||
[package.extras]
|
||||
jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "70.0.0"
|
||||
version = "71.1.0"
|
||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "setuptools-70.0.0-py3-none-any.whl", hash = "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4"},
|
||||
{file = "setuptools-70.0.0.tar.gz", hash = "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0"},
|
||||
{file = "setuptools-71.1.0-py3-none-any.whl", hash = "sha256:33874fdc59b3188304b2e7c80d9029097ea31627180896fb549c578ceb8a0855"},
|
||||
{file = "setuptools-71.1.0.tar.gz", hash = "sha256:032d42ee9fb536e33087fb66cac5f840eb9391ed05637b3f2a76a7c8fb477936"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
||||
testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
||||
core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
|
||||
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
||||
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
||||
|
||||
[[package]]
|
||||
name = "shellingham"
|
||||
version = "1.5.4"
|
||||
description = "Tool to Detect Surrounding Shell"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"},
|
||||
{file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
|
@ -649,19 +729,19 @@ test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"]
|
|||
|
||||
[[package]]
|
||||
name = "sphinx-rtd-theme"
|
||||
version = "1.2.0"
|
||||
version = "1.3.0"
|
||||
description = "Read the Docs theme for Sphinx"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
|
||||
files = [
|
||||
{file = "sphinx_rtd_theme-1.2.0-py2.py3-none-any.whl", hash = "sha256:f823f7e71890abe0ac6aaa6013361ea2696fc8d3e1fa798f463e82bdb77eeff2"},
|
||||
{file = "sphinx_rtd_theme-1.2.0.tar.gz", hash = "sha256:a0d8bd1a2ed52e0b338cbe19c4b2eef3c5e7a048769753dac6a9f059c7b641b8"},
|
||||
{file = "sphinx_rtd_theme-1.3.0-py2.py3-none-any.whl", hash = "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0"},
|
||||
{file = "sphinx_rtd_theme-1.3.0.tar.gz", hash = "sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
docutils = "<0.19"
|
||||
sphinx = ">=1.6,<7"
|
||||
sphinxcontrib-jquery = {version = ">=2.0.0,<3.0.0 || >3.0.0", markers = "python_version > \"3\""}
|
||||
sphinx = ">=1.6,<8"
|
||||
sphinxcontrib-jquery = ">=4,<5"
|
||||
|
||||
[package.extras]
|
||||
dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"]
|
||||
|
@ -802,6 +882,24 @@ Sphinx = ">=1.6.3"
|
|||
[package.extras]
|
||||
cairosvg = ["cairosvg (>=1.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "tlc"
|
||||
version = "0.9.0"
|
||||
description = "Transfer List Compiler (TLC) is a Python-based CLI for efficiently handling transfer lists."
|
||||
optional = false
|
||||
python-versions = "^3.8"
|
||||
files = []
|
||||
develop = false
|
||||
|
||||
[package.dependencies]
|
||||
click = "^8.1.7"
|
||||
rich = "^10.14.0"
|
||||
typer = {version = "^0.4.0", extras = ["all"]}
|
||||
|
||||
[package.source]
|
||||
type = "directory"
|
||||
url = "tools/tlc"
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.0.1"
|
||||
|
@ -814,14 +912,36 @@ files = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.5.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||
name = "typer"
|
||||
version = "0.4.2"
|
||||
description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"},
|
||||
{file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
|
||||
{file = "typer-0.4.2-py3-none-any.whl", hash = "sha256:023bae00d1baf358a6cc7cea45851639360bb716de687b42b0a4641cd99173f1"},
|
||||
{file = "typer-0.4.2.tar.gz", hash = "sha256:b8261c6c0152dd73478b5ba96ba677e5d6948c715c310f7c91079f311f62ec03"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
click = ">=7.1.1,<9.0.0"
|
||||
colorama = {version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"all\""}
|
||||
shellingham = {version = ">=1.3.0,<2.0.0", optional = true, markers = "extra == \"all\""}
|
||||
|
||||
[package.extras]
|
||||
all = ["colorama (>=0.4.3,<0.5.0)", "shellingham (>=1.3.0,<2.0.0)"]
|
||||
dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"]
|
||||
doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)"]
|
||||
test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<2.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.12.2"
|
||||
description = "Backported and Experimental Type Hints for Python 3.8+"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
|
||||
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -843,45 +963,45 @@ zstd = ["zstandard (>=0.18.0)"]
|
|||
|
||||
[[package]]
|
||||
name = "wcwidth"
|
||||
version = "0.2.6"
|
||||
version = "0.2.13"
|
||||
description = "Measures the displayed width of unicode strings in a terminal"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"},
|
||||
{file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"},
|
||||
{file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
|
||||
{file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wheel"
|
||||
version = "0.40.0"
|
||||
version = "0.43.0"
|
||||
description = "A built-package format for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "wheel-0.40.0-py3-none-any.whl", hash = "sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247"},
|
||||
{file = "wheel-0.40.0.tar.gz", hash = "sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873"},
|
||||
{file = "wheel-0.43.0-py3-none-any.whl", hash = "sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81"},
|
||||
{file = "wheel-0.43.0.tar.gz", hash = "sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
test = ["pytest (>=6.0.0)"]
|
||||
test = ["pytest (>=6.0.0)", "setuptools (>=65)"]
|
||||
|
||||
[[package]]
|
||||
name = "zipp"
|
||||
version = "3.19.1"
|
||||
version = "3.19.2"
|
||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "zipp-3.19.1-py3-none-any.whl", hash = "sha256:2828e64edb5386ea6a52e7ba7cdb17bb30a73a858f5eb6eb93d8d36f5ea26091"},
|
||||
{file = "zipp-3.19.1.tar.gz", hash = "sha256:35427f6d5594f4acf82d25541438348c26736fa9b3afa2754bcd63cdb99d8e8f"},
|
||||
{file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"},
|
||||
{file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
||||
test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"]
|
||||
test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.8"
|
||||
content-hash = "62d9ce9ca1c9f4669c7b40724acfc93968cde31c0460d1d7515d289739dc9464"
|
||||
content-hash = "3dd9c0d7ea3f1ef33abf600002406dbe51dba2e4ed21175b1f1e7ac64cd0e387"
|
||||
|
|
|
@ -14,6 +14,7 @@ memory = "memory.memmap:main"
|
|||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.8"
|
||||
tlc = {path = "tools/tlc"}
|
||||
|
||||
[tool.poetry.group.doc.dependencies]
|
||||
sphinx = "^5.3.0"
|
||||
|
|
109
tools/tlc/Makefile
Normal file
109
tools/tlc/Makefile
Normal file
|
@ -0,0 +1,109 @@
|
|||
#
|
||||
# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
##* Variables
|
||||
SHELL := /usr/bin/env bash
|
||||
PYTHON := python
|
||||
PYTHONPATH := `pwd`
|
||||
|
||||
#* Docker variables
|
||||
IMAGE := tlc
|
||||
VERSION := latest
|
||||
|
||||
#* Installation
|
||||
.PHONY: dist
|
||||
dist: clean
|
||||
poetry build
|
||||
|
||||
.PHONY: dev-install
|
||||
dev-install:
|
||||
poetry lock -n --no-update && poetry export --without-hashes > requirements.txt
|
||||
poetry install -n
|
||||
-poetry run mypy --install-types --non-interactive ./
|
||||
|
||||
.PHONY: install
|
||||
install: dist
|
||||
pip install dist/*.whl
|
||||
|
||||
.PHONY: pre-commit-install
|
||||
pre-commit-install:
|
||||
poetry run pre-commit install
|
||||
|
||||
#* Formatters
|
||||
.PHONY: codestyle
|
||||
codestyle:
|
||||
poetry run pyupgrade --exit-zero-even-if-changed --py38-plus **/*.py
|
||||
poetry run isort --settings-path pyproject.toml ./
|
||||
poetry run black --config pyproject.toml ./
|
||||
|
||||
.PHONY: formatting
|
||||
formatting: codestyle
|
||||
|
||||
#* Linting
|
||||
.PHONY: test
|
||||
test:
|
||||
PYTHONPATH=$(PYTHONPATH) poetry run pytest -c pyproject.toml --cov-report=html --cov=tlc tests/
|
||||
poetry run coverage-badge -o assets/images/coverage.svg -f
|
||||
|
||||
.PHONY: check-codestyle
|
||||
check-codestyle:
|
||||
poetry run isort --diff --check-only --settings-path pyproject.toml ./
|
||||
poetry run black --diff --check --config pyproject.toml ./
|
||||
poetry run darglint --verbosity 2 tlc tests
|
||||
|
||||
.PHONY: mypy
|
||||
mypy:
|
||||
poetry run mypy --config-file pyproject.toml ./
|
||||
|
||||
.PHONY: check-safety
|
||||
check-safety:
|
||||
poetry check
|
||||
poetry run safety check --full-report
|
||||
poetry run bandit -ll --recursive tlc tests
|
||||
|
||||
.PHONY: lint
|
||||
lint: test check-codestyle mypy check-safety
|
||||
|
||||
.PHONY: update-dev-deps
|
||||
update-dev-deps:
|
||||
poetry add -D bandit@latest darglint@latest "isort[colors]@latest" mypy@latest pre-commit@latest pydocstyle@latest pylint@latest pytest@latest pyupgrade@latest safety@latest coverage@latest coverage-badge@latest pytest-html@latest pytest-cov@latest
|
||||
poetry add -D --allow-prereleases black@latest
|
||||
|
||||
#* Docker
|
||||
.PHONY: docker-build docker-remove
|
||||
docker-build:
|
||||
@echo Building docker $(IMAGE):$(VERSION) ...
|
||||
docker build \
|
||||
-t $(IMAGE):$(VERSION) . \
|
||||
-f ./docker/Dockerfile --no-cache
|
||||
|
||||
docker-remove:
|
||||
@echo Removing docker $(IMAGE):$(VERSION) ...
|
||||
docker rmi -f $(IMAGE):$(VERSION)
|
||||
|
||||
|
||||
#* Cleaning
|
||||
.PHONY: clean .clean-build clean-pyc clean-test
|
||||
clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts
|
||||
|
||||
clean-build: ## remove build artifacts
|
||||
rm -fr build/
|
||||
rm -fr dist/
|
||||
rm -fr .eggs/
|
||||
find . -name '*.egg-info' -exec rm -fr {} +
|
||||
find . -name '*.egg' -exec rm -f {} +
|
||||
|
||||
clean-pyc: ## remove Python file artifacts
|
||||
find . -name '*.pyc' -exec rm -f {} +
|
||||
find . -name '*.pyo' -exec rm -f {} +
|
||||
find . -name '*~' -exec rm -f {} +
|
||||
find . -name '__pycache__' -exec rm -fr {} +
|
||||
find . | grep -E ".pytest_cache" | xargs rm -rf
|
||||
find . | grep -E ".mypy_cache" | xargs rm -rf
|
||||
|
||||
clean-test: ## remove test and coverage artifacts
|
||||
rm -fr .tox/
|
||||
rm -f .coverage
|
||||
rm -fr htmlcov/
|
21
tools/tlc/assets/images/coverage.svg
Normal file
21
tools/tlc/assets/images/coverage.svg
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="99" height="20">
|
||||
<linearGradient id="b" x2="0" y2="100%">
|
||||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
</linearGradient>
|
||||
<mask id="a">
|
||||
<rect width="99" height="20" rx="3" fill="#fff"/>
|
||||
</mask>
|
||||
<g mask="url(#a)">
|
||||
<path fill="#555" d="M0 0h63v20H0z"/>
|
||||
<path fill="#4c1" d="M63 0h36v20H63z"/>
|
||||
<path fill="url(#b)" d="M0 0h99v20H0z"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
||||
<text x="31.5" y="15" fill="#010101" fill-opacity=".3">coverage</text>
|
||||
<text x="31.5" y="14">coverage</text>
|
||||
<text x="80" y="15" fill="#010101" fill-opacity=".3">97%</text>
|
||||
<text x="80" y="14">97%</text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 901 B |
1355
tools/tlc/poetry.lock
generated
Normal file
1355
tools/tlc/poetry.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
146
tools/tlc/pyproject.toml
Normal file
146
tools/tlc/pyproject.toml
Normal file
|
@ -0,0 +1,146 @@
|
|||
# Poetry pyproject.toml: https://python-poetry.org/docs/pyproject/
|
||||
[build-system]
|
||||
requires = ["poetry_core>=1.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.poetry]
|
||||
name = "tlc"
|
||||
version = "0.9.0"
|
||||
description = "Transfer List Compiler (TLC) is a Python-based CLI for efficiently handling transfer lists."
|
||||
authors = ["Arm Ltd <tf-a@lists.trustedfirmware.org>"]
|
||||
license = "BSD-3"
|
||||
repository = "https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/"
|
||||
homepage = "https://trustedfirmware-a.readthedocs.io/en/latest/index.html"
|
||||
|
||||
# Keywords description https://python-poetry.org/docs/pyproject/#keywords
|
||||
keywords = [] #! Update me
|
||||
|
||||
# Pypi classifiers: https://pypi.org/classifiers/
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"Operating System :: OS Independent",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"License :: OSI Approved :: BSD License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
]
|
||||
|
||||
[tool.poetry.scripts]
|
||||
# Entry points for the package https://python-poetry.org/docs/pyproject/#scripts
|
||||
"tlc" = "tlc.__main__:cli"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.8"
|
||||
|
||||
typer = {extras = ["all"], version = "^0.4.0"}
|
||||
rich = "^10.14.0"
|
||||
click = "^8.1.7"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
bandit = "^1.7.1"
|
||||
darglint = "^1.8.1"
|
||||
black = "^24.4.2"
|
||||
isort = {extras = ["colors"], version = "^5.10.1"}
|
||||
mypy = "^0.910"
|
||||
mypy-extensions = "^0.4.3"
|
||||
pre-commit = "^2.15.0"
|
||||
pydocstyle = "^6.1.1"
|
||||
pylint = "^2.11.1"
|
||||
pytest = "^7.0.0"
|
||||
pyupgrade = "^2.29.1"
|
||||
safety = "^2.2.0"
|
||||
coverage = "^6.1.2"
|
||||
coverage-badge = "^1.1.0"
|
||||
pytest-html = "^4.1.1"
|
||||
pytest-cov = "^3.0.0"
|
||||
|
||||
[tool.black]
|
||||
# https://github.com/psf/black
|
||||
target-version = ["py38"]
|
||||
line-length = 88
|
||||
color = true
|
||||
|
||||
exclude = '''
|
||||
/(
|
||||
\.git
|
||||
| \.hg
|
||||
| \.mypy_cache
|
||||
| \.tox
|
||||
| \.venv
|
||||
| _build
|
||||
| buck-out
|
||||
| build
|
||||
| dist
|
||||
| env
|
||||
| venv
|
||||
)/
|
||||
'''
|
||||
|
||||
[tool.isort]
|
||||
# https://github.com/timothycrosley/isort/
|
||||
py_version = 38
|
||||
line_length = 88
|
||||
|
||||
known_typing = ["typing", "types", "typing_extensions", "mypy", "mypy_extensions"]
|
||||
sections = ["FUTURE", "TYPING", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
|
||||
include_trailing_comma = true
|
||||
profile = "black"
|
||||
multi_line_output = 3
|
||||
indent = 4
|
||||
color_output = true
|
||||
|
||||
[tool.mypy]
|
||||
# https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file
|
||||
python_version = 3.8
|
||||
pretty = true
|
||||
show_traceback = true
|
||||
color_output = true
|
||||
|
||||
allow_redefinition = false
|
||||
check_untyped_defs = true
|
||||
disallow_any_generics = true
|
||||
disallow_incomplete_defs = true
|
||||
ignore_missing_imports = true
|
||||
implicit_reexport = false
|
||||
no_implicit_optional = true
|
||||
show_column_numbers = true
|
||||
show_error_codes = true
|
||||
show_error_context = true
|
||||
strict_equality = true
|
||||
strict_optional = true
|
||||
warn_no_return = true
|
||||
warn_redundant_casts = true
|
||||
warn_return_any = true
|
||||
warn_unreachable = true
|
||||
warn_unused_configs = true
|
||||
warn_unused_ignores = true
|
||||
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
# https://docs.pytest.org/en/6.2.x/customize.html#pyproject-toml
|
||||
# Directories that are not visited by pytest collector:
|
||||
norecursedirs =["hooks", "*.egg", ".eggs", "dist", "build", "docs", ".tox", ".git", "__pycache__"]
|
||||
doctest_optionflags = ["NUMBER", "NORMALIZE_WHITESPACE", "IGNORE_EXCEPTION_DETAIL"]
|
||||
|
||||
# Extra options:
|
||||
addopts = [
|
||||
"--strict-markers",
|
||||
"--tb=short",
|
||||
"--doctest-modules",
|
||||
"--doctest-continue-on-failure",
|
||||
]
|
||||
|
||||
[tool.coverage.run]
|
||||
source = ["tests"]
|
||||
|
||||
[coverage.paths]
|
||||
source = "tlc"
|
||||
|
||||
[coverage.run]
|
||||
branch = true
|
||||
|
||||
[coverage.report]
|
||||
fail_under = 50
|
||||
show_missing = true
|
4
tools/tlc/setup.cfg
Normal file
4
tools/tlc/setup.cfg
Normal file
|
@ -0,0 +1,4 @@
|
|||
[darglint]
|
||||
# https://github.com/terrencepreilly/darglint
|
||||
strictness = long
|
||||
docstring_style = google
|
40
tools/tlc/tests/conftest.py
Normal file
40
tools/tlc/tests/conftest.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python3
|
||||
# type: ignore[attr-defined]
|
||||
|
||||
#
|
||||
# Copyright (c) 2024, Arm Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
""" Common configurations and fixtures for test environment."""
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
from tlc.cli import cli
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def tmptlstr(tmpdir):
|
||||
return tmpdir.join("tl.bin").strpath
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def tmpfdt(tmpdir):
|
||||
fdt = tmpdir.join("fdt.dtb")
|
||||
fdt.write_binary(b"\x00" * 100)
|
||||
return fdt
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def tlcrunner(tmptlstr):
|
||||
runner = CliRunner()
|
||||
with runner.isolated_filesystem():
|
||||
runner.invoke(cli, ["create", tmptlstr])
|
||||
return runner
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def tlc_entries(tmpfdt):
|
||||
return [(0, "/dev/null"), (1, tmpfdt.strpath), (0x102, tmpfdt.strpath)]
|
205
tools/tlc/tests/test_cli.py
Normal file
205
tools/tlc/tests/test_cli.py
Normal file
|
@ -0,0 +1,205 @@
|
|||
#!/usr/bin/env python3
|
||||
# type: ignore[attr-defined]
|
||||
|
||||
#
|
||||
# Copyright (c) 2024, Arm Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
"""Contains unit tests for the CLI functionality."""
|
||||
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
from tlc.cli import cli
|
||||
from tlc.te import TransferEntry
|
||||
from tlc.tl import TransferList
|
||||
|
||||
|
||||
def test_create_empty_tl(tmpdir):
|
||||
runner = CliRunner()
|
||||
test_file = tmpdir.join("tl.bin")
|
||||
|
||||
result = runner.invoke(cli, ["create", test_file.strpath])
|
||||
assert result.exit_code == 0
|
||||
assert TransferList.fromfile(test_file) is not None
|
||||
|
||||
|
||||
def test_create_with_fdt(tmpdir):
|
||||
runner = CliRunner()
|
||||
fdt = tmpdir.join("fdt.dtb")
|
||||
fdt.write_binary(b"\x00" * 100)
|
||||
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[
|
||||
"create",
|
||||
"--fdt",
|
||||
fdt.strpath,
|
||||
"--size",
|
||||
"1000",
|
||||
tmpdir.join("tl.bin").strpath,
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
|
||||
def test_add_single_entry(tlcrunner, tmptlstr):
|
||||
tlcrunner.invoke(cli, ["add", "--entry", "0", "/dev/null", tmptlstr])
|
||||
|
||||
tl = TransferList.fromfile(tmptlstr)
|
||||
assert tl is not None
|
||||
assert len(tl.entries) == 1
|
||||
assert tl.entries[0].id == 0
|
||||
|
||||
|
||||
def test_add_multiple_entries(tlcrunner, tlc_entries, tmptlstr):
|
||||
for id, path in tlc_entries:
|
||||
tlcrunner.invoke(cli, ["add", "--entry", id, path, tmptlstr])
|
||||
|
||||
tl = TransferList.fromfile(tmptlstr)
|
||||
assert tl is not None
|
||||
assert len(tl.entries) == len(tlc_entries)
|
||||
|
||||
|
||||
def test_info(tlcrunner, tmptlstr, tmpfdt):
|
||||
tlcrunner.invoke(cli, ["add", "--entry", "0", "/dev/null", tmptlstr])
|
||||
tlcrunner.invoke(cli, ["add", "--fdt", tmpfdt.strpath, tmptlstr])
|
||||
|
||||
result = tlcrunner.invoke(cli, ["info", tmptlstr])
|
||||
assert result.exit_code == 0
|
||||
assert "signature" in result.stdout
|
||||
assert "id" in result.stdout
|
||||
|
||||
result = tlcrunner.invoke(cli, ["info", "--header", tmptlstr])
|
||||
assert result.exit_code == 0
|
||||
assert "signature" in result.stdout
|
||||
assert "id" not in result.stdout
|
||||
|
||||
result = tlcrunner.invoke(cli, ["info", "--entries", tmptlstr])
|
||||
assert result.exit_code == 0
|
||||
assert "signature" not in result.stdout
|
||||
assert "id" in result.stdout
|
||||
|
||||
|
||||
def test_raises_max_size_error(tmptlstr, tmpfdt):
|
||||
tmpfdt.write_binary(bytes(6000))
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["create", "--fdt", tmpfdt, tmptlstr])
|
||||
|
||||
assert result.exception
|
||||
assert isinstance(result.exception, MemoryError)
|
||||
assert "TL max size exceeded, consider increasing with the option -s" in str(
|
||||
result.exception
|
||||
)
|
||||
assert "TL size has exceeded the maximum allocation" in str(
|
||||
result.exception.__cause__
|
||||
)
|
||||
|
||||
|
||||
def test_info_get_fdt_offset(tmptlstr, tmpfdt):
|
||||
runner = CliRunner()
|
||||
with runner.isolated_filesystem():
|
||||
runner.invoke(cli, ["create", "--size", "1000", tmptlstr])
|
||||
runner.invoke(cli, ["add", "--entry", "1", tmpfdt.strpath, tmptlstr])
|
||||
result = runner.invoke(cli, ["info", "--fdt-offset", tmptlstr])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert result.output.strip("\n").isdigit()
|
||||
|
||||
|
||||
def test_remove_tag(tlcrunner, tmptlstr):
|
||||
tlcrunner.invoke(cli, ["add", "--entry", "0", "/dev/null", tmptlstr])
|
||||
result = tlcrunner.invoke(cli, ["info", tmptlstr])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "signature" in result.stdout
|
||||
|
||||
tlcrunner.invoke(cli, ["remove", "--tags", "0", tmptlstr])
|
||||
tl = TransferList.fromfile(tmptlstr)
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert len(tl.entries) == 0
|
||||
|
||||
|
||||
def test_unpack_tl(tlcrunner, tmptlstr, tmpfdt, tmpdir):
|
||||
with tlcrunner.isolated_filesystem(temp_dir=tmpdir):
|
||||
tlcrunner.invoke(cli, ["add", "--entry", 1, tmpfdt.strpath, tmptlstr])
|
||||
tlcrunner.invoke(cli, ["unpack", tmptlstr])
|
||||
assert Path("te_0_1.bin").exists()
|
||||
|
||||
|
||||
def test_unpack_multiple_tes(tlcrunner, tlc_entries, tmptlstr, tmpdir):
|
||||
with tlcrunner.isolated_filesystem(temp_dir=tmpdir):
|
||||
for id, path in tlc_entries:
|
||||
tlcrunner.invoke(cli, ["add", "--entry", id, path, tmptlstr])
|
||||
|
||||
assert all(
|
||||
filter(
|
||||
lambda te: (Path(tmpdir.strpath) / f"te_{te[0]}.bin").exists(), tlc_entries
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_unpack_into_dir(tlcrunner, tmpdir, tmptlstr, tmpfdt):
|
||||
tlcrunner.invoke(cli, ["add", "--entry", 1, tmpfdt.strpath, tmptlstr])
|
||||
tlcrunner.invoke(cli, ["unpack", "-C", tmpdir.strpath, tmptlstr])
|
||||
|
||||
assert (Path(tmpdir.strpath) / "te_0_1.bin").exists()
|
||||
|
||||
|
||||
def test_unpack_into_dir_with_conflicting_tags(tlcrunner, tmpdir, tmptlstr, tmpfdt):
|
||||
tlcrunner.invoke(cli, ["add", "--entry", 1, tmpfdt.strpath, tmptlstr])
|
||||
tlcrunner.invoke(cli, ["add", "--entry", 1, tmpfdt.strpath, tmptlstr])
|
||||
tlcrunner.invoke(cli, ["unpack", "-C", tmpdir.strpath, tmptlstr])
|
||||
|
||||
assert (Path(tmpdir.strpath) / "te_0_1.bin").exists()
|
||||
assert (Path(tmpdir.strpath) / "te_1_1.bin").exists()
|
||||
|
||||
|
||||
def test_validate_invalid_signature(tmptlstr, tlcrunner, monkeypatch):
|
||||
tl = TransferList()
|
||||
tl.signature = 0xDEADBEEF
|
||||
|
||||
mock_open = lambda tmptlstr, mode: mock.mock_open(read_data=tl.header_to_bytes())()
|
||||
monkeypatch.setattr("builtins.open", mock_open)
|
||||
|
||||
result = tlcrunner.invoke(cli, ["validate", tmptlstr])
|
||||
assert result.exit_code != 0
|
||||
|
||||
|
||||
def test_validate_misaligned_entries(tmptlstr, tlcrunner, monkeypatch):
|
||||
"""Base address of a TE must be 8-byte aligned."""
|
||||
mock_open = lambda tmptlstr, mode: mock.mock_open(
|
||||
read_data=TransferList().header_to_bytes()
|
||||
+ bytes(5)
|
||||
+ TransferEntry(0, 0, bytes(0)).header_to_bytes
|
||||
)()
|
||||
monkeypatch.setattr("builtins.open", mock_open)
|
||||
|
||||
result = tlcrunner.invoke(cli, ["validate", tmptlstr])
|
||||
|
||||
assert result.exit_code == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"version", [0, TransferList.version, TransferList.version + 1, 1 << 8]
|
||||
)
|
||||
def test_validate_unsupported_version(version, tmptlstr, tlcrunner, monkeypatch):
|
||||
tl = TransferList()
|
||||
tl.version = version
|
||||
|
||||
mock_open = lambda tmptlstr, mode: mock.mock_open(read_data=tl.header_to_bytes())()
|
||||
monkeypatch.setattr("builtins.open", mock_open)
|
||||
|
||||
result = tlcrunner.invoke(cli, ["validate", tmptlstr])
|
||||
|
||||
if version >= TransferList.version and version <= 0xFF:
|
||||
assert result.exit_code == 0
|
||||
else:
|
||||
assert result.exit_code == 1
|
234
tools/tlc/tests/test_transfer_list.py
Normal file
234
tools/tlc/tests/test_transfer_list.py
Normal file
|
@ -0,0 +1,234 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# Copyright (c) 2024, Arm Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
"""Contains unit tests for the types TransferEntry and TransferList."""
|
||||
|
||||
import math
|
||||
|
||||
import pytest
|
||||
|
||||
from tlc.te import TransferEntry
|
||||
from tlc.tl import TransferList
|
||||
|
||||
large_data = 0xDEADBEEF.to_bytes(4, "big")
|
||||
small_data = 0x1234.to_bytes(3, "big")
|
||||
test_entries = [
|
||||
(0, b""),
|
||||
(1, small_data),
|
||||
(1, large_data),
|
||||
(0xFFFFFF, small_data),
|
||||
(0xFFFFFF, large_data),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"size,csum",
|
||||
[
|
||||
(-1, None),
|
||||
(0x18, 0x9E),
|
||||
(0x1000, 0xA6),
|
||||
(0x2000, 0x96),
|
||||
(0x4000, 0x76),
|
||||
],
|
||||
)
|
||||
def test_make_transfer_list(size, csum):
|
||||
if size < 8:
|
||||
with pytest.raises(AssertionError):
|
||||
tl = TransferList(size)
|
||||
else:
|
||||
tl = TransferList(size)
|
||||
|
||||
assert tl.signature == 0x4A0FB10B
|
||||
assert not tl.entries
|
||||
assert tl.sum_of_bytes() == 0
|
||||
assert tl.checksum == csum
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("tag_id", "data"), test_entries)
|
||||
def test_add_transfer_entry(tag_id, data):
|
||||
tl = TransferList(0x1000)
|
||||
te = TransferEntry(tag_id, len(data), data)
|
||||
|
||||
tl.add_transfer_entry(tag_id, data)
|
||||
|
||||
assert te in tl.entries
|
||||
assert tl.size == TransferList.hdr_size + te.size
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("tag_id", "data"),
|
||||
[
|
||||
(-1, None), # tag out of range
|
||||
(1, None), # no data provided
|
||||
(1, bytes(8000)), # very large data > total size
|
||||
(0x100000, b"0dd0edfe"), # tag out of range
|
||||
],
|
||||
)
|
||||
def test_add_out_of_range_transfer_entry(tag_id, data):
|
||||
tl = TransferList()
|
||||
|
||||
with pytest.raises(Exception):
|
||||
tl.add_transfer_entry(tag_id, data)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("tag_id", "data"), test_entries)
|
||||
def test_calculate_te_sum_of_bytes(tag_id, data):
|
||||
te = TransferEntry(tag_id, len(data), data)
|
||||
csum = (
|
||||
sum(data)
|
||||
+ sum(len(data).to_bytes(4, "big"))
|
||||
+ te.hdr_size
|
||||
+ sum(tag_id.to_bytes(4, "big"))
|
||||
) % 256
|
||||
assert te.sum_of_bytes == csum
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("tag_id", "data"), test_entries)
|
||||
def test_calculate_tl_checksum(tag_id, data):
|
||||
tl = TransferList(0x1000)
|
||||
|
||||
tl.add_transfer_entry(tag_id, data)
|
||||
assert tl.sum_of_bytes() == 0
|
||||
|
||||
|
||||
def test_empty_transfer_list_blob(tmpdir):
|
||||
"""Check that we can correctly create a transfer list header."""
|
||||
test_file = tmpdir.join("test_tl_blob.bin")
|
||||
tl = TransferList()
|
||||
tl.write_to_file(test_file)
|
||||
|
||||
with open(test_file, "rb") as f:
|
||||
assert f.read(tl.hdr_size) == tl.header_to_bytes()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("tag_id", "data"), test_entries)
|
||||
def test_single_te_transfer_list(tag_id, data, tmpdir):
|
||||
"""Check that we can create a complete TL with a single TE."""
|
||||
test_file = tmpdir.join("test_tl_blob.bin")
|
||||
tl = TransferList(0x1000)
|
||||
|
||||
tl.add_transfer_entry(tag_id, data)
|
||||
tl.write_to_file(test_file)
|
||||
|
||||
te = tl.entries[0]
|
||||
|
||||
with open(test_file, "rb") as f:
|
||||
assert f.read(tl.hdr_size) == tl.header_to_bytes()
|
||||
assert int.from_bytes(f.read(3), "little") == te.id
|
||||
assert int.from_bytes(f.read(1), "little") == te.hdr_size
|
||||
assert int.from_bytes(f.read(4), "little") == te.data_size
|
||||
assert f.read(te.data_size) == te.data
|
||||
|
||||
|
||||
def test_multiple_te_transfer_list(tmpdir):
|
||||
"""Check that we can create a TL with multiple TE's."""
|
||||
test_file = tmpdir.join("test_tl_blob.bin")
|
||||
tl = TransferList(0x1000)
|
||||
|
||||
for tag_id, data in test_entries:
|
||||
tl.add_transfer_entry(tag_id, data)
|
||||
|
||||
tl.write_to_file(test_file)
|
||||
|
||||
with open(test_file, "rb") as f:
|
||||
assert f.read(tl.hdr_size) == tl.header_to_bytes()
|
||||
# Ensure that TE's have the correct alignment
|
||||
for tag_id, data in test_entries:
|
||||
f.seek(int(math.ceil(f.tell() / 2**tl.alignment) * 2**tl.alignment))
|
||||
print(f.tell())
|
||||
assert int.from_bytes(f.read(3), "little") == tag_id
|
||||
assert int.from_bytes(f.read(1), "little") == TransferEntry.hdr_size
|
||||
# Make sure the data in the TE matches the data in the original case
|
||||
data_size = int.from_bytes(f.read(4), "little")
|
||||
assert f.read(data_size) == data
|
||||
|
||||
|
||||
def test_read_empty_transfer_list_from_file(tmpdir):
|
||||
test_file = tmpdir.join("test_tl_blob.bin")
|
||||
original_tl = TransferList(0x1000)
|
||||
original_tl.write_to_file(test_file)
|
||||
|
||||
# Read the contents of the file we just wrote
|
||||
tl = TransferList.fromfile(test_file)
|
||||
assert tl.header_to_bytes() == original_tl.header_to_bytes()
|
||||
assert tl.sum_of_bytes() == 0
|
||||
|
||||
|
||||
def test_read_single_transfer_list_from_file(tmpdir):
|
||||
test_file = tmpdir.join("test_tl_blob.bin")
|
||||
original_tl = TransferList(0x1000)
|
||||
|
||||
original_tl.add_transfer_entry(test_entries[0][0], test_entries[0][1])
|
||||
original_tl.write_to_file(test_file)
|
||||
|
||||
# Read the contents of the file we just wrote
|
||||
tl = TransferList.fromfile(test_file)
|
||||
assert tl.entries
|
||||
|
||||
te = tl.entries[0]
|
||||
assert te.id == test_entries[0][0]
|
||||
assert te.data == test_entries[0][1]
|
||||
assert tl.sum_of_bytes() == 0
|
||||
|
||||
|
||||
def test_read_multiple_transfer_list_from_file(tmpdir):
|
||||
test_file = tmpdir.join("test_tl_blob.bin")
|
||||
original_tl = TransferList(0x1000)
|
||||
|
||||
for tag_id, data in test_entries:
|
||||
original_tl.add_transfer_entry(tag_id, data)
|
||||
|
||||
original_tl.write_to_file(test_file)
|
||||
|
||||
# Read the contents of the file we just wrote
|
||||
tl = TransferList.fromfile(test_file)
|
||||
|
||||
# The TE we derive from the file might have a an associated offset, compare
|
||||
# the TE's based on the header in bytes, which doesn't account for this.
|
||||
for te0, te1 in zip(tl.entries, original_tl.entries):
|
||||
assert te0.header_to_bytes() == te1.header_to_bytes()
|
||||
|
||||
assert tl.sum_of_bytes() == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize("tag", [tag for tag, _ in test_entries])
|
||||
def test_remove_tag_from_file(tag):
|
||||
tl = TransferList(0x1000)
|
||||
|
||||
for tag_id, data in test_entries:
|
||||
tl.add_transfer_entry(tag_id, data)
|
||||
|
||||
removed_entries = list(filter(lambda te: te.id == tag, tl.entries))
|
||||
original_size = tl.size
|
||||
tl.remove_tag(tag)
|
||||
|
||||
assert not any(tag == te.id for te in tl.entries)
|
||||
assert tl.size == original_size - sum(map(lambda te: te.size, removed_entries))
|
||||
|
||||
|
||||
def test_get_fdt_offset(tmpdir):
|
||||
tl = TransferList(0x1000)
|
||||
tl.add_transfer_entry(1, 0xEDFE0DD0.to_bytes(4, "big"))
|
||||
f = tmpdir.join("blob.bin")
|
||||
|
||||
tl.write_to_file(f)
|
||||
|
||||
blob_tl = TransferList.fromfile(f)
|
||||
|
||||
assert blob_tl.hdr_size + TransferEntry.hdr_size == blob_tl.get_entry_data_offset(1)
|
||||
|
||||
|
||||
def test_get_missing_fdt_offset(tmpdir):
|
||||
tl = TransferList(0x1000)
|
||||
f = tmpdir.join("blob.bin")
|
||||
|
||||
tl.write_to_file(f)
|
||||
blob_tl = TransferList.fromfile(f)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
blob_tl.get_entry_data_offset(1)
|
27
tools/tlc/tlc/__init__.py
Normal file
27
tools/tlc/tlc/__init__.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env python3
|
||||
# type: ignore[attr-defined]
|
||||
|
||||
#
|
||||
# Copyright (c) 2024, Arm Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
"""Transfer List Compiler (TLC) is a Python-based CLI for efficiently handling transfer lists."""
|
||||
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from importlib import metadata as importlib_metadata
|
||||
else:
|
||||
import importlib_metadata
|
||||
|
||||
|
||||
def get_version() -> str:
|
||||
try:
|
||||
return importlib_metadata.version(__name__)
|
||||
except importlib_metadata.PackageNotFoundError: # pragma: no cover
|
||||
return "unknown"
|
||||
|
||||
|
||||
version: str = get_version()
|
13
tools/tlc/tlc/__main__.py
Normal file
13
tools/tlc/tlc/__main__.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
# type: ignore[attr-defined]
|
||||
|
||||
#
|
||||
# Copyright (c) 2024, Arm Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
from tlc.cli import cli
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli()
|
160
tools/tlc/tlc/cli.py
Normal file
160
tools/tlc/tlc/cli.py
Normal file
|
@ -0,0 +1,160 @@
|
|||
#!/usr/bin/env python3
|
||||
# type: ignore[attr-defined]
|
||||
|
||||
#
|
||||
# Copyright (c) 2024, Arm Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
"""Module defining the Transfer List Compiler (TLC) command line interface."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import click
|
||||
|
||||
from tlc.tl import *
|
||||
|
||||
|
||||
@click.group()
|
||||
@click.version_option()
|
||||
def cli():
|
||||
pass
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.argument("filename", type=click.Path(dir_okay=False))
|
||||
@click.option(
|
||||
"-s", "--size", default=0x1000, type=int, help="Maximum size of the Transfer List"
|
||||
)
|
||||
@click.option(
|
||||
"--fdt",
|
||||
type=click.Path(exists=True),
|
||||
help="Path to flattened device tree (FDT).",
|
||||
)
|
||||
@click.option(
|
||||
"--entry",
|
||||
type=(int, click.Path(exists=True)),
|
||||
multiple=True,
|
||||
help="A tag ID and the corresponding path to a binary blob in the form <id> <path-to-blob>.",
|
||||
)
|
||||
@click.option(
|
||||
"--flags",
|
||||
default=TRANSFER_LIST_ENABLE_CHECKSUM,
|
||||
show_default=True,
|
||||
help="Settings for the TL's properties.",
|
||||
)
|
||||
def create(filename, size, fdt, entry, flags):
|
||||
"""Create a new Transfer List."""
|
||||
tl = TransferList(size)
|
||||
|
||||
entry = (*entry, (1, fdt)) if fdt else entry
|
||||
|
||||
try:
|
||||
for id, path in entry:
|
||||
tl.add_transfer_entry_from_file(id, path)
|
||||
except MemoryError as mem_excp:
|
||||
raise MemoryError(
|
||||
"TL max size exceeded, consider increasing with the option -s"
|
||||
) from mem_excp
|
||||
|
||||
tl.write_to_file(filename)
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
|
||||
@click.option(
|
||||
"--fdt-offset",
|
||||
is_flag=True,
|
||||
help="Returns the offset of FDT in the TL if it is present.",
|
||||
)
|
||||
@click.option(
|
||||
"--header",
|
||||
is_flag=True,
|
||||
help="Print the Transfer List header.",
|
||||
)
|
||||
@click.option(
|
||||
"--entries",
|
||||
is_flag=True,
|
||||
help="Print the Transfer List entries.",
|
||||
)
|
||||
def info(filename, fdt_offset, header, entries):
|
||||
"""Print the contents of an existing Transfer List.
|
||||
|
||||
This command allows you to extract the data stored in a binary blob
|
||||
representing a transfer list (TL). The transfer list must comply with the
|
||||
version of the firmware handoff specification supported by this tool.
|
||||
"""
|
||||
tl = TransferList.fromfile(filename)
|
||||
|
||||
if fdt_offset:
|
||||
return print(tl.get_entry_data_offset(1))
|
||||
|
||||
if header and entries or not (header or entries):
|
||||
print(tl, sep="")
|
||||
if tl.entries:
|
||||
print("----", tl.get_transfer_entries_str(), sep="\n")
|
||||
elif entries:
|
||||
print(tl.get_transfer_entries_str())
|
||||
elif header:
|
||||
print(tl)
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
|
||||
@click.option(
|
||||
"--tags",
|
||||
type=int,
|
||||
multiple=True,
|
||||
help="Tags to be removed from TL.",
|
||||
)
|
||||
def remove(filename, tags):
|
||||
"""Remove Transfer Entries with given tags.
|
||||
|
||||
Remove Transfer Entries with given tags from a Transfer List."""
|
||||
tl = TransferList.fromfile(filename)
|
||||
|
||||
for tag in tags:
|
||||
tl.remove_tag(tag)
|
||||
tl.write_to_file(filename)
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
|
||||
@click.option(
|
||||
"--entry",
|
||||
type=(int, click.Path(exists=True)),
|
||||
multiple=True,
|
||||
help="A tag ID and the corresponding path to a binary blob in the form <id> <path-to-blob>.",
|
||||
)
|
||||
def add(filename, entry):
|
||||
"""Update an existing Transfer List with given images."""
|
||||
tl = TransferList.fromfile(filename)
|
||||
|
||||
for id, path in entry:
|
||||
tl.add_transfer_entry_from_file(id, path)
|
||||
|
||||
tl.write_to_file(filename)
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
|
||||
@click.option(
|
||||
"-C", type=click.Path(exists=True), help="Output directory for extracted images."
|
||||
)
|
||||
def unpack(filename, c):
|
||||
"""Unpack images from a Transfer List."""
|
||||
tl = TransferList.fromfile(filename)
|
||||
pwd = Path(".") if not c else Path(c)
|
||||
|
||||
for i, te in enumerate(tl.entries):
|
||||
with open(pwd / f"te_{i}_{te.id}.bin", "wb") as f:
|
||||
f.write(te.data)
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
|
||||
def validate(filename):
|
||||
"""Validate the contents of an existing Transfer List."""
|
||||
TransferList.fromfile(filename)
|
||||
print("Valid TL!")
|
56
tools/tlc/tlc/te.py
Normal file
56
tools/tlc/tlc/te.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# Copyright (c) 2024, Arm Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
"""Module containing definitions pertaining to the 'Transfer Entry' (TE) type."""
|
||||
|
||||
from typing import ClassVar
|
||||
|
||||
import struct
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class TransferEntry:
|
||||
"""Class representing a Transfer Entry."""
|
||||
|
||||
id: int
|
||||
data_size: int
|
||||
data: bytes
|
||||
hdr_size: int = 8
|
||||
offset: int = 0
|
||||
# Header encoding, with little-endian byte order.
|
||||
encoding: ClassVar[str] = "<BI"
|
||||
|
||||
def __post_init__(self):
|
||||
if self.id < 0 or self.id > 0xFFFFFF:
|
||||
raise ValueError(
|
||||
f"Out of bounds tag ID: {self.id:x}.\n"
|
||||
f"Valid range is from 0 to 0xFFFFFF. Please ensure the tag ID is within this range."
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "\n".join(
|
||||
[
|
||||
f"{k:<10} {hex(v)}"
|
||||
for k, v in vars(self).items()
|
||||
if not isinstance(v, bytes)
|
||||
]
|
||||
)
|
||||
|
||||
@property
|
||||
def size(self) -> int:
|
||||
return self.hdr_size + len(self.data)
|
||||
|
||||
@property
|
||||
def sum_of_bytes(self) -> int:
|
||||
return (sum(self.header_to_bytes()) + sum(self.data)) % 256
|
||||
|
||||
def header_to_bytes(self) -> bytes:
|
||||
return self.id.to_bytes(3, "little") + struct.pack(
|
||||
self.encoding, self.hdr_size, self.data_size
|
||||
)
|
176
tools/tlc/tlc/tl.py
Normal file
176
tools/tlc/tlc/tl.py
Normal file
|
@ -0,0 +1,176 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# Copyright (c) 2024, Arm Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
"""Module containing definitions pertaining to the 'Transfer List' (TL) type."""
|
||||
|
||||
import typing
|
||||
|
||||
import math
|
||||
import struct
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
from tlc.te import TransferEntry
|
||||
|
||||
TRANSFER_LIST_ENABLE_CHECKSUM = 0b1
|
||||
|
||||
|
||||
class TransferList:
|
||||
"""Class representing a Transfer List based on version 1.0 of the Firmware Handoff specification."""
|
||||
|
||||
# Header encoding, with little-endian byte order.
|
||||
encoding = "<I4B4I"
|
||||
hdr_size = 0x18
|
||||
signature = 0x4A0FB10B
|
||||
version = 1
|
||||
|
||||
def __init__(
|
||||
self, max_size: int = hdr_size, flags: int = TRANSFER_LIST_ENABLE_CHECKSUM
|
||||
) -> None:
|
||||
assert max_size >= self.hdr_size
|
||||
self.checksum: int = 0
|
||||
self.alignment: int = 3
|
||||
self.size = self.hdr_size
|
||||
self.total_size = max_size
|
||||
self.flags = flags
|
||||
self.entries: typing.List["TransferEntry"] = []
|
||||
self.update_checksum()
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "\n".join(
|
||||
[
|
||||
f"{k:<10} {hex(v)}"
|
||||
for k, v in vars(self).items()
|
||||
if not isinstance(v, list)
|
||||
]
|
||||
)
|
||||
|
||||
def get_transfer_entries_str(self):
|
||||
return "\n----\n".join([str(te) for _, te in enumerate(self.entries)])
|
||||
|
||||
@classmethod
|
||||
def fromfile(cls, filepath: Path) -> "TransferList":
|
||||
tl = cls()
|
||||
|
||||
with open(filepath, "rb") as f:
|
||||
(
|
||||
tl.signature,
|
||||
tl.checksum,
|
||||
tl.version,
|
||||
tl.hdr_size,
|
||||
tl.alignment,
|
||||
used_size,
|
||||
tl.total_size,
|
||||
tl.flags,
|
||||
_,
|
||||
) = struct.unpack(
|
||||
cls.encoding,
|
||||
f.read(tl.hdr_size),
|
||||
)
|
||||
|
||||
if tl.signature != TransferList.signature:
|
||||
raise ValueError(f"Invalid TL signature 0x{tl.signature:x}!")
|
||||
elif tl.version == 0 or tl.version > 0xFF:
|
||||
raise ValueError(f"Invalid TL version 0x{tl.version:x}!")
|
||||
else:
|
||||
while tl.size < used_size:
|
||||
# We add an extra padding byte into the header so we can extract
|
||||
# the 3-byte wide ID as a 4-byte uint, shift out this padding
|
||||
# once we have the id.
|
||||
te_base = f.tell()
|
||||
(id, hdr_size, data_size) = struct.unpack(
|
||||
TransferEntry.encoding[0] + "I" + TransferEntry.encoding[1:],
|
||||
b"\x00" + f.read(TransferEntry.hdr_size),
|
||||
)
|
||||
|
||||
id >>= 8
|
||||
|
||||
te = tl.add_transfer_entry(id, f.read(data_size))
|
||||
te.offset = te_base
|
||||
f.seek(align(te_base + hdr_size + data_size, 2**tl.alignment))
|
||||
|
||||
return tl
|
||||
|
||||
def header_to_bytes(self) -> bytes:
|
||||
return struct.pack(
|
||||
self.encoding,
|
||||
self.signature,
|
||||
self.checksum,
|
||||
self.version,
|
||||
self.hdr_size,
|
||||
self.alignment,
|
||||
self.size,
|
||||
self.total_size,
|
||||
self.flags,
|
||||
0,
|
||||
)
|
||||
|
||||
def update_checksum(self) -> None:
|
||||
"""Calculates the checksum based on the sum of bytes."""
|
||||
self.checksum = 256 - ((self.sum_of_bytes() - self.checksum) % 256)
|
||||
|
||||
def sum_of_bytes(self) -> int:
|
||||
"""Sum of all bytes between the base address and the end of that last TE (modulo 0xff)."""
|
||||
return (
|
||||
sum(self.header_to_bytes()) + sum(te.sum_of_bytes for te in self.entries)
|
||||
) % 256
|
||||
|
||||
def get_entry_data_offset(self, tag_id: int) -> int:
|
||||
"""Returns offset of data of a TE from the base of the TL."""
|
||||
for te in self.entries:
|
||||
if te.id == tag_id:
|
||||
return te.offset + te.hdr_size
|
||||
|
||||
raise ValueError(f"Tag {tag_id} not found in TL!")
|
||||
|
||||
def add_transfer_entry(self, tag_id: int, data: bytes) -> "TransferEntry":
|
||||
"""Appends a TransferEntry into the internal list of TE's."""
|
||||
if not (self.total_size >= self.size + TransferEntry.hdr_size + len(data)):
|
||||
raise MemoryError(
|
||||
f"TL size has exceeded the maximum allocation {self.total_size}."
|
||||
)
|
||||
else:
|
||||
te = TransferEntry(tag_id, len(data), data)
|
||||
self.entries.append(te)
|
||||
self.size += te.size
|
||||
self.update_checksum()
|
||||
return te
|
||||
|
||||
def add_transfer_entry_from_file(self, tag_id: int, path: Path) -> "TransferEntry":
|
||||
with open(path, "rb") as f:
|
||||
return self.add_transfer_entry(tag_id, f.read())
|
||||
|
||||
def write_to_file(self, file: Path) -> None:
|
||||
"""Write the contents of the TL to a file."""
|
||||
with open(file, "wb") as f:
|
||||
f.write(self.header_to_bytes())
|
||||
for te in self.entries:
|
||||
assert f.tell() + te.hdr_size + te.data_size < self.total_size
|
||||
te_base = f.tell()
|
||||
f.write(te.header_to_bytes())
|
||||
f.write(te.data)
|
||||
# Ensure the next TE has the correct alignment
|
||||
f.write(
|
||||
bytes(
|
||||
(
|
||||
align(
|
||||
te_base + te.hdr_size + te.data_size, 2**self.alignment
|
||||
)
|
||||
- f.tell()
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def remove_tag(self, tag: int) -> None:
|
||||
self.entries = list(filter(lambda te: te.id != tag, self.entries))
|
||||
self.size = self.hdr_size + sum(map(lambda te: te.size, self.entries))
|
||||
self.update_checksum()
|
||||
|
||||
|
||||
def align(n, alignment):
|
||||
return int(math.ceil(n / alignment) * alignment)
|
Loading…
Add table
Reference in a new issue