diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dc9a2a4..a79fa61 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,11 +12,11 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] - python-version: [3.9] + python-version: [3.11] poetry-version: [1.4.2] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: @@ -33,6 +33,11 @@ jobs: brew install cairo brew install pango brew install gdal + # https://github.com/Kozea/CairoSVG/issues/354#issuecomment-1160552256 + sudo ln -s /opt/homebrew/lib/libcairo* . + sudo ln -s /opt/homebrew/lib/libpango* . + sudo ln -s /opt/homebrew/lib/libgobject* . + sudo ln -s /opt/homebrew/lib/libglib* . - name: Install System Dependencies (ubuntu) if: matrix.os == 'ubuntu-latest' run: | diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index baf17a1..f57dc9f 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -5,15 +5,15 @@ on: pull_request: jobs: - build: + pytest: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.9] + python-version: [3.11] poetry-version: [1.4.2] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: @@ -39,7 +39,7 @@ jobs: run: | poetry run pytest --cov --cov-report xml - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: - files: ./coverage.xml fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/map_engraver/canvas/canvas.py b/map_engraver/canvas/canvas.py index bd089fc..0f486e1 100644 --- a/map_engraver/canvas/canvas.py +++ b/map_engraver/canvas/canvas.py @@ -33,12 +33,20 @@ def __init__( width, height ) + # In version 1.5 the document units are no longer easy to read via + # regular expressions. 1.4 uses the old format that has 'MediaBox' + # in the PDF output. + surface.restrict_to_version(cairo.PDF_VERSION_1_4) elif surface_type == 'svg': surface = cairo.SVGSurface( self.path_as_posix, width, height ) + # In cairo-1.17.8 the default document unit was changed to + # cairo.SVG_UNIT_USER, which can be ambiguous. Here we reset it + # back to cairo.SVG_UNIT_PT like older versions of cairo. + surface.set_document_unit(cairo.SVG_UNIT_PT) elif surface_type == 'png': surface = cairo.ImageSurface( cairo.FORMAT_ARGB32, diff --git a/poetry.lock b/poetry.lock index c10f056..8a2709b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,13 +1,15 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. [[package]] name = "cairocffi" -version = "1.5.1" +version = "1.7.1" description = "cffi-based cairo bindings for Python" +category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "cairocffi-1.5.1.tar.gz", hash = "sha256:071ab7b72e3533300b0bfd55a52056b4ffdc1ed6e656779e2aced9b709b8a295"}, + {file = "cairocffi-1.7.1-py3-none-any.whl", hash = "sha256:9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f"}, + {file = "cairocffi-1.7.1.tar.gz", hash = "sha256:2e48ee864884ec4a3a34bfa8c9ab9999f688286eb714a15a43ec9d068c36557b"}, ] [package.dependencies] @@ -15,13 +17,14 @@ cffi = ">=1.1.0" [package.extras] doc = ["sphinx", "sphinx_rtd_theme"] -test = ["flake8", "isort", "numpy", "pikepdf", "pytest"] -xcb = ["xcffib (>=0.3.2)"] +test = ["numpy", "pikepdf", "pytest", "ruff"] +xcb = ["xcffib (>=1.4.0)"] [[package]] name = "cairosvg" version = "2.7.0" description = "A Simple SVG Converter based on Cairo" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -44,6 +47,7 @@ test = ["flake8", "isort", "pytest"] name = "certifi" version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -55,6 +59,7 @@ files = [ name = "cffi" version = "1.15.1" description = "Foreign Function Interface for Python calling C code." +category = "main" optional = false python-versions = "*" files = [ @@ -131,6 +136,7 @@ pycparser = "*" name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -140,63 +146,64 @@ files = [ [[package]] name = "coverage" -version = "7.3.1" +version = "7.5.4" description = "Code coverage measurement for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cd0f7429ecfd1ff597389907045ff209c8fdb5b013d38cfa7c60728cb484b6e3"}, - {file = "coverage-7.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:966f10df9b2b2115da87f50f6a248e313c72a668248be1b9060ce935c871f276"}, - {file = "coverage-7.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0575c37e207bb9b98b6cf72fdaaa18ac909fb3d153083400c2d48e2e6d28bd8e"}, - {file = "coverage-7.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:245c5a99254e83875c7fed8b8b2536f040997a9b76ac4c1da5bff398c06e860f"}, - {file = "coverage-7.3.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c96dd7798d83b960afc6c1feb9e5af537fc4908852ef025600374ff1a017392"}, - {file = "coverage-7.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:de30c1aa80f30af0f6b2058a91505ea6e36d6535d437520067f525f7df123887"}, - {file = "coverage-7.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:50dd1e2dd13dbbd856ffef69196781edff26c800a74f070d3b3e3389cab2600d"}, - {file = "coverage-7.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9c0c19f70d30219113b18fe07e372b244fb2a773d4afde29d5a2f7930765136"}, - {file = "coverage-7.3.1-cp310-cp310-win32.whl", hash = "sha256:770f143980cc16eb601ccfd571846e89a5fe4c03b4193f2e485268f224ab602f"}, - {file = "coverage-7.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:cdd088c00c39a27cfa5329349cc763a48761fdc785879220d54eb785c8a38520"}, - {file = "coverage-7.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:74bb470399dc1989b535cb41f5ca7ab2af561e40def22d7e188e0a445e7639e3"}, - {file = "coverage-7.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:025ded371f1ca280c035d91b43252adbb04d2aea4c7105252d3cbc227f03b375"}, - {file = "coverage-7.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6191b3a6ad3e09b6cfd75b45c6aeeffe7e3b0ad46b268345d159b8df8d835f9"}, - {file = "coverage-7.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7eb0b188f30e41ddd659a529e385470aa6782f3b412f860ce22b2491c89b8593"}, - {file = "coverage-7.3.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c8f0df9dfd8ff745bccff75867d63ef336e57cc22b2908ee725cc552689ec8"}, - {file = "coverage-7.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7eb3cd48d54b9bd0e73026dedce44773214064be93611deab0b6a43158c3d5a0"}, - {file = "coverage-7.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ac3c5b7e75acac31e490b7851595212ed951889918d398b7afa12736c85e13ce"}, - {file = "coverage-7.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5b4ee7080878077af0afa7238df1b967f00dc10763f6e1b66f5cced4abebb0a3"}, - {file = "coverage-7.3.1-cp311-cp311-win32.whl", hash = "sha256:229c0dd2ccf956bf5aeede7e3131ca48b65beacde2029f0361b54bf93d36f45a"}, - {file = "coverage-7.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:c6f55d38818ca9596dc9019eae19a47410d5322408140d9a0076001a3dcb938c"}, - {file = "coverage-7.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5289490dd1c3bb86de4730a92261ae66ea8d44b79ed3cc26464f4c2cde581fbc"}, - {file = "coverage-7.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ca833941ec701fda15414be400c3259479bfde7ae6d806b69e63b3dc423b1832"}, - {file = "coverage-7.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd694e19c031733e446c8024dedd12a00cda87e1c10bd7b8539a87963685e969"}, - {file = "coverage-7.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aab8e9464c00da5cb9c536150b7fbcd8850d376d1151741dd0d16dfe1ba4fd26"}, - {file = "coverage-7.3.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87d38444efffd5b056fcc026c1e8d862191881143c3aa80bb11fcf9dca9ae204"}, - {file = "coverage-7.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8a07b692129b8a14ad7a37941a3029c291254feb7a4237f245cfae2de78de037"}, - {file = "coverage-7.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2829c65c8faaf55b868ed7af3c7477b76b1c6ebeee99a28f59a2cb5907a45760"}, - {file = "coverage-7.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1f111a7d85658ea52ffad7084088277135ec5f368457275fc57f11cebb15607f"}, - {file = "coverage-7.3.1-cp312-cp312-win32.whl", hash = "sha256:c397c70cd20f6df7d2a52283857af622d5f23300c4ca8e5bd8c7a543825baa5a"}, - {file = "coverage-7.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:5ae4c6da8b3d123500f9525b50bf0168023313963e0e2e814badf9000dd6ef92"}, - {file = "coverage-7.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca70466ca3a17460e8fc9cea7123c8cbef5ada4be3140a1ef8f7b63f2f37108f"}, - {file = "coverage-7.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f2781fd3cabc28278dc982a352f50c81c09a1a500cc2086dc4249853ea96b981"}, - {file = "coverage-7.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6407424621f40205bbe6325686417e5e552f6b2dba3535dd1f90afc88a61d465"}, - {file = "coverage-7.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:04312b036580ec505f2b77cbbdfb15137d5efdfade09156961f5277149f5e344"}, - {file = "coverage-7.3.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac9ad38204887349853d7c313f53a7b1c210ce138c73859e925bc4e5d8fc18e7"}, - {file = "coverage-7.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:53669b79f3d599da95a0afbef039ac0fadbb236532feb042c534fbb81b1a4e40"}, - {file = "coverage-7.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:614f1f98b84eb256e4f35e726bfe5ca82349f8dfa576faabf8a49ca09e630086"}, - {file = "coverage-7.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f1a317fdf5c122ad642db8a97964733ab7c3cf6009e1a8ae8821089993f175ff"}, - {file = "coverage-7.3.1-cp38-cp38-win32.whl", hash = "sha256:defbbb51121189722420a208957e26e49809feafca6afeef325df66c39c4fdb3"}, - {file = "coverage-7.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:f4f456590eefb6e1b3c9ea6328c1e9fa0f1006e7481179d749b3376fc793478e"}, - {file = "coverage-7.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f12d8b11a54f32688b165fd1a788c408f927b0960984b899be7e4c190ae758f1"}, - {file = "coverage-7.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f09195dda68d94a53123883de75bb97b0e35f5f6f9f3aa5bf6e496da718f0cb6"}, - {file = "coverage-7.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6601a60318f9c3945be6ea0f2a80571f4299b6801716f8a6e4846892737ebe4"}, - {file = "coverage-7.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07d156269718670d00a3b06db2288b48527fc5f36859425ff7cec07c6b367745"}, - {file = "coverage-7.3.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:636a8ac0b044cfeccae76a36f3b18264edcc810a76a49884b96dd744613ec0b7"}, - {file = "coverage-7.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5d991e13ad2ed3aced177f524e4d670f304c8233edad3210e02c465351f785a0"}, - {file = "coverage-7.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:586649ada7cf139445da386ab6f8ef00e6172f11a939fc3b2b7e7c9082052fa0"}, - {file = "coverage-7.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4aba512a15a3e1e4fdbfed2f5392ec221434a614cc68100ca99dcad7af29f3f8"}, - {file = "coverage-7.3.1-cp39-cp39-win32.whl", hash = "sha256:6bc6f3f4692d806831c136c5acad5ccedd0262aa44c087c46b7101c77e139140"}, - {file = "coverage-7.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:553d7094cb27db58ea91332e8b5681bac107e7242c23f7629ab1316ee73c4981"}, - {file = "coverage-7.3.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:220eb51f5fb38dfdb7e5d54284ca4d0cd70ddac047d750111a68ab1798945194"}, - {file = "coverage-7.3.1.tar.gz", hash = "sha256:6cb7fe1581deb67b782c153136541e20901aa312ceedaf1467dcb35255787952"}, + {file = "coverage-7.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6cfb5a4f556bb51aba274588200a46e4dd6b505fb1a5f8c5ae408222eb416f99"}, + {file = "coverage-7.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2174e7c23e0a454ffe12267a10732c273243b4f2d50d07544a91198f05c48f47"}, + {file = "coverage-7.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2214ee920787d85db1b6a0bd9da5f8503ccc8fcd5814d90796c2f2493a2f4d2e"}, + {file = "coverage-7.5.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1137f46adb28e3813dec8c01fefadcb8c614f33576f672962e323b5128d9a68d"}, + {file = "coverage-7.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b385d49609f8e9efc885790a5a0e89f2e3ae042cdf12958b6034cc442de428d3"}, + {file = "coverage-7.5.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b4a474f799456e0eb46d78ab07303286a84a3140e9700b9e154cfebc8f527016"}, + {file = "coverage-7.5.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5cd64adedf3be66f8ccee418473c2916492d53cbafbfcff851cbec5a8454b136"}, + {file = "coverage-7.5.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e564c2cf45d2f44a9da56f4e3a26b2236504a496eb4cb0ca7221cd4cc7a9aca9"}, + {file = "coverage-7.5.4-cp310-cp310-win32.whl", hash = "sha256:7076b4b3a5f6d2b5d7f1185fde25b1e54eb66e647a1dfef0e2c2bfaf9b4c88c8"}, + {file = "coverage-7.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:018a12985185038a5b2bcafab04ab833a9a0f2c59995b3cec07e10074c78635f"}, + {file = "coverage-7.5.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:db14f552ac38f10758ad14dd7b983dbab424e731588d300c7db25b6f89e335b5"}, + {file = "coverage-7.5.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3257fdd8e574805f27bb5342b77bc65578e98cbc004a92232106344053f319ba"}, + {file = "coverage-7.5.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a6612c99081d8d6134005b1354191e103ec9705d7ba2754e848211ac8cacc6b"}, + {file = "coverage-7.5.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d45d3cbd94159c468b9b8c5a556e3f6b81a8d1af2a92b77320e887c3e7a5d080"}, + {file = "coverage-7.5.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed550e7442f278af76d9d65af48069f1fb84c9f745ae249c1a183c1e9d1b025c"}, + {file = "coverage-7.5.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7a892be37ca35eb5019ec85402c3371b0f7cda5ab5056023a7f13da0961e60da"}, + {file = "coverage-7.5.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8192794d120167e2a64721d88dbd688584675e86e15d0569599257566dec9bf0"}, + {file = "coverage-7.5.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:820bc841faa502e727a48311948e0461132a9c8baa42f6b2b84a29ced24cc078"}, + {file = "coverage-7.5.4-cp311-cp311-win32.whl", hash = "sha256:6aae5cce399a0f065da65c7bb1e8abd5c7a3043da9dceb429ebe1b289bc07806"}, + {file = "coverage-7.5.4-cp311-cp311-win_amd64.whl", hash = "sha256:d2e344d6adc8ef81c5a233d3a57b3c7d5181f40e79e05e1c143da143ccb6377d"}, + {file = "coverage-7.5.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:54317c2b806354cbb2dc7ac27e2b93f97096912cc16b18289c5d4e44fc663233"}, + {file = "coverage-7.5.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:042183de01f8b6d531e10c197f7f0315a61e8d805ab29c5f7b51a01d62782747"}, + {file = "coverage-7.5.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6bb74ed465d5fb204b2ec41d79bcd28afccf817de721e8a807d5141c3426638"}, + {file = "coverage-7.5.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3d45ff86efb129c599a3b287ae2e44c1e281ae0f9a9bad0edc202179bcc3a2e"}, + {file = "coverage-7.5.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5013ed890dc917cef2c9f765c4c6a8ae9df983cd60dbb635df8ed9f4ebc9f555"}, + {file = "coverage-7.5.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1014fbf665fef86cdfd6cb5b7371496ce35e4d2a00cda501cf9f5b9e6fced69f"}, + {file = "coverage-7.5.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3684bc2ff328f935981847082ba4fdc950d58906a40eafa93510d1b54c08a66c"}, + {file = "coverage-7.5.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:581ea96f92bf71a5ec0974001f900db495488434a6928a2ca7f01eee20c23805"}, + {file = "coverage-7.5.4-cp312-cp312-win32.whl", hash = "sha256:73ca8fbc5bc622e54627314c1a6f1dfdd8db69788f3443e752c215f29fa87a0b"}, + {file = "coverage-7.5.4-cp312-cp312-win_amd64.whl", hash = "sha256:cef4649ec906ea7ea5e9e796e68b987f83fa9a718514fe147f538cfeda76d7a7"}, + {file = "coverage-7.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdd31315fc20868c194130de9ee6bfd99755cc9565edff98ecc12585b90be882"}, + {file = "coverage-7.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:02ff6e898197cc1e9fa375581382b72498eb2e6d5fc0b53f03e496cfee3fac6d"}, + {file = "coverage-7.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d05c16cf4b4c2fc880cb12ba4c9b526e9e5d5bb1d81313d4d732a5b9fe2b9d53"}, + {file = "coverage-7.5.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5986ee7ea0795a4095ac4d113cbb3448601efca7f158ec7f7087a6c705304e4"}, + {file = "coverage-7.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5df54843b88901fdc2f598ac06737f03d71168fd1175728054c8f5a2739ac3e4"}, + {file = "coverage-7.5.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ab73b35e8d109bffbda9a3e91c64e29fe26e03e49addf5b43d85fc426dde11f9"}, + {file = "coverage-7.5.4-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:aea072a941b033813f5e4814541fc265a5c12ed9720daef11ca516aeacd3bd7f"}, + {file = "coverage-7.5.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:16852febd96acd953b0d55fc842ce2dac1710f26729b31c80b940b9afcd9896f"}, + {file = "coverage-7.5.4-cp38-cp38-win32.whl", hash = "sha256:8f894208794b164e6bd4bba61fc98bf6b06be4d390cf2daacfa6eca0a6d2bb4f"}, + {file = "coverage-7.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:e2afe743289273209c992075a5a4913e8d007d569a406ffed0bd080ea02b0633"}, + {file = "coverage-7.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b95c3a8cb0463ba9f77383d0fa8c9194cf91f64445a63fc26fb2327e1e1eb088"}, + {file = "coverage-7.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3d7564cc09dd91b5a6001754a5b3c6ecc4aba6323baf33a12bd751036c998be4"}, + {file = "coverage-7.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44da56a2589b684813f86d07597fdf8a9c6ce77f58976727329272f5a01f99f7"}, + {file = "coverage-7.5.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e16f3d6b491c48c5ae726308e6ab1e18ee830b4cdd6913f2d7f77354b33f91c8"}, + {file = "coverage-7.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbc5958cb471e5a5af41b0ddaea96a37e74ed289535e8deca404811f6cb0bc3d"}, + {file = "coverage-7.5.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a04e990a2a41740b02d6182b498ee9796cf60eefe40cf859b016650147908029"}, + {file = "coverage-7.5.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ddbd2f9713a79e8e7242d7c51f1929611e991d855f414ca9996c20e44a895f7c"}, + {file = "coverage-7.5.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b1ccf5e728ccf83acd313c89f07c22d70d6c375a9c6f339233dcf792094bcbf7"}, + {file = "coverage-7.5.4-cp39-cp39-win32.whl", hash = "sha256:56b4eafa21c6c175b3ede004ca12c653a88b6f922494b023aeb1e836df953ace"}, + {file = "coverage-7.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:65e528e2e921ba8fd67d9055e6b9f9e34b21ebd6768ae1c1723f4ea6ace1234d"}, + {file = "coverage-7.5.4-pp38.pp39.pp310-none-any.whl", hash = "sha256:79b356f3dd5b26f3ad23b35c75dbdaf1f9e2450b6bcefc6d0825ea0aa3f86ca5"}, + {file = "coverage-7.5.4.tar.gz", hash = "sha256:a44963520b069e12789d0faea4e9fdb1e410cdc4aab89d94f7f55cbb7fef0353"}, ] [package.dependencies] @@ -209,6 +216,7 @@ toml = ["tomli"] name = "cssselect2" version = "0.7.0" description = "CSS selectors for Python ElementTree" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -228,6 +236,7 @@ test = ["flake8", "isort", "pytest"] name = "defusedxml" version = "0.7.1" description = "XML bomb protection for Python stdlib modules" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -239,6 +248,7 @@ files = [ name = "exceptiongroup" version = "1.1.1" description = "Backport of PEP 654 (exception groups)" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -251,28 +261,30 @@ test = ["pytest (>=6)"] [[package]] name = "flake8" -version = "6.1.0" +version = "7.1.0" description = "the modular source code checker: pep8 pyflakes and co" +category = "dev" optional = false python-versions = ">=3.8.1" files = [ - {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"}, - {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"}, + {file = "flake8-7.1.0-py2.py3-none-any.whl", hash = "sha256:2e416edcc62471a64cea09353f4e7bdba32aeb079b6e360554c659a122b1bc6a"}, + {file = "flake8-7.1.0.tar.gz", hash = "sha256:48a07b626b55236e0fb4784ee69a465fbf59d79eec1f5b4785c3d3bc57d17aa5"}, ] [package.dependencies] mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.11.0,<2.12.0" -pyflakes = ">=3.1.0,<3.2.0" +pycodestyle = ">=2.12.0,<2.13.0" +pyflakes = ">=3.2.0,<3.3.0" [[package]] name = "gdal" -version = "3.4.3" +version = "3.8.4" description = "GDAL: Geospatial Data Abstraction Library" +category = "dev" optional = false python-versions = ">=3.6.0" files = [ - {file = "GDAL-3.4.3.tar.gz", hash = "sha256:f4f4b0bb34073b164c5a05a1b0eb44af47349e5606eb7b75244c2167ac462f36"}, + {file = "GDAL-3.8.4.tar.gz", hash = "sha256:7c51e0ae7a7ccf43ad9e4bf435176baa9276653dfa16fd167c3632f6e7275207"}, ] [package.extras] @@ -282,6 +294,7 @@ numpy = ["numpy (>1.0.0)"] name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -293,6 +306,7 @@ files = [ name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -304,6 +318,7 @@ files = [ name = "numpy" version = "1.24.3" description = "Fundamental package for array computing in Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -341,6 +356,7 @@ files = [ name = "packaging" version = "23.1" description = "Core utilities for Python packages" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -352,6 +368,7 @@ files = [ name = "pangocairocffi" version = "0.7.0" description = "CFFI-based pango-cairo bindings for Python" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -365,12 +382,13 @@ pangocffi = ">=0.11.0" [[package]] name = "pangocffi" -version = "0.11.0" +version = "0.13.0" description = "CFFI-based pango bindings for Python" +category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pangocffi-0.11.0.tar.gz", hash = "sha256:ef02ff5cad2d729d8b55cb54d1bfc57a1ea201278f6e979c4f8ea1f66bcfc64e"}, + {file = "pangocffi-0.13.0.tar.gz", hash = "sha256:5dbd440c39c8e01d8c675316837029013488a5bf1b11527133721f65bb14b7b6"}, ] [package.dependencies] @@ -378,80 +396,101 @@ cffi = ">=1.1.0" [[package]] name = "pillow" -version = "10.0.1" +version = "10.3.0" description = "Python Imaging Library (Fork)" +category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "Pillow-10.0.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:8f06be50669087250f319b706decf69ca71fdecd829091a37cc89398ca4dc17a"}, - {file = "Pillow-10.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:50bd5f1ebafe9362ad622072a1d2f5850ecfa44303531ff14353a4059113b12d"}, - {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6a90167bcca1216606223a05e2cf991bb25b14695c518bc65639463d7db722d"}, - {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f11c9102c56ffb9ca87134bd025a43d2aba3f1155f508eff88f694b33a9c6d19"}, - {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:186f7e04248103482ea6354af6d5bcedb62941ee08f7f788a1c7707bc720c66f"}, - {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:0462b1496505a3462d0f35dc1c4d7b54069747d65d00ef48e736acda2c8cbdff"}, - {file = "Pillow-10.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d889b53ae2f030f756e61a7bff13684dcd77e9af8b10c6048fb2c559d6ed6eaf"}, - {file = "Pillow-10.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:552912dbca585b74d75279a7570dd29fa43b6d93594abb494ebb31ac19ace6bd"}, - {file = "Pillow-10.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:787bb0169d2385a798888e1122c980c6eff26bf941a8ea79747d35d8f9210ca0"}, - {file = "Pillow-10.0.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:fd2a5403a75b54661182b75ec6132437a181209b901446ee5724b589af8edef1"}, - {file = "Pillow-10.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2d7e91b4379f7a76b31c2dda84ab9e20c6220488e50f7822e59dac36b0cd92b1"}, - {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19e9adb3f22d4c416e7cd79b01375b17159d6990003633ff1d8377e21b7f1b21"}, - {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93139acd8109edcdeffd85e3af8ae7d88b258b3a1e13a038f542b79b6d255c54"}, - {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:92a23b0431941a33242b1f0ce6c88a952e09feeea9af4e8be48236a68ffe2205"}, - {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cbe68deb8580462ca0d9eb56a81912f59eb4542e1ef8f987405e35a0179f4ea2"}, - {file = "Pillow-10.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:522ff4ac3aaf839242c6f4e5b406634bfea002469656ae8358644fc6c4856a3b"}, - {file = "Pillow-10.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:84efb46e8d881bb06b35d1d541aa87f574b58e87f781cbba8d200daa835b42e1"}, - {file = "Pillow-10.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:898f1d306298ff40dc1b9ca24824f0488f6f039bc0e25cfb549d3195ffa17088"}, - {file = "Pillow-10.0.1-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:bcf1207e2f2385a576832af02702de104be71301c2696d0012b1b93fe34aaa5b"}, - {file = "Pillow-10.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d6c9049c6274c1bb565021367431ad04481ebb54872edecfcd6088d27edd6ed"}, - {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28444cb6ad49726127d6b340217f0627abc8732f1194fd5352dec5e6a0105635"}, - {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de596695a75496deb3b499c8c4f8e60376e0516e1a774e7bc046f0f48cd620ad"}, - {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:2872f2d7846cf39b3dbff64bc1104cc48c76145854256451d33c5faa55c04d1a"}, - {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4ce90f8a24e1c15465048959f1e94309dfef93af272633e8f37361b824532e91"}, - {file = "Pillow-10.0.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ee7810cf7c83fa227ba9125de6084e5e8b08c59038a7b2c9045ef4dde61663b4"}, - {file = "Pillow-10.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b1be1c872b9b5fcc229adeadbeb51422a9633abd847c0ff87dc4ef9bb184ae08"}, - {file = "Pillow-10.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:98533fd7fa764e5f85eebe56c8e4094db912ccbe6fbf3a58778d543cadd0db08"}, - {file = "Pillow-10.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:764d2c0daf9c4d40ad12fbc0abd5da3af7f8aa11daf87e4fa1b834000f4b6b0a"}, - {file = "Pillow-10.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fcb59711009b0168d6ee0bd8fb5eb259c4ab1717b2f538bbf36bacf207ef7a68"}, - {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:697a06bdcedd473b35e50a7e7506b1d8ceb832dc238a336bd6f4f5aa91a4b500"}, - {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f665d1e6474af9f9da5e86c2a3a2d2d6204e04d5af9c06b9d42afa6ebde3f21"}, - {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:2fa6dd2661838c66f1a5473f3b49ab610c98a128fc08afbe81b91a1f0bf8c51d"}, - {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:3a04359f308ebee571a3127fdb1bd01f88ba6f6fb6d087f8dd2e0d9bff43f2a7"}, - {file = "Pillow-10.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:723bd25051454cea9990203405fa6b74e043ea76d4968166dfd2569b0210886a"}, - {file = "Pillow-10.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:71671503e3015da1b50bd18951e2f9daf5b6ffe36d16f1eb2c45711a301521a7"}, - {file = "Pillow-10.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:44e7e4587392953e5e251190a964675f61e4dae88d1e6edbe9f36d6243547ff3"}, - {file = "Pillow-10.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:3855447d98cced8670aaa63683808df905e956f00348732448b5a6df67ee5849"}, - {file = "Pillow-10.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ed2d9c0704f2dc4fa980b99d565c0c9a543fe5101c25b3d60488b8ba80f0cce1"}, - {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5bb289bb835f9fe1a1e9300d011eef4d69661bb9b34d5e196e5e82c4cb09b37"}, - {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a0d3e54ab1df9df51b914b2233cf779a5a10dfd1ce339d0421748232cea9876"}, - {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:2cc6b86ece42a11f16f55fe8903595eff2b25e0358dec635d0a701ac9586588f"}, - {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:ca26ba5767888c84bf5a0c1a32f069e8204ce8c21d00a49c90dabeba00ce0145"}, - {file = "Pillow-10.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f0b4b06da13275bc02adfeb82643c4a6385bd08d26f03068c2796f60d125f6f2"}, - {file = "Pillow-10.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bc2e3069569ea9dbe88d6b8ea38f439a6aad8f6e7a6283a38edf61ddefb3a9bf"}, - {file = "Pillow-10.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:8b451d6ead6e3500b6ce5c7916a43d8d8d25ad74b9102a629baccc0808c54971"}, - {file = "Pillow-10.0.1-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:32bec7423cdf25c9038fef614a853c9d25c07590e1a870ed471f47fb80b244db"}, - {file = "Pillow-10.0.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7cf63d2c6928b51d35dfdbda6f2c1fddbe51a6bc4a9d4ee6ea0e11670dd981e"}, - {file = "Pillow-10.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f6d3d4c905e26354e8f9d82548475c46d8e0889538cb0657aa9c6f0872a37aa4"}, - {file = "Pillow-10.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:847e8d1017c741c735d3cd1883fa7b03ded4f825a6e5fcb9378fd813edee995f"}, - {file = "Pillow-10.0.1-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:7f771e7219ff04b79e231d099c0a28ed83aa82af91fd5fa9fdb28f5b8d5addaf"}, - {file = "Pillow-10.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459307cacdd4138edee3875bbe22a2492519e060660eaf378ba3b405d1c66317"}, - {file = "Pillow-10.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b059ac2c4c7a97daafa7dc850b43b2d3667def858a4f112d1aa082e5c3d6cf7d"}, - {file = "Pillow-10.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6caf3cd38449ec3cd8a68b375e0c6fe4b6fd04edb6c9766b55ef84a6e8ddf2d"}, - {file = "Pillow-10.0.1.tar.gz", hash = "sha256:d72967b06be9300fed5cfbc8b5bafceec48bf7cdc7dab66b1d2549035287191d"}, + {file = "pillow-10.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45"}, + {file = "pillow-10.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf"}, + {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3"}, + {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5"}, + {file = "pillow-10.3.0-cp310-cp310-win32.whl", hash = "sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2"}, + {file = "pillow-10.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f"}, + {file = "pillow-10.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b"}, + {file = "pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795"}, + {file = "pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd"}, + {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad"}, + {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c"}, + {file = "pillow-10.3.0-cp311-cp311-win32.whl", hash = "sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09"}, + {file = "pillow-10.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d"}, + {file = "pillow-10.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f"}, + {file = "pillow-10.3.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84"}, + {file = "pillow-10.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a"}, + {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef"}, + {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3"}, + {file = "pillow-10.3.0-cp312-cp312-win32.whl", hash = "sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d"}, + {file = "pillow-10.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b"}, + {file = "pillow-10.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a"}, + {file = "pillow-10.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b"}, + {file = "pillow-10.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd"}, + {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d"}, + {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3"}, + {file = "pillow-10.3.0-cp38-cp38-win32.whl", hash = "sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b"}, + {file = "pillow-10.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999"}, + {file = "pillow-10.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936"}, + {file = "pillow-10.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8"}, + {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9"}, + {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb"}, + {file = "pillow-10.3.0-cp39-cp39-win32.whl", hash = "sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572"}, + {file = "pillow-10.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb"}, + {file = "pillow-10.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591"}, + {file = "pillow-10.3.0.tar.gz", hash = "sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d"}, ] [package.extras] docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.5.0" description = "plugin and hook calling mechanisms for python" +category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [package.extras] @@ -460,19 +499,21 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pycodestyle" -version = "2.11.0" +version = "2.12.0" description = "Python style guide checker" +category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "pycodestyle-2.11.0-py2.py3-none-any.whl", hash = "sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"}, - {file = "pycodestyle-2.11.0.tar.gz", hash = "sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0"}, + {file = "pycodestyle-2.12.0-py2.py3-none-any.whl", hash = "sha256:949a39f6b86c3e1515ba1787c2022131d165a8ad271b11370a8819aa070269e4"}, + {file = "pycodestyle-2.12.0.tar.gz", hash = "sha256:442f950141b4f43df752dd303511ffded3a04c2b6fb7f65980574f0c31e6e79c"}, ] [[package]] name = "pycparser" version = "2.21" description = "C parser in Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -482,57 +523,51 @@ files = [ [[package]] name = "pyflakes" -version = "3.1.0" +version = "3.2.0" description = "passive checker of Python programs" +category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, - {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, + {file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"}, + {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, ] [[package]] name = "pyproj" -version = "3.5.0" +version = "3.6.1" description = "Python interface to PROJ (cartographic projections and coordinate transformations library)" +category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pyproj-3.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6475ce653880938468a1a1b7321267243909e34b972ba9e53d5982c41d555918"}, - {file = "pyproj-3.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61e4ad57d89b03a7b173793b31bca8ee110112cde1937ef0f42a70b9120c827d"}, - {file = "pyproj-3.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdd2021bb6f7f346bfe1d2a358aa109da017d22c4704af2d994e7c7ee0a7a53"}, - {file = "pyproj-3.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5674923351e76222e2c10c58b5e1ac119d7a46b270d822c463035971b06f724b"}, - {file = "pyproj-3.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd5e2b6aa255023c4acd0b977590f1f7cc801ba21b4d806fcf6dfac3474ebb83"}, - {file = "pyproj-3.5.0-cp310-cp310-win32.whl", hash = "sha256:6f316a66031a14e9c5a88c91f8b77aa97f5454895674541ed6ab630b682be35d"}, - {file = "pyproj-3.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:f7c2f4d9681e810cf40239caaca00079930a6d9ee6591139b88d592d36051d82"}, - {file = "pyproj-3.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7572983134e310e0ca809c63f1722557a040fe9443df5f247bf11ba887eb1229"}, - {file = "pyproj-3.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eccb417b91d0be27805dfc97550bfb8b7db94e9fe1db5ebedb98f5b88d601323"}, - {file = "pyproj-3.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:621d78a9d8bf4d06e08bef2471021fbcb1a65aa629ad4a20c22e521ce729cc20"}, - {file = "pyproj-3.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9a024370e917c899bff9171f03ea6079deecdc7482a146a2c565f3b9df134ea"}, - {file = "pyproj-3.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b7c2113c4d11184a238077ec85e31eda1dcc58ffeb9a4429830e0a7036e787d"}, - {file = "pyproj-3.5.0-cp311-cp311-win32.whl", hash = "sha256:a730f5b4c98c8a0f312437873e6e34dbd4cc6dc23d5afd91a6691c62724b1f68"}, - {file = "pyproj-3.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:e97573de0ab3bbbcb4c7748bc41f4ceb6da10b45d35b1a294b5820701e7c25f0"}, - {file = "pyproj-3.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2b708fd43453b985642b737d4a6e7f1d6a0ab1677ffa4e14cc258537b49224b0"}, - {file = "pyproj-3.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b60d93a200639e8367c6542a964fd0aa2dbd152f256c1831dc18cd5aa470fb8a"}, - {file = "pyproj-3.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38862fe07316ae12b79d82d298e390973a4f00b684f3c2d037238e20e00610ba"}, - {file = "pyproj-3.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:71b65f2a38cd9e16883dbb0f8ae82bdf8f6b79b1b02975c78483ab8428dbbf2f"}, - {file = "pyproj-3.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b752b7d9c4b08181c7e8c0d9c7f277cbefff42227f34d3310696a87c863d9dd3"}, - {file = "pyproj-3.5.0-cp38-cp38-win32.whl", hash = "sha256:b937215bfbaf404ec8f03ca741fc3f9f2c4c2c5590a02ccddddd820ae3c71331"}, - {file = "pyproj-3.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:97ed199033c2c770e7eea2ef80ff5e6413426ec2d7ec985b869792f04ab95d05"}, - {file = "pyproj-3.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:052c49fce8b5d55943a35c36ccecb87350c68b48ba95bc02a789770c374ef819"}, - {file = "pyproj-3.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1507138ea28bf2134d31797675380791cc1a7156a3aeda484e65a78a4aba9b62"}, - {file = "pyproj-3.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c02742ef3d846401861a878a61ef7ad911ea7539d6cc4619ddb52dbdf7b45aee"}, - {file = "pyproj-3.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:385b0341861d3ebc8cad98337a738821dcb548d465576527399f4955ca24b6ed"}, - {file = "pyproj-3.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fe6bb1b68a35d07378d38be77b5b2f8dd2bea5910c957bfcc7bee55988d3910"}, - {file = "pyproj-3.5.0-cp39-cp39-win32.whl", hash = "sha256:5c4b85ac10d733c42d73a2e6261c8d6745bf52433a31848dd1b6561c9a382da3"}, - {file = "pyproj-3.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:1798ff7d65d9057ebb2d017ffe8403268b8452f24d0428b2140018c25c7fa1bc"}, - {file = "pyproj-3.5.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d711517a8487ef3245b08dc82f781a906df9abb3b6cb0ce0486f0eeb823ca570"}, - {file = "pyproj-3.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:788a5dadb532644a64efe0f5f01bf508c821eb7e984f13a677d56002f1e8a67a"}, - {file = "pyproj-3.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73f7960a97225812f9b1d7aeda5fb83812f38de9441e3476fcc8abb3e2b2f4de"}, - {file = "pyproj-3.5.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fde5ece4d2436b5a57c8f5f97b49b5de06a856d03959f836c957d3e609f2de7e"}, - {file = "pyproj-3.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e08db25b61cf024648d55973cc3d1c3f1d0818fabf594d5f5a8e2318103d2aa0"}, - {file = "pyproj-3.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a87b419a2a352413fbf759ecb66da9da50bd19861c8f26db6a25439125b27b9"}, - {file = "pyproj-3.5.0.tar.gz", hash = "sha256:9859d1591c1863414d875ae0759e72c2cffc01ab989dc64137fbac572cc81bf6"}, + {file = "pyproj-3.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ab7aa4d9ff3c3acf60d4b285ccec134167a948df02347585fdd934ebad8811b4"}, + {file = "pyproj-3.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4bc0472302919e59114aa140fd7213c2370d848a7249d09704f10f5b062031fe"}, + {file = "pyproj-3.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5279586013b8d6582e22b6f9e30c49796966770389a9d5b85e25a4223286cd3f"}, + {file = "pyproj-3.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80fafd1f3eb421694857f254a9bdbacd1eb22fc6c24ca74b136679f376f97d35"}, + {file = "pyproj-3.6.1-cp310-cp310-win32.whl", hash = "sha256:c41e80ddee130450dcb8829af7118f1ab69eaf8169c4bf0ee8d52b72f098dc2f"}, + {file = "pyproj-3.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:db3aedd458e7f7f21d8176f0a1d924f1ae06d725228302b872885a1c34f3119e"}, + {file = "pyproj-3.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ebfbdbd0936e178091309f6cd4fcb4decd9eab12aa513cdd9add89efa3ec2882"}, + {file = "pyproj-3.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:447db19c7efad70ff161e5e46a54ab9cc2399acebb656b6ccf63e4bc4a04b97a"}, + {file = "pyproj-3.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7e13c40183884ec7f94eb8e0f622f08f1d5716150b8d7a134de48c6110fee85"}, + {file = "pyproj-3.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65ad699e0c830e2b8565afe42bd58cc972b47d829b2e0e48ad9638386d994915"}, + {file = "pyproj-3.6.1-cp311-cp311-win32.whl", hash = "sha256:8b8acc31fb8702c54625f4d5a2a6543557bec3c28a0ef638778b7ab1d1772132"}, + {file = "pyproj-3.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:38a3361941eb72b82bd9a18f60c78b0df8408416f9340521df442cebfc4306e2"}, + {file = "pyproj-3.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1e9fbaf920f0f9b4ee62aab832be3ae3968f33f24e2e3f7fbb8c6728ef1d9746"}, + {file = "pyproj-3.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d227a865356f225591b6732430b1d1781e946893789a609bb34f59d09b8b0f8"}, + {file = "pyproj-3.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83039e5ae04e5afc974f7d25ee0870a80a6bd6b7957c3aca5613ccbe0d3e72bf"}, + {file = "pyproj-3.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb059ba3bced6f6725961ba758649261d85ed6ce670d3e3b0a26e81cf1aa8d"}, + {file = "pyproj-3.6.1-cp312-cp312-win32.whl", hash = "sha256:2d6ff73cc6dbbce3766b6c0bce70ce070193105d8de17aa2470009463682a8eb"}, + {file = "pyproj-3.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:7a27151ddad8e1439ba70c9b4b2b617b290c39395fa9ddb7411ebb0eb86d6fb0"}, + {file = "pyproj-3.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ba1f9b03d04d8cab24d6375609070580a26ce76eaed54631f03bab00a9c737b"}, + {file = "pyproj-3.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18faa54a3ca475bfe6255156f2f2874e9a1c8917b0004eee9f664b86ccc513d3"}, + {file = "pyproj-3.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd43bd9a9b9239805f406fd82ba6b106bf4838d9ef37c167d3ed70383943ade1"}, + {file = "pyproj-3.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50100b2726a3ca946906cbaa789dd0749f213abf0cbb877e6de72ca7aa50e1ae"}, + {file = "pyproj-3.6.1-cp39-cp39-win32.whl", hash = "sha256:9274880263256f6292ff644ca92c46d96aa7e57a75c6df3f11d636ce845a1877"}, + {file = "pyproj-3.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:36b64c2cb6ea1cc091f329c5bd34f9c01bb5da8c8e4492c709bda6a09f96808f"}, + {file = "pyproj-3.6.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd93c1a0c6c4aedc77c0fe275a9f2aba4d59b8acf88cebfc19fe3c430cfabf4f"}, + {file = "pyproj-3.6.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6420ea8e7d2a88cb148b124429fba8cd2e0fae700a2d96eab7083c0928a85110"}, + {file = "pyproj-3.6.1.tar.gz", hash = "sha256:44aa7c704c2b7d8fb3d483bbf75af6cb2350d30a63b144279a09b75fead501bf"}, ] [package.dependencies] @@ -540,13 +575,14 @@ certifi = "*" [[package]] name = "pytest" -version = "7.4.2" +version = "8.2.2" description = "pytest: simple powerful testing with Python" +category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, - {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, + {file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"}, + {file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"}, ] [package.dependencies] @@ -554,21 +590,22 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +pluggy = ">=1.5,<2.0" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" -version = "4.1.0" +version = "5.0.0" description = "Pytest plugin for measuring coverage." +category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, - {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, + {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] @@ -576,12 +613,13 @@ coverage = {version = ">=5.2.1", extras = ["toml"]} pytest = ">=4.6" [package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "shapely" version = "2.0.1" description = "Manipulation and analysis of geometric objects" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -629,13 +667,14 @@ files = [ numpy = ">=1.14" [package.extras] -docs = ["matplotlib", "numpydoc (==1.1.*)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] +docs = ["matplotlib", "numpydoc (>=1.1.0,<1.2.0)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] test = ["pytest", "pytest-cov"] [[package]] name = "tinycss2" version = "1.2.1" description = "A tiny CSS parser" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -654,6 +693,7 @@ test = ["flake8", "isort", "pytest"] name = "tomli" version = "2.0.1" description = "A lil' TOML parser" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -661,30 +701,11 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -[[package]] -name = "tqdm" -version = "4.65.0" -description = "Fast, Extensible Progress Meter" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tqdm-4.65.0-py3-none-any.whl", hash = "sha256:c4f53a17fe37e132815abceec022631be8ffe1b9381c2e6e30aa70edc99e9671"}, - {file = "tqdm-4.65.0.tar.gz", hash = "sha256:1871fb68a86b8fb3b59ca4cdd3dcccbc7e6d613eeed31f4c332531977b89beb5"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -dev = ["py-make (>=0.1.0)", "twine", "wheel"] -notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] - [[package]] name = "webencodings" version = "0.5.1" description = "Character encoding aliases for legacy web content" +category = "main" optional = false python-versions = "*" files = [ @@ -695,4 +716,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "83f10c9ed89e4fa9ba5386d76c5b9f9c92afbadbc6c1c6df0386f33bb532e211" +content-hash = "4da2cb97a8f8c3419bf66bb1f6b4bdf141090f88154a3b7aa11af58034c5df80" diff --git a/pyproject.toml b/pyproject.toml index 95af711..49d2085 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,28 +7,27 @@ license = "LGPL-3.0-only" [tool.poetry.dependencies] python = "^3.9" -cairocffi = "^1.4.0" -tqdm = "^4.64.0" +cairocffi = "^1.7.1" Shapely = "^2.0.1" CairoSVG = "^2.7.0" -pyproj = "^3.4.0" -Pillow = "^10.0.1" -pangocffi = "^0.11.0" +pyproj = "^3.6.1" +Pillow = "^10.3.0" +pangocffi = "^0.13.0" pangocairocffi = "^0.7.0" [tool.poetry.group.gdal] optional = true -[tool.poetry.group.gdal.dependencies] # We need to lock ourselves to 3.4.3 as that is the version that is supported # by GitHub Action Ubuntu environments. See .github/workflows/build.yml -GDAL = "3.4.3" +[tool.poetry.group.gdal.dependencies] +gdal = "3.8.4" -[tool.poetry.dev-dependencies] -flake8 = "^6.1.0" -pytest = "^7.4.2" -coverage = "^7.3.1" -pytest-cov = "^4.1.0" +[tool.poetry.group.dev.dependencies] +flake8 = "^7.1.0" +pytest = "^8.2.2" +coverage = "^7.5.4" +pytest-cov = "^5.0.0" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/tests/data/geotiff/test_canvas_transform.py b/tests/data/geotiff/test_canvas_transform.py index 76a6fa3..fcfabd3 100644 --- a/tests/data/geotiff/test_canvas_transform.py +++ b/tests/data/geotiff/test_canvas_transform.py @@ -23,6 +23,7 @@ from map_engraver.drawable.geometry.polygon_drawer import PolygonDrawer from map_engraver.drawable.images.bitmap import Bitmap +from tests.utils import svg_has_style_attr class TestCanvasTransform(unittest.TestCase): @@ -56,7 +57,7 @@ def test_transform_geotiff_to_crs_within_canvas_invalid(self): with self.assertRaisesRegex( RuntimeError, - 'not recognized as a supported file format.' + 'not recognized as( being in)? a supported file format.' ): transform_geotiff_to_crs_within_canvas( input_file, canvas_mask, builder, output_file @@ -204,15 +205,21 @@ def test_build_geotiff_crs_within_canvas_matrix(self): with open(canvas_file, 'r') as file: data = file.read() - assert data.find( + + assert svg_has_style_attr( + data, 'path', 'd', 'M -0.000432709 -0.000179234 ' 'L 26.999834 0.000401775 ' 'L 26.999823 31.499943 ' 'L 0.0000793665 31.500624 Z ' 'M -0.000432709 -0.000179234' - ) != -1 - assert data.find( - 'matrix(' - '1.094261,-2.64178,2.64178,1.094261,18.938447,82.311553' - ')' - ) != -1 + ) + + assert svg_has_style_attr( + data, 'path', 'transform', + 'matrix\\(' + '1.094261, ?-2.64178, ?2.64178, ?' + '1.094261, ?18.938447, ?82.311553' + '\\)', + escape=False + ) diff --git a/tests/drawable/geometry/test_line_drawer.py b/tests/drawable/geometry/test_line_drawer.py index 5816b97..6572876 100644 --- a/tests/drawable/geometry/test_line_drawer.py +++ b/tests/drawable/geometry/test_line_drawer.py @@ -7,6 +7,7 @@ from map_engraver.canvas import CanvasBuilder from map_engraver.canvas.canvas_unit import CanvasUnit as Cu from map_engraver.drawable.geometry.line_drawer import LineDrawer +from tests.utils import svg_has_style_attr class TestLineDrawer(unittest.TestCase): @@ -50,10 +51,15 @@ def test_line_string(self): with open(path, 'r') as file: data = file.read() - assert data.find('M 30 30 L 70 30 L 70 70 L 30 70') != -1 - assert data.find('fill:none') != -1 - assert data.find('stroke-width:1.5') != -1 - assert data.find('stroke:rgb(0%,100%,0%);') != -1 + assert svg_has_style_attr( + data, 'path', 'd', 'M 30 30 L 70 30 L 70 70 L 30 70' + ) + assert svg_has_style_attr(data, 'path', 'fill', 'none') + assert svg_has_style_attr(data, 'path', 'fill', 'none') + assert svg_has_style_attr(data, 'path', 'stroke-width', '1.5') + assert svg_has_style_attr( + data, 'path', 'stroke', 'rgb\\(0%, ?100%, ?0%\\)', escape=False + ) def test_multi_line_string(self): path = Path(__file__).parent.joinpath( @@ -90,8 +96,14 @@ def test_multi_line_string(self): with open(path, 'r') as file: data = file.read() - assert data.find('M 30 30 L 70 30 L 70 70 L 30 70') != -1 - assert data.find('M 40 40 L 40 60 L 60 60 L 60 40') != -1 - assert data.find('fill:none') != -1 - assert data.find('stroke-width:1.5') != -1 - assert data.find('stroke:rgb(100%,0%,0%);') != -1 + assert svg_has_style_attr( + data, 'path', 'd', 'M 30 30 L 70 30 L 70 70 L 30 70' + ) + assert svg_has_style_attr( + data, 'path', 'd', 'M 40 40 L 40 60 L 60 60 L 60 40' + ) + assert svg_has_style_attr(data, 'path', 'fill', 'none') + assert svg_has_style_attr(data, 'path', 'stroke-width', '1.5') + assert svg_has_style_attr( + data, 'path', 'stroke', 'rgb\\(100%, ?0%, ?0%\\)', escape=False + ) diff --git a/tests/drawable/geometry/test_polygon_drawer.py b/tests/drawable/geometry/test_polygon_drawer.py index 0b2125b..1dc5891 100644 --- a/tests/drawable/geometry/test_polygon_drawer.py +++ b/tests/drawable/geometry/test_polygon_drawer.py @@ -6,6 +6,7 @@ from map_engraver.canvas import CanvasBuilder from map_engraver.canvas.canvas_unit import CanvasUnit as Cu from map_engraver.drawable.geometry.polygon_drawer import PolygonDrawer +from tests.utils import svg_has_style_attr class TestPolygonDrawer(unittest.TestCase): @@ -43,10 +44,14 @@ def test_only_fill(self): with open(path, 'r') as file: data = file.read() - assert data.find('M 30 30 L 70 30 L 70 70 L 30 70 Z M 30 30') != -1 - assert data.find('fill:rgb(0%,100%,0%)') != -1 - assert data.find('stroke:none') != -1 - assert data.find('stroke-width:') == -1 + assert svg_has_style_attr( + data, 'path', 'd', 'M 30 30 L 70 30 L 70 70 L 30 70 Z M 30 30' + ) + assert svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(0%, ?100%, ?0%\\)', escape=False + ) + assert not svg_has_style_attr(data, 'path', 'stroke') + assert not svg_has_style_attr(data, 'path', 'stroke-width') def test_only_stroke(self): path = Path(__file__).parent.joinpath( @@ -79,10 +84,14 @@ def test_only_stroke(self): with open(path, 'r') as file: data = file.read() - assert data.find('M 30 30 L 70 30 L 70 70 L 30 70 Z M 30 30') != -1 - assert data.find('fill:none') != -1 - assert data.find('stroke-width:1.5') != -1 - assert data.find('stroke:rgb(0%,100%,0%);') != -1 + assert svg_has_style_attr( + data, 'path', 'd', 'M 30 30 L 70 30 L 70 70 L 30 70 Z M 30 30' + ) + assert svg_has_style_attr(data, 'path', 'fill', 'none') + assert svg_has_style_attr(data, 'path', 'stroke-width', '1.5') + assert svg_has_style_attr( + data, 'path', 'stroke', 'rgb\\(0%, ?100%, ?0%\\)', escape=False + ) def test_fill_preserve(self): path = Path(__file__).parent.joinpath( @@ -116,10 +125,16 @@ def test_fill_preserve(self): with open(path, 'r') as file: data = file.read() - assert data.find('M 30 30 L 70 30 L 70 70 L 30 70 Z M 30 30') != -1 - assert data.find('fill:rgb(100%,0%,0%)') != -1 - assert data.find('stroke-width:2') != -1 - assert data.find('stroke:rgb(0%,100%,0%);') != -1 + assert svg_has_style_attr( + data, 'path', 'd', 'M 30 30 L 70 30 L 70 70 L 30 70 Z M 30 30' + ) + assert svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(100%, ?0%, ?0%\\)', escape=False + ) + assert svg_has_style_attr(data, 'path', 'stroke-width', '2') + assert svg_has_style_attr( + data, 'path', 'stroke', 'rgb\\(0%, ?100%, ?0%\\)', escape=False + ) def test_multipolygons(self): path = Path(__file__).parent.joinpath( @@ -161,8 +176,14 @@ def test_multipolygons(self): with open(path, 'r') as file: data = file.read() - assert data.find('M 30 30 L 40 30 L 40 70 L 30 70 Z M 30 30') != -1 - assert data.find('M 60 30 L 70 30 L 70 70 L 60 70 Z M 60 30') != -1 - assert data.find('fill:none') != -1 - assert data.find('stroke-width:1.5') != -1 - assert data.find('stroke:rgb(0%,100%,0%);') != -1 + assert svg_has_style_attr( + data, 'path', 'd', 'M 30 30 L 40 30 L 40 70 L 30 70 Z M 30 30' + ) + assert svg_has_style_attr( + data, 'path', 'd', 'M 30 30 L 40 30 L 40 70 L 30 70 Z M 30 30' + ) + assert svg_has_style_attr(data, 'path', 'fill', 'none') + assert svg_has_style_attr(data, 'path', 'stroke-width', '1.5') + assert svg_has_style_attr( + data, 'path', 'stroke', 'rgb\\(0%, ?100%, ?0%\\)', escape=False + ) diff --git a/tests/drawable/geometry/test_stripe_filled_polygon_drawer.py b/tests/drawable/geometry/test_stripe_filled_polygon_drawer.py index 0fcc1a2..219cdb7 100644 --- a/tests/drawable/geometry/test_stripe_filled_polygon_drawer.py +++ b/tests/drawable/geometry/test_stripe_filled_polygon_drawer.py @@ -11,6 +11,7 @@ from map_engraver.canvas.canvas_unit import CanvasUnit as Cu from map_engraver.drawable.geometry.stripe_filled_polygon_drawer import \ StripeFilledPolygonDrawer +from tests.utils import svg_has_style_attr class TestStripeFilledPolygonDrawer(unittest.TestCase): @@ -88,11 +89,17 @@ def test_single_stripe(self): with open(path, 'r') as file: data = file.read() - assert data.find('M 30 30 L 70 30 L 70 70 L 30 70 Z M 30 30') != -1 - assert data.find('M 40 40 L 60 40 L 60 60 L 40 60 Z M 40 40') == -1 - assert data.find('fill:rgb(0%,100%,0%)') != -1 - assert data.find('stroke:none') != -1 - assert data.find('stroke-width:') == -1 + assert svg_has_style_attr( + data, 'path', 'd', 'M 30 30 L 70 30 L 70 70 L 30 70 Z M 30 30' + ) + assert not svg_has_style_attr( + data, 'path', 'd', 'M 40 40 L 60 40 L 60 60 L 40 60 Z M 40 40' + ) + assert svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(0%, ?100%, ?0%\\)', escape=False + ) + assert not svg_has_style_attr(data, 'path', 'stroke') + assert not svg_has_style_attr(data, 'path', 'stroke-width') def test_two_vertical_stripes(self): path = Path(__file__).parent.joinpath( @@ -127,12 +134,20 @@ def test_two_vertical_stripes(self): with open(path, 'r') as file: data = file.read() - assert data.find('M 30 30 L 30 70 L 50 70 L 50 30 Z M 30 30') != -1 - assert data.find('M 50 30 L 50 70 L 70 70 L 70 30 Z M 50 30') != -1 - assert data.find('fill:rgb(0%,100%,0%)') != -1 - assert data.find('fill:rgb(0%,0%,100%)') != -1 - assert data.find('stroke:none') != -1 - assert data.find('stroke-width:') == -1 + assert svg_has_style_attr( + data, 'path', 'd', 'M 30 30 L 30 70 L 50 70 L 50 30 Z M 30 30' + ) + assert svg_has_style_attr( + data, 'path', 'd', 'M 50 30 L 50 70 L 70 70 L 70 30 Z M 50 30' + ) + assert svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(0%, ?100%, ?0%\\)', escape=False + ) + assert svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(0%, ?0%, ?100%\\)', escape=False + ) + assert not svg_has_style_attr(data, 'path', 'stroke') + assert not svg_has_style_attr(data, 'path', 'stroke-width') def test_large_stripes(self): path = Path(__file__).parent.joinpath( @@ -167,11 +182,17 @@ def test_large_stripes(self): with open(path, 'r') as file: data = file.read() - assert data.find('M 30 30 L 30 70 L 70 70 L 70 30 Z M 30 30') != -1 - assert data.find('fill:rgb(0%,100%,0%)') != -1 - assert data.find('fill:rgb(0%,0%,100%)') == -1 - assert data.find('stroke:none') != -1 - assert data.find('stroke-width:') == -1 + assert svg_has_style_attr( + data, 'path', 'd', 'M 30 30 L 30 70 L 70 70 L 70 30 Z M 30 30' + ) + assert svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(0%, ?100%, ?0%\\)', escape=False + ) + assert not svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(0%, ?0%, ?100%\\)', escape=False + ) + assert not svg_has_style_attr(data, 'path', 'stroke') + assert not svg_has_style_attr(data, 'path', 'stroke-width') def test_multi_polygons(self): path = Path(__file__).parent.joinpath( @@ -223,8 +244,14 @@ def test_multi_polygons(self): with open(path, 'r') as file: data = file.read() - assert data.find('fill:rgb(100%,100%,0%)') != -1 - assert data.find('fill:rgb(0%,0%,0%)') != -1 - assert data.find('fill:rgb(70%,0%,70%)') != -1 - assert data.find('stroke:none') != -1 - assert data.find('stroke-width:') == -1 + assert svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(100%, ?100%, ?0%\\)', escape=False + ) + assert svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(0%, ?0%, ?0%\\)', escape=False + ) + assert svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(70%, ?0%, ?70%\\)', escape=False + ) + assert not svg_has_style_attr(data, 'path', 'stroke') + assert not svg_has_style_attr(data, 'path', 'stroke-width') diff --git a/tests/drawable/geometry/test_stripe_stroked_polygon_drawer.py b/tests/drawable/geometry/test_stripe_stroked_polygon_drawer.py index 32848df..be5d07e 100644 --- a/tests/drawable/geometry/test_stripe_stroked_polygon_drawer.py +++ b/tests/drawable/geometry/test_stripe_stroked_polygon_drawer.py @@ -11,6 +11,7 @@ from map_engraver.canvas.canvas_unit import CanvasUnit as Cu from map_engraver.drawable.geometry.stripe_stroked_polygon_drawer import \ StripeStrokedPolygonDrawer +from tests.utils import svg_has_style_attr, svg_count_style_attr class TestStripeStrokedPolygonDrawer(unittest.TestCase): @@ -114,13 +115,15 @@ def test_single_stripe(self): with open(path, 'r') as file: data = file.read() - assert data.find('M 30 30 L 70 30') != -1 - assert data.find('M 70 70 L 30 70') != -1 - assert data.find('M 30 40 L 70 40') != -1 - assert data.find('M 30 50 L 70 50') != -1 - assert data.find('M 30 60 L 70 60') != -1 - assert data.count('stroke:rgb(0%,100%,0%)') == 5 - assert data.count('stroke-width:1') == 5 + assert svg_has_style_attr(data, 'path', 'd', 'M 30 30 L 70 30') + assert svg_has_style_attr(data, 'path', 'd', 'M 70 70 L 30 70') + assert svg_has_style_attr(data, 'path', 'd', 'M 30 40 L 70 40') + assert svg_has_style_attr(data, 'path', 'd', 'M 30 50 L 70 50') + assert svg_has_style_attr(data, 'path', 'd', 'M 30 60 L 70 60') + assert svg_count_style_attr( + data, 'path', 'stroke', 'rgb\\(0%, ?100%, ?0%\\)', escape=False + ) == 5 + assert svg_count_style_attr(data, 'path', 'stroke-width', '1') == 5 def test_two_vertical_stripes(self): path = Path(__file__).parent.joinpath( @@ -156,12 +159,16 @@ def test_two_vertical_stripes(self): with open(path, 'r') as file: data = file.read() - assert data.find('M 30 70 L 30 30') != -1 - assert data.find('M 50 30 L 50 70') != -1 - assert data.find('stroke:rgb(0%,100%,0%)') != -1 - assert data.find('stroke:rgb(0%,0%,100%)') != -1 - assert data.find('stroke-width:1') != -1 - assert data.find('stroke-width:2') != -1 + assert svg_has_style_attr(data, 'path', 'd', 'M 30 70 L 30 30') + assert svg_has_style_attr(data, 'path', 'd', 'M 50 30 L 50 70') + assert svg_has_style_attr( + data, 'path', 'stroke', 'rgb\\(0%, ?100%, ?0%\\)', escape=False + ) + assert svg_has_style_attr( + data, 'path', 'stroke', 'rgb\\(0%, ?0%, ?100%\\)', escape=False + ) + assert svg_has_style_attr(data, 'path', 'stroke-width', '1') + assert svg_has_style_attr(data, 'path', 'stroke-width', '2') def test_large_stripes(self): path = Path(__file__).parent.joinpath( @@ -197,15 +204,21 @@ def test_large_stripes(self): with open(path, 'r') as file: data = file.read() - assert data.find('M 44 70 L 44 30') != -1 - assert data.find('M 58 70 L 58 30') != -1 - assert data.find('M 37 70 L 37 30') != -1 - assert data.find('M 51 70 L 51 30') != -1 - assert data.find('M 65 70 L 65 30') != -1 - assert data.find('stroke:rgb(0%,100%,0%)') != -1 - assert data.find('stroke:rgb(0%,0%,100%)') != -1 - assert data.find('stroke:rgb(0%,100%,0%)') < \ - data.find('stroke:rgb(0%,0%,100%)') + assert svg_has_style_attr(data, 'path', 'd', 'M 44 70 L 44 30') + assert svg_has_style_attr(data, 'path', 'd', 'M 58 70 L 58 30') + assert svg_has_style_attr(data, 'path', 'd', 'M 37 70 L 37 30') + assert svg_has_style_attr(data, 'path', 'd', 'M 51 70 L 51 30') + assert svg_has_style_attr(data, 'path', 'd', 'M 65 70 L 65 30') + assert svg_has_style_attr( + data, 'path', 'stroke', 'rgb\\(0%, ?100%, ?0%\\)', escape=False + ) + assert svg_has_style_attr( + data, 'path', 'stroke', 'rgb\\(0%, ?0%, ?100%\\)', escape=False + ) + assert (data.find('stroke:rgb(0%,100%,0%)') < + data.find('stroke:rgb(0%,0%,100%)')) or \ + (data.find('stroke="rgb(0%, 100%, 0%)"') < + data.find('stroke="rgb(0%, 0%, 100%)"')) def test_multi_polygons(self): path = Path(__file__).parent.joinpath( @@ -260,9 +273,18 @@ def test_multi_polygons(self): with open(path, 'r') as file: data = file.read() - assert data.count('stroke:rgb(100%,100%,0%)') == 6 - assert data.count('stroke:rgb(0%,0%,0%)') == 6 - assert data.count('stroke:rgb(70%,0%,70%)') == 6 - assert data.count('stroke-width:1') == 6 - assert data.count('stroke-width:3') == 6 - assert data.count('stroke-width:4') == 6 + assert svg_count_style_attr( + data, 'path', 'stroke', + 'rgb\\(100%, ?100%, ?0%\\)', escape=False + ) == 6 + assert svg_count_style_attr( + data, 'path', 'stroke', + 'rgb\\(0%, ?0%, ?0%\\)', escape=False + ) == 6 + assert svg_count_style_attr( + data, 'path', 'stroke', + 'rgb\\(70%, ?0%, ?70%\\)', escape=False + ) == 6 + assert svg_count_style_attr(data, 'path', 'stroke-width', '1') == 6 + assert svg_count_style_attr(data, 'path', 'stroke-width', '3') == 6 + assert svg_count_style_attr(data, 'path', 'stroke-width', '4') == 6 diff --git a/tests/drawable/geometry/test_symbol_drawer.py b/tests/drawable/geometry/test_symbol_drawer.py index a6a7c77..b0b4de8 100644 --- a/tests/drawable/geometry/test_symbol_drawer.py +++ b/tests/drawable/geometry/test_symbol_drawer.py @@ -7,6 +7,7 @@ from map_engraver.canvas.canvas_unit import CanvasUnit as Cu from map_engraver.drawable.geometry.symbol_drawer import SymbolDrawer from map_engraver.graphicshelper import CairoHelper +from tests.utils import svg_has_style_attr class TestPolygonDrawer(unittest.TestCase): @@ -55,9 +56,17 @@ def draw_symbol(self, key, point: Point, canvas: Canvas): with open(path, 'r') as file: data = file.read() # Assert that the symbols appear - assert data.find('rgb(50%,30%,0%)') != -1 - assert data.find('rgb(50%,30%,0%)') < data.find('rgb(45%,40%,0%)') - assert data.find('rgb(45%,40%,0%)') < data.find('rgb(55%,40%,0%)') + assert svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(50%, ?30%, ?0%\\)', escape=False + ) + assert svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(45%, ?40%, ?0%\\)', escape=False + ) + assert svg_has_style_attr( + data, 'path', 'fill', 'rgb\\(55%, ?40%, ?0%\\)', escape=False + ) + assert data.find('rgb(50%,') < data.find('rgb(45%,') + assert data.find('rgb(45%,') < data.find('rgb(55%,') def test_can_iterate_dict(self): path = Path(__file__).parent.joinpath( @@ -100,5 +109,9 @@ def draw_symbol(self, key, point: Point, canvas: Canvas): with open(path, 'r') as file: data = file.read() # Assert that the symbols appear with correct size - assert data.find('d="M 55 30 C') != -1 - assert data.find('d="M 79 70 C') != -1 + assert svg_has_style_attr( + data, 'path', 'd', 'M 55 30 C.*', escape=False + ) + assert svg_has_style_attr( + data, 'path', 'd', 'M 79 70 C.*', escape=False + ) diff --git a/tests/drawable/images/test_bitmap.py b/tests/drawable/images/test_bitmap.py index a48024c..66c3a20 100644 --- a/tests/drawable/images/test_bitmap.py +++ b/tests/drawable/images/test_bitmap.py @@ -9,6 +9,7 @@ from map_engraver.canvas.canvas_coordinate import CanvasCoordinate as Cc from map_engraver.drawable.images.bitmap import Bitmap from map_engraver.drawable.layout.background import Background +from tests.utils import svg_has_style_attr class TestBitmap(unittest.TestCase): @@ -154,24 +155,31 @@ def test_scale_and_dpi(self): with open(output_path, 'r') as file: data = file.read() - assert data.find('matrix(0.75,0,0,0.75,37.5,37.5)') != -1 - assert data.find('matrix(0.375,0,0,0.375,37.5,112.5)') != -1 - assert data.find('matrix(0.375,0,0,0.375,37.5,150)') != -1 - assert data.find('matrix(0.375,0,0,0.75,112.5,112.5)') != -1 - assert data.find( - 'matrix(0.265165,0.265165,-0.53033,0.53033,112.5,187.5)' - ) != -1 - assert data.find('matrix(0.75,0,0,0.75,225,37.5)') != -1 - assert data.find('matrix(0.375,0,0,0.375,225,112.5)') != -1 - assert data.find('matrix(0.375,0,0,0.375,225,150)') != -1 - assert data.find('matrix(0.375,0,0,0.75,300,112.5)') != -1 - assert data.find( - 'matrix(0.265165,0.265165,-0.53033,0.53033,300,187.5)' - ) != -1 - assert data.find('matrix(1,0,0,1,450,37.5)') != -1 - assert data.find('matrix(0.5,0,0,0.5,450,137.5)') != -1 - assert data.find('matrix(0.5,0,0,0.5,450,187.5)') != -1 - assert data.find('matrix(0.5,0,0,1,550,137.5)') != -1 - assert data.find( - 'matrix(0.353553,0.353553,-0.707107,0.707107,550,237.5)' - ) != -1 + for matrix in [ + 'matrix(0.75, 0, 0, 0.75, 37.5, 37.5)', + 'matrix(0.375, 0, 0, 0.375, 37.5, 112.5)', + 'matrix(0.375, 0, 0, 0.375, 37.5, 150)', + 'matrix(0.375, 0, 0, 0.75, 112.5, 112.5)', + 'matrix(0.265165, 0.265165, -0.53033, 0.53033, 112.5, 187.5)', + 'matrix(0.75, 0, 0, 0.75, 225, 37.5)', + 'matrix(0.375, 0, 0, 0.375, 225, 112.5)', + 'matrix(0.375, 0, 0, 0.375, 225, 150)', + 'matrix(0.375, 0, 0, 0.75, 300, 112.5)', + 'matrix(0.265165, 0.265165, -0.53033, 0.53033, 300, 187.5)', + 'matrix(1, 0, 0, 1, 450, 37.5)', + 'matrix(0.5, 0, 0, 0.5, 450, 137.5)', + 'matrix(0.5, 0, 0, 0.5, 450, 187.5)', + 'matrix(0.5, 0, 0, 1, 550, 137.5)', + 'matrix(0.353553, 0.353553, -0.707107, 0.707107, 550, 237.5)', + ]: + matrix_escaped = matrix\ + .replace(' ', ' ?')\ + .replace('(', '\\(')\ + .replace(')', '\\)') + assert svg_has_style_attr( + data, + 'use', + 'transform', + matrix_escaped, + escape=False + ) diff --git a/tests/drawable/text/test_pango_drawer.py b/tests/drawable/text/test_pango_drawer.py index 01f7ffe..3bed961 100644 --- a/tests/drawable/text/test_pango_drawer.py +++ b/tests/drawable/text/test_pango_drawer.py @@ -7,6 +7,7 @@ from map_engraver.canvas.canvas_unit import CanvasUnit as Cu from map_engraver.data.pango.layout import Layout from map_engraver.drawable.text.pango_drawer import PangoDrawer +from tests.utils import svg_has_style_attr class TestPangoDrawer(unittest.TestCase): @@ -46,15 +47,14 @@ def test_layout_is_drawn(self): with open(path, 'r') as file: data = file.read() - assert data.find( - '' - ) != -1 - assert data.find( - 'xlink:href="#glyph0-1" x="10"' - ) != -1 - assert data.find( - 'xlink:href="#glyph1-5"' - ) != -1 + assert svg_has_style_attr( + data, 'g', 'fill', 'rgb\\(100%, ?0%, ?0%\\)', escape=False + ) + assert svg_has_style_attr(data, 'g', 'fill-opacity', '1') + assert data.find('xlink:href="#glyph-0-0" x="10"') != -1 or \ + data.find('xlink:href="#glyph0-1" x="10"') != -1 + assert data.find('xlink:href="#glyph-1-4"') != -1 or \ + data.find('xlink:href="#glyph1-5"') != -1 def test_layout_is_drawn_with_color(self): path = Path(__file__).parent.joinpath( @@ -88,15 +88,16 @@ def test_layout_is_drawn_with_color(self): with open(path, 'r') as file: data = file.read() - assert data.find( - '' - ) != -1 - assert data.find( - 'xlink:href="#glyph0-1" x="10"' - ) != -1 - assert data.find( - '' - ) != -1 - assert data.find( - 'xlink:href="#glyph1-5"' - ) != -1 + assert svg_has_style_attr( + data, 'g', 'fill', 'rgb\\(0%, ?0%, ?100%\\)', escape=False + ) + assert svg_has_style_attr(data, 'g', 'fill-opacity', '0.5') + assert data.find('xlink:href="#glyph-0-0" x="10"') != -1 or \ + data.find('xlink:href="#glyph0-1" x="10"') != -1 + + assert svg_has_style_attr( + data, 'g', 'fill', 'rgb\\(100%, ?0%, ?0%\\)', escape=False + ) + assert svg_has_style_attr(data, 'g', 'fill-opacity', '1') + assert data.find('xlink:href="#glyph-1-4"') != -1 or \ + data.find('xlink:href="#glyph1-5"') != -1 diff --git a/tests/drawable/text/test_pango_stroke_drawer.py b/tests/drawable/text/test_pango_stroke_drawer.py index 6687b9d..f5ffc9b 100644 --- a/tests/drawable/text/test_pango_stroke_drawer.py +++ b/tests/drawable/text/test_pango_stroke_drawer.py @@ -10,9 +10,10 @@ from map_engraver.canvas.canvas_unit import CanvasUnit as Cu from map_engraver.data.pango.layout import Layout from map_engraver.drawable.text.pango_stroke_drawer import PangoStrokeDrawer +from tests.utils import svg_has_style_attr -class TestPangoStokeDrawer(unittest.TestCase): +class TestPangoStrokeDrawer(unittest.TestCase): def setUp(self): Path(__file__).parent.joinpath('output/')\ .mkdir(parents=True, exist_ok=True) @@ -52,24 +53,12 @@ def test_layout_is_drawn(self): with open(path, 'r') as file: data = file.read() - assert data.find( - '' - ) != -1 + assert svg_has_style_attr(data, 'path', 'fill', 'none') + assert svg_has_style_attr(data, 'path', 'stroke-linecap', 'round') + assert svg_has_style_attr(data, 'path', 'stroke-linejoin', 'round') + assert svg_has_style_attr(data, 'path', 'stroke-width', '0.5') + assert svg_has_style_attr(data, 'path', 'd', 'M.*', escape=False) + assert svg_has_style_attr( + data, 'path', 'transform', + 'matrix\\(1, *0, *0, *1, *10, *10\\)', escape=False + ) diff --git a/tests/graphicshelper/test_cairo_svg_helper.py b/tests/graphicshelper/test_cairo_svg_helper.py index 6eacc7a..e3fba07 100644 --- a/tests/graphicshelper/test_cairo_svg_helper.py +++ b/tests/graphicshelper/test_cairo_svg_helper.py @@ -5,6 +5,7 @@ from map_engraver.canvas import CanvasBuilder from map_engraver.canvas.canvas_unit import CanvasUnit as Cu from map_engraver.graphicshelper.cairo_svg_helper import CairoSvgHelper +from tests.utils import svg_has_style_attr class TestCairoSvgHelper(unittest.TestCase): @@ -37,8 +38,9 @@ def test_outputs_expected_lines(self): with open(path, 'r') as file: data = file.read() - assert data.find( + assert svg_has_style_attr( + data, 'path', 'd', 'M 10 10 L 90 10 ' # Top line 'M 90 90 L 10 90 ' # Bottom line 'M 10 50 L 50 10 L 90 50 L 50 90' # Inner Diamond - ) != -1 + ) diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..4ea3515 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,87 @@ +import unittest + +from tests.utils import svg_has_tag, svg_has_style_attr + + +real_svg = """ + + + """ + +real_svg_2 = """ + + + + +""" + + +class TestUtils(unittest.TestCase): + def test_svg_has_tag(self): + svg = '' + assert svg_has_tag(svg, 'myElements') + assert svg_has_tag(svg, 'myElement') + assert not svg_has_tag(svg, 'myElem') + assert not svg_has_tag(svg, 'missingElement') + + def test_svg_has_tag_real_svg(self): + assert svg_has_tag(real_svg, 'path') + assert svg_has_tag(real_svg, 'svg') + assert not svg_has_tag(real_svg, 'circle') + + def test_svg_has_tag_real_svg_2(self): + assert svg_has_tag(real_svg_2, 'svg') + assert svg_has_tag(real_svg_2, 'g') + assert svg_has_tag(real_svg_2, 'path') + + def test_svg_has_style_attr(self): + svg = '' + assert svg_has_style_attr(svg, 'myElement', 'myAttr') + assert not svg_has_style_attr(svg, 'myElem', 'myAttr') + assert not svg_has_style_attr(svg, 'missingElement', 'myAttr') + svg = '' + assert svg_has_style_attr(svg, 'path', 'fill', 'none') + for case in [ + '', + '', + '', + '', + '', + ]: + assert svg_has_style_attr(case, 'ele', 'attr') + assert svg_has_style_attr(case, 'ele', 'attr', 'm(0.0,2,43)') + assert svg_has_style_attr(case, 'ele', 'attr', r'.*', escape=False) + assert not svg_has_style_attr(case, 'ele', 'attr', 'm(0.1,2,43)') + assert not svg_has_style_attr(case, 'ele', 'attr2', 'm(0.0,2,43)') + + def test_svg_has_style_attr_real_svg(self): + assert svg_has_style_attr(real_svg, 'path', 'fill', 'none') + assert svg_has_style_attr(real_svg, 'svg', 'width', '100pt') + assert not svg_has_style_attr(real_svg, 'path', 'missing-prop', '0.5') + assert not svg_has_style_attr(real_svg, 'path', 'fill', 'fakeValue') + + def test_svg_has_style_attr_real_svg_2(self): + assert svg_has_style_attr( + real_svg_2, 'path', 'd', + 'M 30 30 L 70 30 L 70 70 L 30 70 Z M 30 30' + ) diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 0000000..8e9f01a --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,88 @@ +import re +import xml.etree.ElementTree as Et +from typing import Optional, Iterator + +ns_array = { + 'svg': 'http://www.w3.org/2000/svg', + 'xlink': 'http://www.w3.org/1999/xlink' +} + + +def svg_has_tag(svg: str, tag: str) -> bool: + el = Et.fromstring(svg) + if el.tag == tag or el.tag == '{' + ns_array['svg'] + '}' + tag: + return True + if el.find('.//' + tag, ns_array) is not None: + return True + if el.find('.//svg:' + tag, ns_array) is not None: + return True + return False + + +def _get_style_attr_value(style: str, attr: str) -> Optional[str]: + for style_prop in style.split(';'): + if style_prop.split(':')[0] == attr: + return style_prop.split(':')[1] + return None + + +def _get_attr_value(el: Et.Element, attr: str) -> Optional[str]: + if attr in el.attrib: + return el.attrib[attr] + if 'style' in el.attrib: + return _get_style_attr_value(el.attrib['style'], attr) + return None + + +def _svg_get_matches( + svg: str, + tag: str, + attr: str, + value: Optional[str] = None, + escape: bool = True, + trim: bool = True +) -> Iterator[Et.Element]: + el = Et.fromstring(svg) + matches = [] + matches.extend(el.findall('.//' + tag, ns_array)) + matches.extend(el.findall('.//svg:' + tag, ns_array)) + if value is not None and escape: + value = re.escape(value) + if el.tag == tag or el.tag == '{' + ns_array['svg'] + '}' + tag: + matches.append(el) + for match in matches: + match_value = _get_attr_value(match, attr) + if match_value is None: + continue + if trim: + match_value = match_value.strip() + if value is None: + yield match + if re.match(value, match_value) is not None: + yield match + + +def svg_has_style_attr( + svg: str, + tag: str, + attr: str, + value: Optional[str] = None, + escape: bool = True, + trim: bool = True +) -> bool: + for _ in _svg_get_matches(svg, tag, attr, value, escape=escape, trim=trim): + return True + return False + + +def svg_count_style_attr( + svg: str, + tag: str, + attr: str, + value: Optional[str] = None, + escape: bool = True, + trim: bool = True +) -> int: + return len(list( + _svg_get_matches(svg, tag, attr, value, escape=escape, trim=trim) + ))