diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..623ee03 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,34 @@ +name: ❤️ Tests + +on: + pull_request: + branches: ["main", "master", "develop"] + push: + branches: ["main", "master", "develop"] + +jobs: + test: + name: Run Tests + runs-on: ubuntu-latest + + strategy: + matrix: + python-version: ["3.10", "3.11", "3.12"] + + steps: + - name: 📥 Checkout code + uses: actions/checkout@v4 + + - name: 🐍 Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: ⚙️ Install dependencies + run: | + python -m pip install --upgrade pip + pip install poetry + poetry install + + - name: ❤️ Run tests + run: poetry run pytest --tb=short -v diff --git a/mkdocs_dracula_theme/assets/css/mkdocs.min.css b/mkdocs_dracula_theme/assets/css/mkdocs.min.css index 56dd4a4..2130b24 100644 --- a/mkdocs_dracula_theme/assets/css/mkdocs.min.css +++ b/mkdocs_dracula_theme/assets/css/mkdocs.min.css @@ -1 +1,2 @@ -code,pre{background-color:var(--black)}footer,table{width:100%}.content,.sidebar ul.components{padding:0}.active,.bold,.sidebar h1{font-weight:700}.normal,a{text-decoration:none}a{color:var(--white)}a:hover{color:var(--pink)}footer{position:fixed;bottom:0}.footer-text{font-size:14px!important;margin-top:0!important;margin-bottom:0!important}pre{margin:1rem 0;padding:1rem 1rem 10px;font-size:.775em}article{padding-left:5%;padding-right:5%}table,td,th{border-color:var(--greySecondary)!important;padding-right:15px!important;border-width:1px;border-style:solid;padding:1%}h1,h2,h3,h4{margin-top:1.8rem!important}img,svg{max-width:100%;margin-left:auto;margin-right:auto}.logo{display:block;margin-bottom:10%;width:150px!important}.sidebar{min-width:270px;max-width:270px;-webkit-transition:.3s;-o-transition:.3s;transition:.3s;position:sticky}.sidebar.active{margin-left:-270px}.sidebar h1{margin-bottom:20px;font-size:30px}.sidebar h1 .logo span{font-size:14px;display:block}.sidebar ul li{font-size:16px}.sidebar ul li>ul{margin-left:10px}.sidebar ul li>ul li{font-size:14px}.sidebar ul li a{padding:10px 0;display:block;border-bottom:1px solid rgba(255,255,255,.1)}.sidebar .custom-menu{display:inline-block;position:absolute;top:81px;right:0;margin-right:-41px;-webkit-transition:.3s;-o-transition:.3s;transition:.3s}.sidebar .custom-menu .btn{width:60px;height:60px;border-radius:50%;position:relative}.sidebar .custom-menu .btn i{margin-right:00px;font-size:18px}.sidebar .custom-menu .btn.btn-primary{background:0 0;border-color:transparent}.sidebar .custom-menu .btn.btn-primary:after{z-index:-1;position:absolute;top:0;left:0;right:0;bottom:0;content:'';-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);background:linear-gradient(var(--gradientDegree),var(--purple) 0,var(--cyan) 100%);border-radius:10px}.sidebar .custom-menu .btn.btn-primary:focus,.sidebar .custom-menu .btn.btn-primary:hover{background:0 0!important;border-color:transparent!important}@media (prefers-reduced-motion:reduce){.sidebar .custom-menu{-webkit-transition:none;-o-transition:none;transition:none}}@media (max-width:991.98px){.sidebarCollapse span{display:none}.sidebar{margin-left:-270px}.sidebar.active{margin-left:0}}.content{width:100%;min-height:100vh;-webkit-transition:.3s;-o-transition:.3s;transition:.3s}.content-search,.section-content{padding-top:7px!important}.dot-ul{list-style:none;display:flex;margin:10px 0 0;padding-left:23%}.dot-li{width:12px;height:12px;margin:3px;border-radius:100%}.md-source-repo-icon{display:inline-block;vertical-align:middle;margin-right:10px;margin-left:10px;font-size:xx-large}.md-source-repo-text{display:flex;font-size:14px;text-align:left;gap:.4rem;list-style-type:none;margin:.1rem 0 0;opacity:.75;overflow:hidden;padding:0;width:100%}.md-source-repo-url{display:inline-block;max-width:calc(100% - 1.2rem);white-space:nowrap;width:15em;overflow:hidden;text-overflow:ellipsis;font-size:16px;text-align:left;vertical-align:middle}.flex-column{flex-direction:row-reverse!important}.divider{min-width:10px!important;flex-shrink:0;width:1.5rem}.btn-preview,.btn-preview:disabled{width:170px}.btn-preview:hover{border-color:var(--green)}.row-preview{padding:5px}.drac-bg-grey-ternary{--accentColor:var(--greyTernary);background-color:var(--greyTernary)}.drac-text-grey-ternary{color:var(--greyTernary)}@media all and (min-width:992px){.dropdown-menu li{position:relative}.nav-item .submenu{display:none;position:absolute;left:100%;top:-7px}.nav-item .submenu-left{right:100%;left:auto}.dropdown-menu>li:hover{background-color:#f1f1f1}.dropdown-menu>li:hover>.submenu{display:block}}@media (max-width:991px){.dropdown-menu .dropdown-menu{margin-left:.7rem;margin-right:.7rem;margin-bottom:.5rem}}.normal{font-weight:400;font-style:normal}.italic{font-style:italic}.scratched{text-decoration:line-through}.underline{text-decoration:underline}.overline{text-decoration:overline}@media only screen and (max-width:780px){a,code,h1,h2,h3,h4,h5,h6,li,p,small{margin-top:1rem!important;margin-bottom:1rem!important}.sidebar ul li a{padding:1%;font-size:15px!important;margin-top:1%!important;margin-bottom:8%!important}.site-name{font-size:14px!important}.title,h1,h2,h3,h4,h5,h6{font-size:18px!important}.container{padding-left:5%!important;padding-right:5%!important}main{margin-left:0!important;margin-right:0!important;line-height:1.8!important}a,code,li,p,small{font-size:12px!important}article{padding-left:10%;padding-right:10%}.section-content{padding-top:7px!important;padding-bottom:20%!important}.footer-text{font-size:12px!important;margin-top:0!important;margin-bottom:0!important}}.search-box{margin-top:2%;margin-bottom:1%}.btn-toggle{color:var(--white)!important;background-color:transparent;display:inline-flex!important;text-decoration:none;transition:.16s ease-in-out}.btn-toggle:focus,.btn-toggle:hover{color:var(--purple)!important;background:var(--black)!important}.btn-toggle::after{width:1.25em;line-height:0;content:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%280,0,0,.5%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e");transition:transform .35s;transform-origin:.5em 50%;margin-left:10px}[data-bs-theme=dark] .btn-toggle::after{content:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%28248,248,242,1%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e")}.btn-toggle[aria-expanded=true]{color:rgba(var(--bs-emphasis-color-rgb),.85)}.btn-toggle[aria-expanded=true]::after{transform:rotate(90deg)}.drac-anchor-secondary{margin-left:10%}.drac-box-ternary{margin-top:3%;margin-left:10%}.drac-input-search{margin-top:2px;width:170px} \ No newline at end of file +code,pre{background-color:var(--black)}footer,table{width:100%}.content,.sidebar ul.components{padding:0}.active,.bold,.sidebar h1{font-weight:700}.normal,a{text-decoration:none}a{color:var(--white)}a:hover{color:var(--pink)}footer{position:fixed;bottom:0}.footer-text{font-size:14px!important;margin-top:0!important;margin-bottom:0!important}pre{margin:1rem 0;padding:1rem 1rem 10px;font-size:.775em}article{padding-left:5%;padding-right:5%}table,td,th{border-color:var(--greySecondary)!important;padding-right:15px!important;border-width:1px;border-style:solid;padding:1%}h1,h2,h3,h4{margin-top:1.8rem!important}img,svg{max-width:100%;margin-left:auto;margin-right:auto}.logo{display:block;margin-bottom:10%;width:150px!important}.sidebar{min-width:270px;max-width:270px;-webkit-transition:.3s;-o-transition:.3s;transition:.3s;position:sticky}.sidebar.active{margin-left:-270px}.sidebar h1{margin-bottom:20px;font-size:30px}.sidebar h1 .logo span{font-size:14px;display:block}.sidebar ul li{font-size:16px}.sidebar ul li>ul{margin-left:10px}.sidebar ul li>ul li{font-size:14px}.sidebar ul li a{padding:10px 0;display:block;border-bottom:1px solid rgba(255,255,255,.1)}.sidebar .custom-menu{display:inline-block;position:absolute;top:81px;right:0;margin-right:-41px;-webkit-transition:.3s;-o-transition:.3s;transition:.3s}.sidebar .custom-menu .btn{width:60px;height:60px;border-radius:50%;position:relative}.sidebar .custom-menu .btn i{margin-right:00px;font-size:18px}.sidebar .custom-menu .btn.btn-primary{background:0 0;border-color:transparent}.sidebar .custom-menu .btn.btn-primary:after{z-index:-1;position:absolute;top:0;left:0;right:0;bottom:0;content:'';-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);background:linear-gradient(var(--gradientDegree),var(--purple) 0,var(--cyan) 100%);border-radius:10px}.sidebar .custom-menu .btn.btn-primary:focus,.sidebar .custom-menu .btn.btn-primary:hover{background:0 0!important;border-color:transparent!important}@media (prefers-reduced-motion:reduce){.sidebar .custom-menu{-webkit-transition:none;-o-transition:none;transition:none}}@media (max-width:991.98px){.sidebarCollapse span{display:none}.sidebar{margin-left:-270px}.sidebar.active{margin-left:0}}.content{width:100%;min-height:100vh;-webkit-transition:.3s;-o-transition:.3s;transition:.3s}.content-search,.section-content{padding-top:7px!important}.dot-ul{list-style:none;display:flex;margin:10px 0 0;padding-left:23%}.dot-li{width:12px;height:12px;margin:3px;border-radius:100%}.md-source-repo-icon{display:inline-block;vertical-align:middle;margin-right:10px;margin-left:10px;font-size:xx-large}.md-source-repo-text{display:flex;font-size:14px;text-align:left;gap:.4rem;list-style-type:none;margin:.1rem 0 0;opacity:.75;overflow:hidden;padding:0;width:100%}.md-source-repo-url{display:inline-block;max-width:calc(100% - 1.2rem);white-space:nowrap;width:15em;overflow:hidden;text-overflow:ellipsis;font-size:16px;text-align:left;vertical-align:middle}.flex-column{flex-direction:row-reverse!important}.divider{min-width:10px!important;flex-shrink:0;width:1.5rem}.btn-preview,.btn-preview:disabled{width:170px}.btn-preview:hover{border-color:var(--green)}.row-preview{padding:5px}.drac-bg-grey-ternary{--accentColor:var(--greyTernary);background-color:var(--greyTernary)}.drac-text-grey-ternary{color:var(--greyTernary)}@media all and (min-width:992px){.dropdown-menu li{position:relative}.nav-item .submenu{display:none;position:absolute;left:100%;top:-7px}.nav-item .submenu-left{right:100%;left:auto}.dropdown-menu>li:hover{background-color:#f1f1f1}.dropdown-menu>li:hover>.submenu{display:block}}@media (max-width:991px){.dropdown-menu .dropdown-menu{margin-left:.7rem;margin-right:.7rem;margin-bottom:.5rem}}.normal{font-weight:400;font-style:normal}.italic{font-style:italic}.scratched{text-decoration:line-through}.underline{text-decoration:underline}.overline{text-decoration:overline}@media only screen and (max-width:780px){a,code,h1,h2,h3,h4,h5,h6,li,p,small{margin-top:1rem!important;margin-bottom:1rem!important}.sidebar ul li a{padding:1%;font-size:15px!important;margin-top:1%!important;margin-bottom:8%!important}.site-name{font-size:14px!important}.title,h1,h2,h3,h4,h5,h6{font-size:18px!important}.container{padding-left:5%!important;padding-right:5%!important}main{margin-left:0!important;margin-right:0!important;line-height:1.8!important}a,code,li,p,small{font-size:12px!important}article{padding-left:10%;padding-right:10%}.section-content{padding-top:7px!important;padding-bottom:20%!important}.footer-text{font-size:12px!important;margin-top:0!important;margin-bottom:0!important}}.search-box{margin-top:2%;margin-bottom:1%}.btn-toggle{color:var(--white)!important;background-color:transparent;display:inline-flex!important;text-decoration:none;transition:.16s ease-in-out}.btn-toggle:focus,.btn-toggle:hover{color:var(--purple)!important;background:var(--black)!important}.btn-toggle::after{width:1.25em;line-height:0;content:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%280,0,0,.5%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e");transition:transform .35s;transform-origin:.5em 50%;margin-left:10px}[data-bs-theme=dark] .btn-toggle::after{content:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%28248,248,242,1%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e")}.btn-toggle[aria-expanded=true]{color:rgba(var(--bs-emphasis-color-rgb),.85)}.btn-toggle[aria-expanded=true]::after{transform:rotate(90deg)}.drac-anchor-secondary{margin-left:10%}.drac-box-ternary{margin-top:3%;margin-left:10%}.drac-input-search{margin-top:2px;width:170px} +.admonition{border-left:4px solid var(--purple);border-radius:.5rem;background:var(--purple-transparent);padding:.75rem 1rem;margin:1.25rem 0;overflow:hidden}.admonition p:last-child{margin-bottom:0}.admonition-title{font-weight:700;margin:-.75rem -1rem .75rem -1rem;padding:.5rem 1rem;display:flex;align-items:center}.admonition-title::before{font-family:FontAwesome;margin-right:.5rem;content:"\f040"}.admonition.note{border-color:var(--purple);background:var(--purple-transparent)}.admonition.note .admonition-title{background:rgba(149,128,255,.15);color:var(--purple)}.admonition.note .admonition-title::before{content:"\f040"}.admonition.abstract,.admonition.summary,.admonition.tldr{border-color:var(--cyan);background:var(--cyan-transparent)}.admonition.abstract .admonition-title,.admonition.summary .admonition-title,.admonition.tldr .admonition-title{background:rgba(128,255,234,.15);color:var(--cyan)}.admonition.abstract .admonition-title::before,.admonition.summary .admonition-title::before,.admonition.tldr .admonition-title::before{content:"\f0ea"}.admonition.info{border-color:var(--cyan);background:var(--cyan-transparent)}.admonition.info .admonition-title{background:rgba(128,255,234,.15);color:var(--cyan)}.admonition.info .admonition-title::before{content:"\f05a"}.admonition.tip,.admonition.hint,.admonition.important{border-color:var(--green);background:var(--green-transparent)}.admonition.tip .admonition-title,.admonition.hint .admonition-title,.admonition.important .admonition-title{background:rgba(138,255,128,.15);color:var(--green)}.admonition.tip .admonition-title::before,.admonition.hint .admonition-title::before,.admonition.important .admonition-title::before{content:"\f0eb"}.admonition.success,.admonition.check,.admonition.done{border-color:var(--green);background:var(--green-transparent)}.admonition.success .admonition-title,.admonition.check .admonition-title,.admonition.done .admonition-title{background:rgba(138,255,128,.15);color:var(--green)}.admonition.success .admonition-title::before,.admonition.check .admonition-title::before,.admonition.done .admonition-title::before{content:"\f058"}.admonition.question,.admonition.help,.admonition.faq{border-color:var(--yellow);background:var(--yellow-transparent)}.admonition.question .admonition-title,.admonition.help .admonition-title,.admonition.faq .admonition-title{background:rgba(255,255,128,.15);color:var(--yellow)}.admonition.question .admonition-title::before,.admonition.help .admonition-title::before,.admonition.faq .admonition-title::before{content:"\f059"}.admonition.warning,.admonition.caution,.admonition.attention{border-color:var(--orange);background:var(--orange-transparent)}.admonition.warning .admonition-title,.admonition.caution .admonition-title,.admonition.attention .admonition-title{background:rgba(255,202,128,.15);color:var(--orange)}.admonition.warning .admonition-title::before,.admonition.caution .admonition-title::before,.admonition.attention .admonition-title::before{content:"\f071"}.admonition.failure,.admonition.fail,.admonition.missing{border-color:var(--pink);background:var(--pink-transparent)}.admonition.failure .admonition-title,.admonition.fail .admonition-title,.admonition.missing .admonition-title{background:rgba(255,128,191,.15);color:var(--pink)}.admonition.failure .admonition-title::before,.admonition.fail .admonition-title::before,.admonition.missing .admonition-title::before{content:"\f057"}.admonition.danger,.admonition.error{border-color:var(--red);background:var(--red-transparent)}.admonition.danger .admonition-title,.admonition.error .admonition-title{background:rgba(255,149,128,.15);color:var(--red)}.admonition.danger .admonition-title::before,.admonition.error .admonition-title::before{content:"\f0e7"}.admonition.bug{border-color:var(--red);background:var(--red-transparent)}.admonition.bug .admonition-title{background:rgba(255,149,128,.15);color:var(--red)}.admonition.bug .admonition-title::before{content:"\f188"}.admonition.example{border-color:var(--purple);background:var(--purple-transparent)}.admonition.example .admonition-title{background:rgba(149,128,255,.15);color:var(--purple)}.admonition.example .admonition-title::before{content:"\f03a"}.admonition.quote,.admonition.cite{border-color:var(--grey);background:rgba(65,69,88,.2)}.admonition.quote .admonition-title,.admonition.cite .admonition-title{background:rgba(65,69,88,.3);color:var(--white)}.admonition.quote .admonition-title::before,.admonition.cite .admonition-title::before{content:"\f10d"} diff --git a/poetry.lock b/poetry.lock index 9d60863..b4f5bd2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. [[package]] name = "build" @@ -49,7 +49,146 @@ files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -markers = {main = "platform_system == \"Windows\"", dev = "os_name == \"nt\""} +markers = {main = "platform_system == \"Windows\"", dev = "os_name == \"nt\" or sys_platform == \"win32\""} + +[[package]] +name = "coverage" +version = "7.10.7" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "coverage-7.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fc04cc7a3db33664e0c2d10eb8990ff6b3536f6842c9590ae8da4c614b9ed05a"}, + {file = "coverage-7.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e201e015644e207139f7e2351980feb7040e6f4b2c2978892f3e3789d1c125e5"}, + {file = "coverage-7.10.7-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:240af60539987ced2c399809bd34f7c78e8abe0736af91c3d7d0e795df633d17"}, + {file = "coverage-7.10.7-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8421e088bc051361b01c4b3a50fd39a4b9133079a2229978d9d30511fd05231b"}, + {file = "coverage-7.10.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6be8ed3039ae7f7ac5ce058c308484787c86e8437e72b30bf5e88b8ea10f3c87"}, + {file = "coverage-7.10.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e28299d9f2e889e6d51b1f043f58d5f997c373cc12e6403b90df95b8b047c13e"}, + {file = "coverage-7.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c4e16bd7761c5e454f4efd36f345286d6f7c5fa111623c355691e2755cae3b9e"}, + {file = "coverage-7.10.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b1c81d0e5e160651879755c9c675b974276f135558cf4ba79fee7b8413a515df"}, + {file = "coverage-7.10.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:606cc265adc9aaedcc84f1f064f0e8736bc45814f15a357e30fca7ecc01504e0"}, + {file = "coverage-7.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:10b24412692df990dbc34f8fb1b6b13d236ace9dfdd68df5b28c2e39cafbba13"}, + {file = "coverage-7.10.7-cp310-cp310-win32.whl", hash = "sha256:b51dcd060f18c19290d9b8a9dd1e0181538df2ce0717f562fff6cf74d9fc0b5b"}, + {file = "coverage-7.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:3a622ac801b17198020f09af3eaf45666b344a0d69fc2a6ffe2ea83aeef1d807"}, + {file = "coverage-7.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a609f9c93113be646f44c2a0256d6ea375ad047005d7f57a5c15f614dc1b2f59"}, + {file = "coverage-7.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:65646bb0359386e07639c367a22cf9b5bf6304e8630b565d0626e2bdf329227a"}, + {file = "coverage-7.10.7-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5f33166f0dfcce728191f520bd2692914ec70fac2713f6bf3ce59c3deacb4699"}, + {file = "coverage-7.10.7-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:35f5e3f9e455bb17831876048355dca0f758b6df22f49258cb5a91da23ef437d"}, + {file = "coverage-7.10.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4da86b6d62a496e908ac2898243920c7992499c1712ff7c2b6d837cc69d9467e"}, + {file = "coverage-7.10.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6b8b09c1fad947c84bbbc95eca841350fad9cbfa5a2d7ca88ac9f8d836c92e23"}, + {file = "coverage-7.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4376538f36b533b46f8971d3a3e63464f2c7905c9800db97361c43a2b14792ab"}, + {file = "coverage-7.10.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:121da30abb574f6ce6ae09840dae322bef734480ceafe410117627aa54f76d82"}, + {file = "coverage-7.10.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:88127d40df529336a9836870436fc2751c339fbaed3a836d42c93f3e4bd1d0a2"}, + {file = "coverage-7.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ba58bbcd1b72f136080c0bccc2400d66cc6115f3f906c499013d065ac33a4b61"}, + {file = "coverage-7.10.7-cp311-cp311-win32.whl", hash = "sha256:972b9e3a4094b053a4e46832b4bc829fc8a8d347160eb39d03f1690316a99c14"}, + {file = "coverage-7.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:a7b55a944a7f43892e28ad4bc0561dfd5f0d73e605d1aa5c3c976b52aea121d2"}, + {file = "coverage-7.10.7-cp311-cp311-win_arm64.whl", hash = "sha256:736f227fb490f03c6488f9b6d45855f8e0fd749c007f9303ad30efab0e73c05a"}, + {file = "coverage-7.10.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7bb3b9ddb87ef7725056572368040c32775036472d5a033679d1fa6c8dc08417"}, + {file = "coverage-7.10.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:18afb24843cbc175687225cab1138c95d262337f5473512010e46831aa0c2973"}, + {file = "coverage-7.10.7-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:399a0b6347bcd3822be369392932884b8216d0944049ae22925631a9b3d4ba4c"}, + {file = "coverage-7.10.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:314f2c326ded3f4b09be11bc282eb2fc861184bc95748ae67b360ac962770be7"}, + {file = "coverage-7.10.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c41e71c9cfb854789dee6fc51e46743a6d138b1803fab6cb860af43265b42ea6"}, + {file = "coverage-7.10.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc01f57ca26269c2c706e838f6422e2a8788e41b3e3c65e2f41148212e57cd59"}, + {file = "coverage-7.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a6442c59a8ac8b85812ce33bc4d05bde3fb22321fa8294e2a5b487c3505f611b"}, + {file = "coverage-7.10.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:78a384e49f46b80fb4c901d52d92abe098e78768ed829c673fbb53c498bef73a"}, + {file = "coverage-7.10.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5e1e9802121405ede4b0133aa4340ad8186a1d2526de5b7c3eca519db7bb89fb"}, + {file = "coverage-7.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d41213ea25a86f69efd1575073d34ea11aabe075604ddf3d148ecfec9e1e96a1"}, + {file = "coverage-7.10.7-cp312-cp312-win32.whl", hash = "sha256:77eb4c747061a6af8d0f7bdb31f1e108d172762ef579166ec84542f711d90256"}, + {file = "coverage-7.10.7-cp312-cp312-win_amd64.whl", hash = "sha256:f51328ffe987aecf6d09f3cd9d979face89a617eacdaea43e7b3080777f647ba"}, + {file = "coverage-7.10.7-cp312-cp312-win_arm64.whl", hash = "sha256:bda5e34f8a75721c96085903c6f2197dc398c20ffd98df33f866a9c8fd95f4bf"}, + {file = "coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:981a651f543f2854abd3b5fcb3263aac581b18209be49863ba575de6edf4c14d"}, + {file = "coverage-7.10.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:73ab1601f84dc804f7812dc297e93cd99381162da39c47040a827d4e8dafe63b"}, + {file = "coverage-7.10.7-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a8b6f03672aa6734e700bbcd65ff050fd19cddfec4b031cc8cf1c6967de5a68e"}, + {file = "coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10b6ba00ab1132a0ce4428ff68cf50a25efd6840a42cdf4239c9b99aad83be8b"}, + {file = "coverage-7.10.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c79124f70465a150e89340de5963f936ee97097d2ef76c869708c4248c63ca49"}, + {file = "coverage-7.10.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:69212fbccdbd5b0e39eac4067e20a4a5256609e209547d86f740d68ad4f04911"}, + {file = "coverage-7.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7ea7c6c9d0d286d04ed3541747e6597cbe4971f22648b68248f7ddcd329207f0"}, + {file = "coverage-7.10.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b9be91986841a75042b3e3243d0b3cb0b2434252b977baaf0cd56e960fe1e46f"}, + {file = "coverage-7.10.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b281d5eca50189325cfe1f365fafade89b14b4a78d9b40b05ddd1fc7d2a10a9c"}, + {file = "coverage-7.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:99e4aa63097ab1118e75a848a28e40d68b08a5e19ce587891ab7fd04475e780f"}, + {file = "coverage-7.10.7-cp313-cp313-win32.whl", hash = "sha256:dc7c389dce432500273eaf48f410b37886be9208b2dd5710aaf7c57fd442c698"}, + {file = "coverage-7.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:cac0fdca17b036af3881a9d2729a850b76553f3f716ccb0360ad4dbc06b3b843"}, + {file = "coverage-7.10.7-cp313-cp313-win_arm64.whl", hash = "sha256:4b6f236edf6e2f9ae8fcd1332da4e791c1b6ba0dc16a2dc94590ceccb482e546"}, + {file = "coverage-7.10.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a0ec07fd264d0745ee396b666d47cef20875f4ff2375d7c4f58235886cc1ef0c"}, + {file = "coverage-7.10.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd5e856ebb7bfb7672b0086846db5afb4567a7b9714b8a0ebafd211ec7ce6a15"}, + {file = "coverage-7.10.7-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f57b2a3c8353d3e04acf75b3fed57ba41f5c0646bbf1d10c7c282291c97936b4"}, + {file = "coverage-7.10.7-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ef2319dd15a0b009667301a3f84452a4dc6fddfd06b0c5c53ea472d3989fbf0"}, + {file = "coverage-7.10.7-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83082a57783239717ceb0ad584de3c69cf581b2a95ed6bf81ea66034f00401c0"}, + {file = "coverage-7.10.7-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:50aa94fb1fb9a397eaa19c0d5ec15a5edd03a47bf1a3a6111a16b36e190cff65"}, + {file = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2120043f147bebb41c85b97ac45dd173595ff14f2a584f2963891cbcc3091541"}, + {file = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2fafd773231dd0378fdba66d339f84904a8e57a262f583530f4f156ab83863e6"}, + {file = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:0b944ee8459f515f28b851728ad224fa2d068f1513ef6b7ff1efafeb2185f999"}, + {file = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4b583b97ab2e3efe1b3e75248a9b333bd3f8b0b1b8e5b45578e05e5850dfb2c2"}, + {file = "coverage-7.10.7-cp313-cp313t-win32.whl", hash = "sha256:2a78cd46550081a7909b3329e2266204d584866e8d97b898cd7fb5ac8d888b1a"}, + {file = "coverage-7.10.7-cp313-cp313t-win_amd64.whl", hash = "sha256:33a5e6396ab684cb43dc7befa386258acb2d7fae7f67330ebb85ba4ea27938eb"}, + {file = "coverage-7.10.7-cp313-cp313t-win_arm64.whl", hash = "sha256:86b0e7308289ddde73d863b7683f596d8d21c7d8664ce1dee061d0bcf3fbb4bb"}, + {file = "coverage-7.10.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b06f260b16ead11643a5a9f955bd4b5fd76c1a4c6796aeade8520095b75de520"}, + {file = "coverage-7.10.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:212f8f2e0612778f09c55dd4872cb1f64a1f2b074393d139278ce902064d5b32"}, + {file = "coverage-7.10.7-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3445258bcded7d4aa630ab8296dea4d3f15a255588dd535f980c193ab6b95f3f"}, + {file = "coverage-7.10.7-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb45474711ba385c46a0bfe696c695a929ae69ac636cda8f532be9e8c93d720a"}, + {file = "coverage-7.10.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:813922f35bd800dca9994c5971883cbc0d291128a5de6b167c7aa697fcf59360"}, + {file = "coverage-7.10.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:93c1b03552081b2a4423091d6fb3787265b8f86af404cff98d1b5342713bdd69"}, + {file = "coverage-7.10.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:cc87dd1b6eaf0b848eebb1c86469b9f72a1891cb42ac7adcfbce75eadb13dd14"}, + {file = "coverage-7.10.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:39508ffda4f343c35f3236fe8d1a6634a51f4581226a1262769d7f970e73bffe"}, + {file = "coverage-7.10.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:925a1edf3d810537c5a3abe78ec5530160c5f9a26b1f4270b40e62cc79304a1e"}, + {file = "coverage-7.10.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2c8b9a0636f94c43cd3576811e05b89aa9bc2d0a85137affc544ae5cb0e4bfbd"}, + {file = "coverage-7.10.7-cp314-cp314-win32.whl", hash = "sha256:b7b8288eb7cdd268b0304632da8cb0bb93fadcfec2fe5712f7b9cc8f4d487be2"}, + {file = "coverage-7.10.7-cp314-cp314-win_amd64.whl", hash = "sha256:1ca6db7c8807fb9e755d0379ccc39017ce0a84dcd26d14b5a03b78563776f681"}, + {file = "coverage-7.10.7-cp314-cp314-win_arm64.whl", hash = "sha256:097c1591f5af4496226d5783d036bf6fd6cd0cbc132e071b33861de756efb880"}, + {file = "coverage-7.10.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a62c6ef0d50e6de320c270ff91d9dd0a05e7250cac2a800b7784bae474506e63"}, + {file = "coverage-7.10.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9fa6e4dd51fe15d8738708a973470f67a855ca50002294852e9571cdbd9433f2"}, + {file = "coverage-7.10.7-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8fb190658865565c549b6b4706856d6a7b09302c797eb2cf8e7fe9dabb043f0d"}, + {file = "coverage-7.10.7-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:affef7c76a9ef259187ef31599a9260330e0335a3011732c4b9effa01e1cd6e0"}, + {file = "coverage-7.10.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e16e07d85ca0cf8bafe5f5d23a0b850064e8e945d5677492b06bbe6f09cc699"}, + {file = "coverage-7.10.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03ffc58aacdf65d2a82bbeb1ffe4d01ead4017a21bfd0454983b88ca73af94b9"}, + {file = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1b4fd784344d4e52647fd7857b2af5b3fbe6c239b0b5fa63e94eb67320770e0f"}, + {file = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0ebbaddb2c19b71912c6f2518e791aa8b9f054985a0769bdb3a53ebbc765c6a1"}, + {file = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:a2d9a3b260cc1d1dbdb1c582e63ddcf5363426a1a68faa0f5da28d8ee3c722a0"}, + {file = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a3cc8638b2480865eaa3926d192e64ce6c51e3d29c849e09d5b4ad95efae5399"}, + {file = "coverage-7.10.7-cp314-cp314t-win32.whl", hash = "sha256:67f8c5cbcd3deb7a60b3345dffc89a961a484ed0af1f6f73de91705cc6e31235"}, + {file = "coverage-7.10.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e1ed71194ef6dea7ed2d5cb5f7243d4bcd334bfb63e59878519be558078f848d"}, + {file = "coverage-7.10.7-cp314-cp314t-win_arm64.whl", hash = "sha256:7fe650342addd8524ca63d77b2362b02345e5f1a093266787d210c70a50b471a"}, + {file = "coverage-7.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fff7b9c3f19957020cac546c70025331113d2e61537f6e2441bc7657913de7d3"}, + {file = "coverage-7.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bc91b314cef27742da486d6839b677b3f2793dfe52b51bbbb7cf736d5c29281c"}, + {file = "coverage-7.10.7-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:567f5c155eda8df1d3d439d40a45a6a5f029b429b06648235f1e7e51b522b396"}, + {file = "coverage-7.10.7-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2af88deffcc8a4d5974cf2d502251bc3b2db8461f0b66d80a449c33757aa9f40"}, + {file = "coverage-7.10.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7315339eae3b24c2d2fa1ed7d7a38654cba34a13ef19fbcb9425da46d3dc594"}, + {file = "coverage-7.10.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:912e6ebc7a6e4adfdbb1aec371ad04c68854cd3bf3608b3514e7ff9062931d8a"}, + {file = "coverage-7.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f49a05acd3dfe1ce9715b657e28d138578bc40126760efb962322c56e9ca344b"}, + {file = "coverage-7.10.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cce2109b6219f22ece99db7644b9622f54a4e915dad65660ec435e89a3ea7cc3"}, + {file = "coverage-7.10.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:f3c887f96407cea3916294046fc7dab611c2552beadbed4ea901cbc6a40cc7a0"}, + {file = "coverage-7.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:635adb9a4507c9fd2ed65f39693fa31c9a3ee3a8e6dc64df033e8fdf52a7003f"}, + {file = "coverage-7.10.7-cp39-cp39-win32.whl", hash = "sha256:5a02d5a850e2979b0a014c412573953995174743a3f7fa4ea5a6e9a3c5617431"}, + {file = "coverage-7.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:c134869d5ffe34547d14e174c866fd8fe2254918cc0a95e99052903bc1543e07"}, + {file = "coverage-7.10.7-py3-none-any.whl", hash = "sha256:f7941f6f2fe6dd6807a1208737b8a0cbcf1cc6d7b07d24998ad2d63590868260"}, + {file = "coverage-7.10.7.tar.gz", hash = "sha256:f4ab143ab113be368a3e9b795f9cd7906c5ef407d6173fe9675a902e1fffc239"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version < \"3.11\"" +files = [ + {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, + {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + +[package.extras] +test = ["pytest (>=6)"] [[package]] name = "ghp-import" @@ -94,6 +233,18 @@ perf = ["ipython"] test = ["flufl.flake8", "importlib_resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] type = ["pytest-mypy"] +[[package]] +name = "iniconfig" +version = "2.1.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, +] + [[package]] name = "jinja2" version = "3.1.6" @@ -305,6 +456,37 @@ docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-a test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] type = ["mypy (>=1.14.1)"] +[[package]] +name = "pluggy" +version = "1.6.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["coverage", "pytest", "pytest-benchmark"] + +[[package]] +name = "pygments" +version = "2.19.2" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, + {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + [[package]] name = "pyproject-hooks" version = "1.2.0" @@ -317,6 +499,49 @@ files = [ {file = "pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8"}, ] +[[package]] +name = "pytest" +version = "8.4.2" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79"}, + {file = "pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01"}, +] + +[package.dependencies] +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} +iniconfig = ">=1" +packaging = ">=20" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "5.0.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, + {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -338,7 +563,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -429,7 +654,7 @@ description = "A lil' TOML parser" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version < \"3.11\"" +markers = "python_full_version <= \"3.11.0a6\"" files = [ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, @@ -465,6 +690,19 @@ files = [ {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] +[[package]] +name = "typing-extensions" +version = "4.15.0" +description = "Backported and Experimental Type Hints for Python 3.9+" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version < \"3.11\"" +files = [ + {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, + {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, +] + [[package]] name = "watchdog" version = "6.0.0" @@ -532,4 +770,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.9.0" -content-hash = "422197e8dc3ea714851167e3ff3f17077c17ee843da57b3cd6acc1d5ccef2149" +content-hash = "dd4df3f4b299128349a919529cdc4aa32cda9d903ea9d5840049eb1027e01d5b" diff --git a/pyproject.toml b/pyproject.toml index 3c09683..ce6abdf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,10 +48,19 @@ mkdocs = { version = ">=1.6.1,<2.0.0" } [tool.poetry.group.dev.dependencies] build = "^1.3.0" +pytest = "^8.0" +pytest-cov = "^5.0" +pyyaml = "^6.0" [build-system] requires = ["poetry-core>=2.0.0,<3.0.0"] build-backend = "poetry.core.masonry.api" [tool.poetry.plugins."mkdocs.themes"] -dracula = "mkdocs_dracula_theme" \ No newline at end of file +dracula = "mkdocs_dracula_theme" + +[tool.pytest.ini_options] +testpaths = ["tests"] +python_files = ["test_*.py"] +python_classes = ["Test*"] +python_functions = ["test_*"] \ No newline at end of file diff --git a/template/assets/css/mkdocs.css b/template/assets/css/mkdocs.css index 782342c..38e047b 100644 --- a/template/assets/css/mkdocs.css +++ b/template/assets/css/mkdocs.css @@ -476,4 +476,95 @@ img, svg { .drac-input-search { margin-top: 2px; width: 170px; -} \ No newline at end of file +} + +/* ============================================================= + Admonitions + ============================================================= */ + +.admonition { + border-left: 4px solid var(--purple); + border-radius: 0.5rem; + background: var(--purple-transparent); + padding: 0.75rem 1rem; + margin: 1.25rem 0; + overflow: hidden; +} + +.admonition p:last-child { + margin-bottom: 0; +} + +.admonition-title { + font-weight: 700; + margin: -0.75rem -1rem 0.75rem -1rem; + padding: 0.5rem 1rem; + display: flex; + align-items: center; +} + +.admonition-title::before { + font-family: FontAwesome; + margin-right: 0.5rem; + content: "\f040"; +} + +/* note */ +.admonition.note { border-color: var(--purple); background: var(--purple-transparent); } +.admonition.note .admonition-title { background: rgba(149,128,255,.15); color: var(--purple); } +.admonition.note .admonition-title::before { content: "\f040"; } + +/* abstract / summary / tldr */ +.admonition.abstract,.admonition.summary,.admonition.tldr { border-color: var(--cyan); background: var(--cyan-transparent); } +.admonition.abstract .admonition-title,.admonition.summary .admonition-title,.admonition.tldr .admonition-title { background: rgba(128,255,234,.15); color: var(--cyan); } +.admonition.abstract .admonition-title::before,.admonition.summary .admonition-title::before,.admonition.tldr .admonition-title::before { content: "\f0ea"; } + +/* info */ +.admonition.info { border-color: var(--cyan); background: var(--cyan-transparent); } +.admonition.info .admonition-title { background: rgba(128,255,234,.15); color: var(--cyan); } +.admonition.info .admonition-title::before { content: "\f05a"; } + +/* tip / hint / important */ +.admonition.tip,.admonition.hint,.admonition.important { border-color: var(--green); background: var(--green-transparent); } +.admonition.tip .admonition-title,.admonition.hint .admonition-title,.admonition.important .admonition-title { background: rgba(138,255,128,.15); color: var(--green); } +.admonition.tip .admonition-title::before,.admonition.hint .admonition-title::before,.admonition.important .admonition-title::before { content: "\f0eb"; } + +/* success / check / done */ +.admonition.success,.admonition.check,.admonition.done { border-color: var(--green); background: var(--green-transparent); } +.admonition.success .admonition-title,.admonition.check .admonition-title,.admonition.done .admonition-title { background: rgba(138,255,128,.15); color: var(--green); } +.admonition.success .admonition-title::before,.admonition.check .admonition-title::before,.admonition.done .admonition-title::before { content: "\f058"; } + +/* question / help / faq */ +.admonition.question,.admonition.help,.admonition.faq { border-color: var(--yellow); background: var(--yellow-transparent); } +.admonition.question .admonition-title,.admonition.help .admonition-title,.admonition.faq .admonition-title { background: rgba(255,255,128,.15); color: var(--yellow); } +.admonition.question .admonition-title::before,.admonition.help .admonition-title::before,.admonition.faq .admonition-title::before { content: "\f059"; } + +/* warning / caution / attention */ +.admonition.warning,.admonition.caution,.admonition.attention { border-color: var(--orange); background: var(--orange-transparent); } +.admonition.warning .admonition-title,.admonition.caution .admonition-title,.admonition.attention .admonition-title { background: rgba(255,202,128,.15); color: var(--orange); } +.admonition.warning .admonition-title::before,.admonition.caution .admonition-title::before,.admonition.attention .admonition-title::before { content: "\f071"; } + +/* failure / fail / missing */ +.admonition.failure,.admonition.fail,.admonition.missing { border-color: var(--pink); background: var(--pink-transparent); } +.admonition.failure .admonition-title,.admonition.fail .admonition-title,.admonition.missing .admonition-title { background: rgba(255,128,191,.15); color: var(--pink); } +.admonition.failure .admonition-title::before,.admonition.fail .admonition-title::before,.admonition.missing .admonition-title::before { content: "\f057"; } + +/* danger / error */ +.admonition.danger,.admonition.error { border-color: var(--red); background: var(--red-transparent); } +.admonition.danger .admonition-title,.admonition.error .admonition-title { background: rgba(255,149,128,.15); color: var(--red); } +.admonition.danger .admonition-title::before,.admonition.error .admonition-title::before { content: "\f0e7"; } + +/* bug */ +.admonition.bug { border-color: var(--red); background: var(--red-transparent); } +.admonition.bug .admonition-title { background: rgba(255,149,128,.15); color: var(--red); } +.admonition.bug .admonition-title::before { content: "\f188"; } + +/* example */ +.admonition.example { border-color: var(--purple); background: var(--purple-transparent); } +.admonition.example .admonition-title { background: rgba(149,128,255,.15); color: var(--purple); } +.admonition.example .admonition-title::before { content: "\f03a"; } + +/* quote / cite */ +.admonition.quote,.admonition.cite { border-color: var(--grey); background: rgba(65,69,88,.2); } +.admonition.quote .admonition-title,.admonition.cite .admonition-title { background: rgba(65,69,88,.3); color: var(--white); } +.admonition.quote .admonition-title::before,.admonition.cite .admonition-title::before { content: "\f10d"; } \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..c8d70a8 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,5 @@ +from pathlib import Path + +THEME_DIR = Path(__file__).parent.parent / "mkdocs_dracula_theme" +CSS_SOURCE = Path(__file__).parent.parent / "template" / "assets" / "css" / "mkdocs.css" +CSS_MIN = THEME_DIR / "assets" / "css" / "mkdocs.min.css" diff --git a/tests/test_admonitions.py b/tests/test_admonitions.py new file mode 100644 index 0000000..80d4b15 --- /dev/null +++ b/tests/test_admonitions.py @@ -0,0 +1,155 @@ +"""Tests for PR #33 — admonition styles with Dracula colors and Font Awesome icons.""" +import re +from pathlib import Path + +CSS_SOURCE = Path(__file__).parent.parent / "template" / "assets" / "css" / "mkdocs.css" +CSS_MIN = Path(__file__).parent.parent / "mkdocs_dracula_theme" / "assets" / "css" / "mkdocs.min.css" + +ADMONITION_TYPES = [ + "note", + "abstract", "summary", "tldr", + "info", + "tip", "hint", "important", + "success", "check", "done", + "question", "help", "faq", + "warning", "caution", "attention", + "failure", "fail", "missing", + "danger", "error", + "bug", + "example", + "quote", "cite", +] + +# Expected Font Awesome 4.7 icon codepoints per type +EXPECTED_ICONS = { + "note": r"\f040", + "abstract": r"\f0ea", "summary": r"\f0ea", "tldr": r"\f0ea", + "info": r"\f05a", + "tip": r"\f0eb", "hint": r"\f0eb", "important": r"\f0eb", + "success": r"\f058", "check": r"\f058", "done": r"\f058", + "question": r"\f059", "help": r"\f059", "faq": r"\f059", + "warning": r"\f071", "caution": r"\f071", "attention": r"\f071", + "failure": r"\f057", "fail": r"\f057", "missing": r"\f057", + "danger": r"\f0e7", "error": r"\f0e7", + "bug": r"\f188", + "example": r"\f03a", + "quote": r"\f10d", "cite": r"\f10d", +} + +# Expected Dracula CSS variable per admonition type +EXPECTED_COLORS = { + "note": "--purple", "example": "--purple", + "abstract": "--cyan", "summary": "--cyan", + "tldr": "--cyan", "info": "--cyan", + "tip": "--green", "hint": "--green", "important": "--green", + "success": "--green", "check": "--green", "done": "--green", + "question": "--yellow", "help": "--yellow", "faq": "--yellow", + "warning": "--orange", "caution": "--orange", "attention": "--orange", + "failure": "--pink", "fail": "--pink", "missing": "--pink", + "danger": "--red", "error": "--red", "bug": "--red", + "quote": "--grey", "cite": "--grey", +} + + +class TestAdmonitionCoverage: + def test_source_css_covers_all_types(self): + """Source CSS must define rules for every MkDocs admonition type.""" + content = CSS_SOURCE.read_text() + missing = [t for t in ADMONITION_TYPES if f".admonition.{t}" not in content] + assert not missing, f"Missing admonition rules in source CSS: {missing}" + + def test_min_css_covers_all_types(self): + """Minified CSS must define rules for every MkDocs admonition type.""" + content = CSS_MIN.read_text() + missing = [t for t in ADMONITION_TYPES if f".admonition.{t}" not in content] + assert not missing, f"Missing admonition rules in minified CSS: {missing}" + + def test_source_and_min_in_sync(self): + """Source and minified CSS must cover the exact same set of admonition types.""" + source = CSS_SOURCE.read_text() + minified = CSS_MIN.read_text() + for t in ADMONITION_TYPES: + in_src = f".admonition.{t}" in source + in_min = f".admonition.{t}" in minified + assert in_src == in_min, ( + f".admonition.{t}: source={in_src}, minified={in_min} — files are out of sync" + ) + + +class TestAdmonitionIcons: + def test_tip_uses_lightbulb_not_fire_in_source(self): + """tip/hint/important must use fa-lightbulb-o (\\f0eb), not fa-fire (\\f06d).""" + content = CSS_SOURCE.read_text() + assert r"\f0eb" in content, r"Source CSS missing lightbulb icon (\f0eb) for tip/hint/important" + assert r"\f06d" not in content, r"Source CSS must not use fire icon (\f06d)" + + def test_tip_uses_lightbulb_not_fire_in_min(self): + """Minified CSS: tip/hint/important must use fa-lightbulb-o (\\f0eb).""" + content = CSS_MIN.read_text() + assert r"\f0eb" in content, r"Minified CSS missing lightbulb icon (\f0eb)" + assert r"\f06d" not in content, r"Minified CSS must not use fire icon (\f06d)" + + def test_all_icon_codepoints_present_in_source(self): + """Each admonition type must reference its expected Font Awesome codepoint.""" + content = CSS_SOURCE.read_text() + seen_codepoints = set() + for admonition_type, codepoint in EXPECTED_ICONS.items(): + if codepoint not in seen_codepoints: + assert codepoint in content, ( + f"Icon codepoint {codepoint} for .admonition.{admonition_type} " + f"not found in source CSS" + ) + seen_codepoints.add(codepoint) + + +class TestAdmonitionColors: + def test_source_css_uses_dracula_variables(self): + """Admonition styles must use CSS variables, not hardcoded hex values.""" + content = CSS_SOURCE.read_text() + # Extract only the admonition section + start = content.find(".admonition {") + assert start != -1, "Admonition base rule not found" + admonition_section = content[start:] + # Must not contain hex colors in the admonition section + assert not re.search(r":\s*#[0-9a-fA-F]{3,6}", admonition_section), \ + "Admonition styles must use CSS variables (var(--color)), not hardcoded hex values" + + def test_expected_color_variables_present(self): + """Each admonition type must reference its expected Dracula color variable.""" + content = CSS_SOURCE.read_text() + for admonition_type, color_var in EXPECTED_COLORS.items(): + pattern = rf"\.admonition\.{admonition_type}[^{{]*\{{[^}}]*{re.escape(color_var)}" + assert re.search(pattern, content), ( + f".admonition.{admonition_type} should reference {color_var}" + ) + + +class TestMinifiedCSSFormat: + def test_admonition_section_has_no_comments(self): + """The admonition block in mkdocs.min.css must not contain CSS comments.""" + content = CSS_MIN.read_text() + admonition_start = content.find(".admonition{") + assert admonition_start != -1, "Admonition CSS not found in minified file" + admonition_section = content[admonition_start:] + assert "/*" not in admonition_section, \ + "Minified CSS must not contain comments — strip them before appending to .min.css" + + def test_admonition_section_has_no_indentation(self): + """The admonition block in mkdocs.min.css must not contain indented lines.""" + content = CSS_MIN.read_text() + admonition_start = content.find(".admonition{") + assert admonition_start != -1 + admonition_section = content[admonition_start:] + assert "\n " not in admonition_section, \ + "Minified CSS must not contain indented lines" + + def test_admonition_uses_shorthand_values(self): + """Minified CSS should use shorthand values (e.g. .5rem not 0.5rem).""" + content = CSS_MIN.read_text() + admonition_start = content.find(".admonition{") + assert admonition_start != -1 + admonition_section = content[admonition_start:] + assert "0.5rem" not in admonition_section, \ + "Minified CSS should use .5rem instead of 0.5rem" + assert "0.75rem" not in admonition_section, \ + "Minified CSS should use .75rem instead of 0.75rem"