21 Commits
Author SHA1 Message Date
hyugogirubato 15d7aaa094 Release v3.3.2 2024-07-18 00:04:25 +02:00
hyugogirubato 7800205e87 Release v3.3.2 2024-07-18 00:03:58 +02:00
hyugogirubato 963ecf9e6f Added zoom and scroll 2024-07-17 23:55:33 +02:00
hyugogirubato baee10d922 Format imports 2024-07-17 23:55:08 +02:00
hyugogirubato 140fd6c107 Format imports 2024-07-17 23:54:54 +02:00
hyugogirubato 7fceb86a7b Native extraction of ICO 2024-07-17 23:54:21 +02:00
hyugogirubato eec284a3ef New Contributors 2024-07-17 22:06:47 +02:00
hyugogirubato fe6d92229c Merge pull request #11 from gokender/fix-xmltodict-parse
Fix XML parsing for CBZ with one page
2024-07-17 22:03:38 +02:00
gokender 413f9d498e Fix XML parsing for CBZ with one page 2024-07-17 09:44:55 +02:00
hyugogirubato a90d9abf75 Simplification of the player icon 2024-07-16 22:45:27 +02:00
hyugogirubato 4fe38f0d5a Update CHANGELOG.md 2024-07-15 20:19:59 +02:00
hyugogirubato 153f5f79c5 Fixed lag when stretching player 2024-07-15 20:19:09 +02:00
hyugogirubato 0947e1904b New Contributors 2024-07-15 19:54:41 +02:00
hyugogirubato 7f1060fc30 Release v3.3.1 2024-07-15 19:51:54 +02:00
hyugogirubato df54489eef Add from_pdf method 2024-07-15 19:45:38 +02:00
hyugogirubato 68e843af63 Change quit keyboard shortcut to allow clipboard 2024-07-15 19:19:36 +02:00
hyugogirubato 4b2c47b4b8 Fix minimum player dimensions 2024-07-15 19:18:26 +02:00
hyugogirubato 74a6a0e9b6 Fix player border margin 2024-07-15 19:12:22 +02:00
hyugogirubato 82e1764c2e Fix windows taskbar player icon 2024-07-15 19:05:13 +02:00
hyugogirubato f62a508d9a Merge pull request #9 from flolep2607/fix-linux-player
fix: cbzplayer icon  for linux
2024-07-15 18:55:00 +02:00
flolep2607 90abd137c5 fix: cbzplayer icon for linux 2024-07-14 20:26:05 +02:00
10 changed files with 437 additions and 44 deletions
+2 -1
View File
@@ -171,4 +171,5 @@ poetry.toml
pyrightconfig.json
### CBZ ###
.cbz
*.cbz
*.pdf
+45
View File
@@ -4,6 +4,49 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.3.2] - 2024-07-18
### Added
- Added zoom options for displaying images in the player.
- Added scroll functionality for image display in the player, especially useful when images are zoomed.
### Changed
- Set a default standard size.
### Fixed
- Fix lag when stretching player.
- Fix XML parsing for CBZ files with a single page.
- Fix image positioning within the player.
### New Contributors
- [gokender](https://github.com/gokender)
## [3.3.1] - 2024-07-15
### Added
- Added `from_pdf` method to convert `.pdf` files to `.cbz`.
### Changed
- Set a default standard size.
- Changed a keyboard shortcut that prevented copying information.
### Fixed
- Fixed the icon display for Linux in the player.
- Fixed the taskbar icon for Windows in the player.
- Fixed the player margins.
- Automatically detect the player size based on the smallest image.
### New Contributors
- [flolep2607](https://github.com/flolep2607)
## [3.3.0] - 2024-07-14
### Added
@@ -82,6 +125,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Initial release.
[3.3.2]: https://github.com/hyugogirubato/cbz/releases/tag/v3.3.2
[3.3.1]: https://github.com/hyugogirubato/cbz/releases/tag/v3.3.1
[3.3.0]: https://github.com/hyugogirubato/cbz/releases/tag/v3.3.0
[3.2.0]: https://github.com/hyugogirubato/cbz/releases/tag/v3.2.0
[3.1.2]: https://github.com/hyugogirubato/cbz/releases/tag/v3.1.2
+3
View File
@@ -150,6 +150,9 @@ comic_from_cbz = ComicInfo.from_cbz('/path/to/your_comic.cbz')
<a href="https://github.com/OleskiiPyskun"><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/75667382?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="OleskiiPyskun"/></a>
<a href="https://github.com/domenicoblanco"><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/9018104?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="domenicoblanco"/></a>
<a href="https://github.com/RivMt"><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/40086827?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="RivMt"/></a>
<a href="https://github.com/flolep2607"><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/24566964?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="flolep2607"/></a>
<a href="https://github.com/gokender"><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3709740?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="gokender"/></a>
## Licensing
+47 -3
View File
@@ -1,12 +1,15 @@
from __future__ import annotations
import zipfile
from enum import Enum
from io import BytesIO
from typing import Union
from functools import cache
from pathlib import Path
import fitz
import xmltodict
from cbz.constants import XML_NAME, COMIC_FIELDS, IMAGE_FORMAT, PAGE_FIELDS
@@ -64,10 +67,51 @@ class ComicInfo(ComicModel):
"""
if not isinstance(path, (Path, str)):
raise ValueError(f'Expecting Path object or path string, got {path!r}')
return cls.__unpack(path)
return cls.__unpack_zip(path)
@classmethod
def from_pdf(cls, path: Union[Path, str]) -> ComicInfo:
"""
Create a ComicInfo instance from a PDF file.
Args:
path (Union[Path, str]): Path to the PDF file.
Returns:
ComicInfo: An instance of ComicInfo.
Raises:
ValueError: If the provided path is not a Path object or a string.
"""
if not isinstance(path, (Path, str)):
raise ValueError(f'Expecting Path object or path string, got {path!r}')
return cls.__unpack_pdf(path)
@staticmethod
def __unpack(path: Path) -> ComicInfo:
def __unpack_pdf(path: Path) -> ComicInfo:
"""
Unpack a PDF file and create a ComicInfo instance.
Args:
path (Path): Path to the PDF file.
Returns:
ComicInfo: An instance of ComicInfo.
"""
pages: list[PageInfo] = []
with fitz.open(path) as pf:
for element in pf:
# Check if the page has images
images = element.get_images(full=True)
for i, image in enumerate(images):
base = pf.extract_image(image[0])
pages.append(PageInfo.loads(data=base['image']))
assert pages, 'No valid images present in file'
return ComicInfo.from_pages(pages=pages)
@staticmethod
def __unpack_zip(path: Path) -> ComicInfo:
"""
Unpack a CBZ file and create a ComicInfo instance.
@@ -103,7 +147,7 @@ class ComicInfo(ComicModel):
if XML_NAME in names:
with zf.open(XML_NAME, 'r') as f:
comic_info = xmltodict.parse(f.read()).get('ComicInfo', {})
comic_info = xmltodict.parse(f.read(), force_list=('Pages',)).get('ComicInfo', {})
names.remove(XML_NAME)
comic = __info(
+1
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
import base64
from io import BytesIO
from typing import Union
+172 -31
View File
@@ -1,15 +1,21 @@
import hashlib
import tkinter as tk
import os
from io import BytesIO
from tkinter import ttk
from tkinter.constants import DISABLED, NORMAL
from ctypes import windll
from PIL import Image, ImageTk
from pathlib import Path
from cbz.comic import ComicInfo
from cbz.page import PageInfo
from cbz.utils import readable_size
from cbz.utils import readable_size, ico_to_png
PARENT = Path(__file__).parent
CTRL_KEY = 0x4 # Constant for Ctrl key
class Player:
@@ -33,6 +39,10 @@ class Player:
page_index_label (ttk.Label): Label showing the current page index.
previous_width (int): Previous width of the main window.
previous_height (int): Previous height of the main window.
resize_timer (int or None): Timer ID for handling window resize delay.
max_zoom_factor (float or None): Maximum allowable zoom factor based on canvas size and image dimensions.
zoom_factor (float or None): Current zoom factor for image display.
img_original (PIL.Image.Image or None): Placeholder for the original image to be displayed.
"""
def __init__(self, comic_info: ComicInfo):
@@ -44,6 +54,9 @@ class Player:
"""
self.comic_info = comic_info
self.current_page = -1 # Track the current page index
self.max_zoom_factor = None # Maximum allowable zoom factor based on canvas size and image dimensions
self.zoom_factor = None # Initial zoom factor (None means no zoom initially)
self.img_original = None # Placeholder for the original image
# Initialize tkinter window
self.root = tk.Tk()
@@ -52,8 +65,8 @@ class Player:
# Set initial window size
self.root.geometry(self._get_initial_geometry())
# Set window icon
self.root.iconbitmap(Path(__file__).parent / 'cbz.ico')
# Set the application icon
self._set_icon()
# Create main frame for content
self.main_frame = ttk.Frame(self.root)
@@ -79,6 +92,23 @@ class Player:
self.previous_width = self.root.winfo_width()
self.previous_height = self.root.winfo_height()
# Initialize resize timer
self.resize_timer = None
def _set_icon(self) -> None:
"""
Set the application icon for the window.
"""
image_path = PARENT / 'cbz.ico'
if os.name == 'nt':
# Set the application ID and icon on Windows
windll.shell32.SetCurrentProcessExplicitAppUserModelID('cbz.player')
self.root.iconbitmap(image_path)
else:
# Convert ICO to PNG for other operating systems
image = ico_to_png(image_path)
self.root.iconphoto(True, tk.PhotoImage(data=image.getvalue()))
def _get_window_title(self) -> str:
"""
Get the window title based on the comic series and title.
@@ -87,7 +117,7 @@ class Player:
str: Window title.
"""
if self.comic_info.series and self.comic_info.title:
return f"{self.comic_info.series} - {self.comic_info.title}"
return f'{self.comic_info.series} - {self.comic_info.title}'
return self.comic_info.title or self.__class__.__name__
def _get_initial_geometry(self) -> str:
@@ -105,21 +135,37 @@ class Player:
available_width = self.root.winfo_screenwidth() - 2 * margin_width
available_height = self.root.winfo_screenheight() - 2 * margin_height
# Default screen size for initialization
screen_width = int(available_height * 0.63)
screen_height = int(available_height)
# Calculate scaling factors for width and height
if self.comic_info.pages:
first_page = self.comic_info.pages[0]
scale_width = available_width / first_page.image_width
scale_height = available_height / first_page.image_height
# Get the minimum dimensions from all pages
image_width = self.comic_info.pages[0].image_width
image_height = self.comic_info.pages[0].image_height
for page in self.comic_info.pages[1:]:
if page.image_width <= image_width and page.image_height <= image_height:
image_width = page.image_width
image_height = page.image_height
scale_width = available_width / image_width
scale_height = available_height / image_height
# Choose the smaller scaling factor to maintain proportions
scale_factor = min(scale_width, scale_height)
# Calculate new dimensions
initial_width = int(first_page.image_width * scale_factor)
initial_height = int(first_page.image_height * scale_factor)
initial_width = int(image_width * scale_factor * 0.94)
initial_height = int(image_height * scale_factor)
else:
initial_width = int(available_width)
initial_height = int(available_height)
# If no pages are available, default to screen size
initial_width = screen_width
initial_height = screen_height
# Ensure that the window's initial width is at least 50% of the screen width
if 100 / screen_width * initial_width < 50.0:
initial_width = screen_width
# Calculate initial position to center the window on the screen
x = self.root.winfo_screenwidth() // 2 - initial_width // 2
@@ -160,7 +206,7 @@ class Player:
self.summary_text.tag_configure('normal', font=('Arial', 12), lmargin1=10, lmargin2=10)
self.summary_text.config(state=DISABLED)
def show_page(self):
def show_page(self) -> None:
"""
Display the current page content (either summary or image).
"""
@@ -213,26 +259,40 @@ class Player:
# Display image centered on canvas
page: PageInfo = self.comic_info.pages[self.current_page]
img = Image.open(BytesIO(page.content))
self.img_original = Image.open(BytesIO(page.content))
self._display_image()
# Calculate scaling factor
scale_width = self.canvas.winfo_width() / img.width
scale_height = self.canvas.winfo_height() / img.height
scale_factor = min(scale_width, scale_height)
def _display_image(self) -> None:
"""
Display the image on the canvas with zooming capabilities.
"""
# Check if zoom factor is not set; initialize zoom factors
if not self.zoom_factor:
# Determine maximum zoom factor based on canvas size and original image size
self.max_zoom_factor = min(
self.canvas.winfo_width() / self.img_original.width,
self.canvas.winfo_height() / self.img_original.height
)
self.zoom_factor = self.max_zoom_factor
# Resize image
new_width = int(img.width * scale_factor)
new_height = int(img.height * scale_factor)
img = img.resize((new_width, new_height), Image.LANCZOS)
# Calculate new dimensions of the image based on current zoom factor
new_width = int(self.img_original.width * self.zoom_factor)
new_height = int(self.img_original.height * self.zoom_factor)
img = self.img_original.resize((new_width, new_height), Image.Resampling.LANCZOS)
# Set image on canvas
# Convert the resized image to PhotoImage format compatible with Tkinter canvas
self.canvas.image = ImageTk.PhotoImage(img)
# Calculate coordinates to center the image on the canvas
x = (self.canvas.winfo_width() - new_width) // 2
y = (self.canvas.winfo_height() - new_height) // 2
# Calculate the position to center the image on the canvas
x = max(0, (self.canvas.winfo_width() - new_width) // 2)
y = max(0, (self.canvas.winfo_height() - new_height) // 2)
self.canvas.create_image(x, y, anchor=tk.NW, image=self.canvas.image)
# Configure the scroll region of the canvas to allow scrolling if image is larger than canvas
canvas_width = max(new_width, self.canvas.winfo_width())
canvas_height = max(new_height, self.canvas.winfo_height())
self.canvas.config(scrollregion=(0, 0, canvas_width, canvas_height))
def _bind_keys(self) -> None:
"""
Bind keys for navigation (left/right arrow keys) and window events.
@@ -241,17 +301,77 @@ class Player:
self.root.bind('<Left>', lambda event: self.on_previous())
self.root.bind('<Right>', lambda event: self.one_next())
# Bind Ctrl+C to exit application
self.root.bind('<Control-c>', lambda event: self.root.quit())
# Bind Ctrl+Q to exit application
self.root.bind('<Control-q>', lambda event: self.root.quit())
# Bind the configure event to handle window resize
self.root.bind('<Configure>', lambda event: self.on_window(event))
# Bind mouse wheel events for zooming
self.root.bind('<Control-MouseWheel>', self.on_zoom)
self.canvas.bind_all("<MouseWheel>", self._on_mouse_wheel)
self.canvas.bind_all("<Shift-MouseWheel>", self._on_shift_mouse_wheel)
# Bind zoom controls to keyboard keys
self.root.bind('<KeyPress-plus>', lambda event: self.on_zoom_key(True))
self.root.bind('<KeyPress-minus>', lambda event: self.on_zoom_key(False))
def on_zoom_key(self, positive: bool) -> None:
"""
Handle zooming triggered by keyboard keys ('+' for zoom in, '-' for zoom out).
Args:
positive (bool): True for zoom in, False for zoom out.
"""
# Create a synthetic event object to simulate mouse wheel scrolling
event = tk.Event()
event.delta = 120 if positive else -120
self.on_zoom(event)
def on_zoom(self, event) -> None:
"""
Handle zooming using Ctrl + Mouse Wheel.
"""
if self.current_page == -1: return
# Adjust zoom factor based on mouse wheel direction
if event.delta > 0:
# Increase zoom factor by 10% for zoom in
self.zoom_factor *= 1.1
elif event.delta < 0:
# Decrease zoom factor by 10% for zoom out
self.zoom_factor /= 1.1
# Ensure the zoom-out factor doesn't go below the original image size
min_zoom_factor = min(
self.canvas.winfo_width() / self.img_original.width,
self.canvas.winfo_height() / self.img_original.height
)
if self.zoom_factor < min_zoom_factor:
self.zoom_factor = min_zoom_factor
# Update the displayed image with the new zoom factor
self._display_image()
def _on_mouse_wheel(self, event) -> None:
"""
Handle vertical scroll using Mouse Wheel.
"""
if self.current_page == -1 or (event.state & CTRL_KEY): return
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
def _on_shift_mouse_wheel(self, event) -> None:
"""
Handle horizontal scroll using Shift + Mouse Wheel.
"""
if self.current_page == -1 or (event.state & CTRL_KEY): return
self.canvas.xview_scroll(int(-1 * (event.delta / 120)), "units")
def on_previous(self) -> None:
"""
Navigate to the previous page.
"""
if self.current_page > -1:
if self.current_page == -1: return
self.current_page -= 1
self.show_page()
@@ -271,8 +391,29 @@ class Player:
if event.width != self.previous_width or event.height != self.previous_height:
self.previous_width = event.width
self.previous_height = event.height
# Update the image display on canvas when the window size changes
self.show_page()
# Cancel any existing resize timer
if self.resize_timer:
self.root.after_cancel(self.resize_timer)
# Set a new timer to call show_page after a delay
self.resize_timer = self.root.after(200, self._on_resize)
def _on_resize(self) -> None:
"""
Handle resizing of the window and adjust image display accordingly.
"""
if self.current_page == -1: return
# Reset zoom factor to None if it's equal to the maximum zoom factor
if self.zoom_factor == self.max_zoom_factor:
self.zoom_factor = None
# Update the displayed image with the current zoom factor
self._display_image()
# Reset the resize timer
self.resize_timer = None
def run(self) -> None:
"""
+30
View File
@@ -1,4 +1,9 @@
from enum import Enum
from io import BytesIO
from PIL import Image
from PIL.IcoImagePlugin import IcoFile
from path import Path
def default_attr(value: any) -> any:
@@ -77,3 +82,28 @@ def readable_size(size: int, decimal: int = 2) -> str:
if size < 1024:
return f'{size:.{decimal}f} {unit}'
size /= 1024
def ico_to_png(path: Path) -> BytesIO:
"""
Converts the largest icon in an ICO file to PNG format.
Args:
path (Path): Path to the ICO file.
Returns:
BytesIO: In-memory PNG file of the largest icon.
"""
# Open the ICO file and read its content
image = Image.open(BytesIO(path.read_bytes()))
assert image.format == 'ICO', 'Unsupported image format'
# Get the ICO file object and find the largest icon size
icon: IcoFile = image.ico
max_size = max(icon.sizes(), key=lambda x: x[0] + x[1])
largest_image = icon.getimage(size=max_size)
# Save the largest icon as PNG format to an in-memory BytesIO object
content = BytesIO()
largest_image.save(content, format='PNG')
return content
+51
View File
@@ -0,0 +1,51 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" viewBox="0 0 512 512">
<defs>
<clipPath id="clip-favicon">
<rect width="512" height="512"/>
</clipPath>
</defs>
<g id="favicon" clip-path="url(#clip-favicon)">
<g id="clipboard" transform="translate(-23.514 -24.026)">
<g id="_000000ff" data-name="#000000ff" transform="translate(23.966 24.026)">
<path id="Path_1" data-name="Path 1" d="M169.389,31.663c.738-3.359,3.051-6.52,6.531-7.335,4.846-1.377,8.954,2.28,12.808,4.6,43.612,29.3,76.068,74.56,90.341,125.088.363,1.817,1.278-.463,1.333-1.046,8.733-27.819,26.068-52.313,47.1-72.225,24.086-22.775,52.72-40.4,83.073-53.491,3.579-1.344,7.148-3.491,11.1-3.15a8.832,8.832,0,0,1,7.511,7.577c1.6,8.767,2.963,17.588,4.5,26.366,15.154-5.4,30.3-10.87,45.573-15.914a8.733,8.733,0,0,1,10.87,4.692c4.78,10.628,9.251,21.41,13.976,32.071,5.991-3.106,11.861-6.454,17.885-9.493a8.785,8.785,0,0,1,11.267,2.5c1.6,2,1.718,4.648,1.762,7.093q-.033,159.185-.011,318.381c-.066,4.053.275,8.128-.275,12.159-.562,3.227-3.315,5.374-6.046,6.806Q429.13,469.256,329.709,522.4c-6.806,3.557-13.447,7.632-20.9,9.747a112.762,112.762,0,0,1-36.465,3.7c-11.322-.7-22.819-2.742-32.93-8.117q-102.72-54.7-205.43-109.482c-3.392-1.927-7.72-3.348-9.273-7.291-1.09-3.293-.628-6.839-.727-10.242q.1-161.415.044-322.842a8.992,8.992,0,0,1,5.33-8.844c2.941-1.388,6.322-.518,9.009,1.024,7.709,4.108,15.4,8.249,23.117,12.335,2.357-11.366,4.427-22.8,6.916-34.141.98-4.692,6.156-7.544,10.716-6.377,28.051,4.5,54.736,15.1,80.121,27.61q5.039-18.932,10.154-37.819M360.546,75.5c-19.714,14.736-37.8,32.4-50.176,53.844,30.143-29.229,67.7-49.5,106.509-64.758-.991-6.52-2.225-13-3.2-19.515A266.629,266.629,0,0,0,360.546,75.5M175.1,78.259C204.686,95.352,231.68,116.685,256,140.638c-14.482-37.236-39.615-70.661-72.39-93.656-3.018,10.374-5.628,20.87-8.5,31.278M83.761,60.616C81.845,70.782,79.719,80.9,77.737,91.057,134.059,120.947,190.259,151.09,246.57,181c8.48,3.106,17.632,3.976,26.575,4.725C237.4,142.268,193.211,105.088,142.164,80.9c-18.678-8.756-38.161-16.09-58.4-20.286m293.745,41.575a255.536,255.536,0,0,0-91.564,83.557c9.1-.848,18.447-1.674,27.037-4.945q87.737-46.867,175.529-93.59-5.617-12.885-11.178-25.782c-34.009,11.608-68.282,23.271-99.824,40.76M41.636,91.784c.055,103.579-.154,207.148.1,310.727q3.948,1.949,7.83,4.053c5.551,3.172,11.222,6.167,16.938,9.031v.165c1.905.98,3.811,1.971,5.694,2.974q81.608,43.563,163.238,87.06.05-152.66,0-305.32c-.011-1.828-.022-3.656-.044-5.474Q138.469,143.458,41.636,91.784M323.629,195.022c-.066,3.2-.077,6.4-.066,9.6q.033,150.595.022,301.2,93.866-49.84,187.577-99.945l-.055-.385c2.048-.936,4.1-1.905,6.156-2.852.308-103.6.044-207.225.132-310.837q-96.889,51.608-193.767,103.216m-70.507,5.991q-.1,137.049.011,274.1c12.974,1.806,26.178,2.654,39.251,1.355a119.414,119.414,0,0,0,13.557-1.586q-.017-137,0-274c-.925.187-2.753.551-3.667.738-12.148,1.6-24.416,2.533-36.652,1.289v-.33c-1.949-.154-3.9-.319-5.848-.485-2.225-.319-4.438-.694-6.652-1.079m-.033,291.74q-.033,11.085.011,22.17c2.709.793,5.441,1.531,8.15,2.346l4.284.661c10.385,1.189,21.1,1.4,31.344-.936a73.568,73.568,0,0,0,8.965-2.1c.2-7.357.055-14.714.1-22.059-4.042.352-8.106.584-12.1,1.311A214.472,214.472,0,0,1,253.09,492.753Z" transform="translate(-23.966 -24.026)"/>
<path id="Path_2" data-name="Path 2" d="M457.7,142.458c5.264-3.128,12.742,1.057,12.786,7.181.242,18.018.066,36.046.088,54.064a9.319,9.319,0,0,1-5.507,8.756q-67.318,35.7-134.659,71.322c-3.095,1.542-6.09,3.733-9.659,3.855a8.814,8.814,0,0,1-8.689-8.855c-.121-17.7-.044-35.4-.033-53.095a9.162,9.162,0,0,1,5.253-8.932q70.209-37.153,140.419-74.3M329.611,230.167c.011,1.476.011,2.941.022,4.416-.033,9.945,0,19.89-.011,29.824Q388.8,233.1,447.937,201.731c1.641-.947,3.3-1.839,4.978-2.72.121-11.388.022-22.775.055-34.163Q391.3,197.524,329.611,230.167Z" transform="translate(5.217 -12.134)"/>
<path id="Path_3" data-name="Path 3" d="M253.906,212.509c5.419-2.148,11.905,2.445,11.663,8.271.132,53.954.022,107.919.055,161.883.374,4.251-2.313,8.623-6.564,9.637-5.308,1.619-11.245-2.918-11-8.469-.121-54-.022-108-.055-161.993A9.061,9.061,0,0,1,253.906,212.509Z" transform="translate(-1.269 -4.983)"/>
<path id="Path_4" data-name="Path 4" d="M253.861,384.521c5.408-2.17,11.916,2.39,11.707,8.2.143,8.48.033,16.971.044,25.463a9.075,9.075,0,0,1-5.892,9.35c-5.374,2.137-11.861-2.39-11.652-8.172q-.182-13.315-.011-26.641A8.733,8.733,0,0,1,253.861,384.521Z" transform="translate(-1.268 12.444)"/>
</g>
<g id="_fcf3e7ff" data-name="#fcf3e7ff" transform="translate(77.737 45.066)">
<path id="Path_5" data-name="Path 5" d="M334.2,73.56a266.629,266.629,0,0,1,53.128-30.43c.98,6.52,2.214,13,3.2,19.515C351.718,77.9,314.163,98.174,284.02,127.4,296.4,105.96,314.483,88.3,334.2,73.56Z" transform="translate(-51.388 -43.13)" fill="#fcf3e7"/>
<path id="Path_6" data-name="Path 6" d="M161.2,76.148c2.874-10.407,5.485-20.9,8.5-31.278,32.775,23,57.908,56.421,72.39,93.656C217.775,114.573,190.782,93.24,161.2,76.148Z" transform="translate(-63.832 -42.954)" fill="#fcf3e7"/>
<path id="Path_7" data-name="Path 7" d="M78.814,57.25c20.242,4.2,39.725,11.531,58.4,20.286C188.264,101.721,232.449,138.9,268.2,182.36c-8.943-.749-18.095-1.619-26.575-4.725C185.312,147.724,129.112,117.58,72.79,87.691,74.772,77.536,76.9,67.415,78.814,57.25Z" transform="translate(-72.79 -41.699)" fill="#fcf3e7"/>
<path id="Path_8" data-name="Path 8" d="M353.4,98.75c31.542-17.489,65.815-29.152,99.824-40.76q5.551,12.9,11.178,25.782-87.7,46.9-175.529,93.59c-8.59,3.271-17.941,4.1-27.037,4.945A255.536,255.536,0,0,1,353.4,98.75Z" transform="translate(-53.635 -41.624)" fill="#fcf3e7"/>
</g>
<g id="_c68315ff" data-name="#c68315ff" transform="translate(41.606 91.784)">
<path id="Path_9" data-name="Path 9" d="M40.013,85.55q96.905,51.542,193.756,103.216c.022,1.817.033,3.645.044,5.474-7.2-3.414-14.152-7.335-21.2-11.057-47.2-25.242-94.5-50.286-141.707-75.54q-2.874-1.569-5.782-3.073c-5.595-2.919-11.1-6.013-16.751-8.822-.3,5.573-.319,11.156-.231,16.729q.05,115.655.011,231.289c-.132,18.855.275,37.72-.209,56.564q-3.882-2.1-7.83-4.053C39.859,292.7,40.068,189.129,40.013,85.55Z" transform="translate(-39.983 -85.55)" fill="#c68315"/>
</g>
<g id="_e2910dff" data-name="#e2910dff" transform="translate(292.385 91.806)">
<path id="Path_10" data-name="Path 10" d="M296.066,188.786Q393.021,137.31,489.833,85.57c-.088,103.612.176,207.236-.132,310.837-2.059.947-4.108,1.916-6.156,2.852-.3-1.971-.584-3.954-.7-5.936q0-147.093.011-294.218a127.8,127.8,0,0,0-14.394,7.291C411,137.112,353.379,167.53,296,198.389,295.989,195.185,296,191.991,296.066,188.786Z" transform="translate(-264.822 -85.57)" fill="#e2910d"/>
<path id="Path_11" data-name="Path 11" d="M277.58,185.348c.914-.187,2.742-.551,3.667-.738q.017,137,0,274a119.414,119.414,0,0,1-13.557,1.586c2.709-.529,5.385-1.255,8.073-1.916q.2-128.921.055-257.842C276,195.414,274.849,189.907,277.58,185.348Z" transform="translate(-267.69 -75.535)" fill="#e2910d"/>
<path id="Path_12" data-name="Path 12" d="M269.01,451.011c4-.727,8.062-.958,12.1-1.311-.044,7.346.1,14.7-.1,22.06a73.568,73.568,0,0,1-8.965,2.1c1.211-.9,2.4-1.839,3.579-2.775.1-6.729.143-13.458-.077-20.187C273.371,450.922,271.191,450.944,269.01,451.011Z" transform="translate(-267.556 -48.675)" fill="#e2910d"/>
</g>
<g id="_f8a928ff" data-name="#f8a928ff" transform="translate(49.565 101.982)">
<path id="Path_13" data-name="Path 13" d="M47.408,111.539c-.088-5.573-.066-11.156.231-16.729,5.65,2.808,11.156,5.9,16.751,8.822-.43,46.685-.055,93.37-.176,140.055-.033,54.912.055,109.824-.066,164.736-5.716-2.863-11.388-5.859-16.938-9.031.485-18.844.077-37.709.209-56.564Q47.4,227.189,47.408,111.539Z" transform="translate(-47.21 -94.81)" fill="#f8a928"/>
<path id="Path_14" data-name="Path 14" d="M468.456,105.151a127.8,127.8,0,0,1,14.394-7.291q-.05,147.109-.011,294.218c.121,1.982.408,3.965.7,5.936l.055.385q-93.833,49.873-187.577,99.945-.083-150.611-.022-301.2c57.379-30.859,115-61.278,172.456-91.993m-9.141,41.718q-70.242,37.071-140.419,74.3a9.162,9.162,0,0,0-5.253,8.932c-.011,17.7-.088,35.4.033,53.095a8.814,8.814,0,0,0,8.689,8.855c3.568-.121,6.564-2.313,9.659-3.855q67.318-35.65,134.659-71.322a9.319,9.319,0,0,0,5.507-8.756c-.022-18.018.154-36.046-.088-54.064C472.058,147.926,464.58,143.741,459.315,146.869Z" transform="translate(-22.002 -94.501)" fill="#f8a928"/>
<path id="Path_15" data-name="Path 15" d="M68.09,105.61c47.2,25.253,94.5,50.3,141.707,75.54,7.048,3.722,14,7.643,21.2,11.057q.066,152.66,0,305.32-81.625-43.5-163.238-87.06c.231-64.02.022-128.04.1-192.06C68.024,180.808,67.573,143.2,68.09,105.61Z" transform="translate(-45.128 -93.716)" fill="#f8a928"/>
<path id="Path_16" data-name="Path 16" d="M232.045,184.73c2.214.385,4.427.76,6.652,1.079.22,91.134.055,182.269.1,273.4,1.861.132,3.711.253,5.573.374.363-90.98.044-181.971.176-272.963,12.236,1.244,24.5.308,36.652-1.289-2.731,4.559-1.575,10.066-1.762,15.088q-.033,128.921-.055,257.842c-2.687.661-5.363,1.388-8.073,1.916-13.073,1.3-26.278.452-39.251-1.355q-.149-137.049-.011-274.1m23.48,30.54a9.061,9.061,0,0,0-5.9,9.328c.033,54-.066,108,.055,161.994-.242,5.551,5.694,10.088,11,8.469,4.251-1.013,6.938-5.385,6.564-9.637-.033-53.965.077-107.93-.055-161.883.242-5.826-6.245-10.419-11.663-8.271m-.044,189.438a8.733,8.733,0,0,0-5.8,8.2q-.165,13.315.011,26.641c-.209,5.782,6.278,10.308,11.652,8.172a9.075,9.075,0,0,0,5.892-9.35c-.011-8.491.1-16.982-.044-25.463C267.4,407.1,260.889,402.539,255.481,404.708Z" transform="translate(-28.488 -85.699)" fill="#f8a928"/>
<path id="Path_17" data-name="Path 17" d="M232.011,449.63a214.472,214.472,0,0,0,40.749,1.388c2.181-.066,4.361-.088,6.542-.11.22,6.729.176,13.458.077,20.187-1.178.936-2.368,1.872-3.579,2.775-10.242,2.335-20.958,2.126-31.344.936.066-7.775.407-15.573-.363-23.326-1.652-.319-3.293-.65-4.934-.969-.4,6.09-.573,12.2-.374,18.3a12.568,12.568,0,0,0,1.388,5.33c-2.709-.815-5.441-1.553-8.15-2.346Q231.973,460.715,232.011,449.63Z" transform="translate(-28.487 -58.859)" fill="#f8a928"/>
</g>
<g id="_fabf5dff" data-name="#fabf5dff" transform="translate(66.504 110.804)">
<path id="Path_18" data-name="Path 18" d="M62.832,102.82q2.907,1.5,5.782,3.073c-.518,37.588-.066,75.2-.231,112.8-.077,64.02.132,128.04-.1,192.06-1.883-1-3.789-1.993-5.694-2.974v-.165c.121-54.912.033-109.824.066-164.736C62.777,196.19,62.4,149.505,62.832,102.82Z" transform="translate(-62.59 -102.82)" fill="#fabf5d"/>
</g>
<g id="_d9d9d9ff" data-name="#d9d9d9ff" transform="translate(358.794 176.74)">
<path id="Path_19" data-name="Path 19" d="M327.99,228.009q61.669-32.676,123.359-65.319c-.033,11.388.066,22.775-.055,34.163-1.674.881-3.337,1.773-4.978,2.72-.154-9.78.187-19.559-.2-29.328-39.515,20.441-78.557,41.8-118.106,62.181C328,230.95,328,229.485,327.99,228.009Z" transform="translate(-327.99 -162.69)" fill="#d9d9d9"/>
</g>
<g id="_ffffffff" data-name="#ffffffff" transform="translate(358.801 184.295)">
<path id="Path_20" data-name="Path 20" d="M328.011,231.731c39.548-20.385,78.59-41.74,118.106-62.181.385,9.769.044,19.548.2,29.328Q387.241,230.365,328,261.554C328.011,251.621,327.978,241.676,328.011,231.731Z" transform="translate(-327.996 -169.55)" fill="#fff"/>
</g>
<g id="_f8ba55ff" data-name="#f8ba55ff" transform="translate(259.775 202.092)">
<path id="Path_21" data-name="Path 21" d="M238.08,185.71c1.949.165,3.9.33,5.848.485v.33c-.132,90.991.187,181.983-.176,272.963-1.861-.121-3.711-.242-5.573-.374C238.135,367.979,238.3,276.844,238.08,185.71Z" transform="translate(-238.08 -185.71)" fill="#f8ba55"/>
<path id="Path_22" data-name="Path 22" d="M238.168,468.734c-.2-6.1-.022-12.214.374-18.3,1.641.319,3.282.65,4.934.969.771,7.753.43,15.551.363,23.326l-4.284-.661A12.568,12.568,0,0,1,238.168,468.734Z" transform="translate(-238.079 -158.888)" fill="#f8ba55"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

Generated
+82 -6
View File
@@ -256,20 +256,96 @@ type = "legacy"
url = "https://pypi.org/simple"
reference = "localpypi"
[[package]]
name = "pymupdf"
version = "1.24.7"
description = "A high performance Python library for data extraction, analysis, conversion & manipulation of PDF (and other) documents."
optional = false
python-versions = ">=3.8"
files = [
{file = "PyMuPDF-1.24.7-cp310-none-macosx_10_9_x86_64.whl", hash = "sha256:9b6984d57e127e016231b2e89b247f2b0fef07af84d4cc91e4893c6d3fde52c7"},
{file = "PyMuPDF-1.24.7-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:7b8405aac8011b445ceb1bc2d4f4c44b2c969024b301f1178399e0084541d747"},
{file = "PyMuPDF-1.24.7-cp310-none-manylinux2014_aarch64.whl", hash = "sha256:ada392c739f43608611d430305c92d1b8922f66a07bc36a4ea0c7f3f9c1b5dd2"},
{file = "PyMuPDF-1.24.7-cp310-none-manylinux2014_x86_64.whl", hash = "sha256:7a59e24873e6d135f9c07be9f47d98502171210957819c8ffa9a7cca1cac1fb8"},
{file = "PyMuPDF-1.24.7-cp310-none-musllinux_1_2_x86_64.whl", hash = "sha256:bdd9a1b703e3fedd9836d54a13b89ddf772a6eaea3b1e34dcd682b8f0b5b7123"},
{file = "PyMuPDF-1.24.7-cp310-none-win32.whl", hash = "sha256:3a2e8af6e2ef437c4e599c7e520299ea10ef02680be0a8533f78d6ee489c5a60"},
{file = "PyMuPDF-1.24.7-cp310-none-win_amd64.whl", hash = "sha256:8293773e973cf07f5d6398699d5d98151a025c9db04a333fd55a87c8f8c3c74b"},
{file = "PyMuPDF-1.24.7-cp311-none-macosx_10_9_x86_64.whl", hash = "sha256:11770619a1d5b90f5f81cc22c11967b2f473310fc9a8f2aa96c1aabff5971c63"},
{file = "PyMuPDF-1.24.7-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:5e9b6018b3af45c6ca04adb0441369eefc0d66e5023f8d54befde9bb4f078c5a"},
{file = "PyMuPDF-1.24.7-cp311-none-manylinux2014_aarch64.whl", hash = "sha256:40743cbfa40a35e873d4b8642709f45849b3315292957d836be647cdd74d1107"},
{file = "PyMuPDF-1.24.7-cp311-none-manylinux2014_x86_64.whl", hash = "sha256:44f4c58040c496fcfc0719df17dab60348c7988d874c5e17233fa664dcf0a984"},
{file = "PyMuPDF-1.24.7-cp311-none-musllinux_1_2_x86_64.whl", hash = "sha256:0d7e8d2155bdc6e61242bdbf5dff2f6d0118f1a3f9e5d83db334a5cf71c90c5f"},
{file = "PyMuPDF-1.24.7-cp311-none-win32.whl", hash = "sha256:3ea0bb27512e72225822d98b6747b51b02de84cc1e17a5579d90ad957760de03"},
{file = "PyMuPDF-1.24.7-cp311-none-win_amd64.whl", hash = "sha256:785c8a40fd5d76b47759f4ade6db0b78a799bb1fb2dd61bbe59784538299ee21"},
{file = "PyMuPDF-1.24.7-cp312-none-macosx_10_9_x86_64.whl", hash = "sha256:999f40a6ead5aaad0c9e23b3c2ed009080bf51be9485ae122ff2cedd6487874b"},
{file = "PyMuPDF-1.24.7-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:03facd26907dcbba63429e8b56fdbabd717f22fb6d24b38bdefc591b309ce437"},
{file = "PyMuPDF-1.24.7-cp312-none-manylinux2014_aarch64.whl", hash = "sha256:7ec6da974092de0f842f9ef0e355c58a5529c2d5ec792709d2c6fec5ffcd80b1"},
{file = "PyMuPDF-1.24.7-cp312-none-manylinux2014_x86_64.whl", hash = "sha256:89ccd758b5b7d1e05d615e85fb5d358ff1994ff70aaa5df4f0724bd414847949"},
{file = "PyMuPDF-1.24.7-cp312-none-musllinux_1_2_x86_64.whl", hash = "sha256:8873253ffedb7bcc8dcafa9bfe8f1efa39ac91732ccc579e1c1746eeff4ed83a"},
{file = "PyMuPDF-1.24.7-cp312-none-win32.whl", hash = "sha256:5341440bfc6c89f025990d181896b74097f6b145f5e563e3d5e5fa944c79aae6"},
{file = "PyMuPDF-1.24.7-cp312-none-win_amd64.whl", hash = "sha256:a906b57dae8f3870663f3d3a1d4a66b67cc8f5cf644bcbdd175a391f5f74f2ef"},
{file = "PyMuPDF-1.24.7-cp38-none-macosx_10_9_x86_64.whl", hash = "sha256:b18630fead76175059b973230cc175c4ed30e9f4ea03d25963d2c74440bdb78b"},
{file = "PyMuPDF-1.24.7-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:a94d556b7ea25e6195c46dc2c4114d30e8e51233a49f0ed589f8e0190d2cc3b5"},
{file = "PyMuPDF-1.24.7-cp38-none-manylinux2014_aarch64.whl", hash = "sha256:da82dc784e52b3635110995a75189cdef71b02d9a3a2635cd1d216133d547519"},
{file = "PyMuPDF-1.24.7-cp38-none-manylinux2014_x86_64.whl", hash = "sha256:d95c0cc4768ce09d06c31280cda6fc7619026e615d33beee2dbd1c74ea3a1e08"},
{file = "PyMuPDF-1.24.7-cp38-none-musllinux_1_2_x86_64.whl", hash = "sha256:5c7c964e4b3dfbcd7a0ec11f44090002967c9652cf1dbaf5e09de333c479eae3"},
{file = "PyMuPDF-1.24.7-cp38-none-win32.whl", hash = "sha256:5812645087eaf537efb168df1a78b40b76d6b01c694b890d31e362fd007926fe"},
{file = "PyMuPDF-1.24.7-cp38-none-win_amd64.whl", hash = "sha256:b11065d5192bdc6e80046505ed68447276d3698ec1d0a3eea8dc2533f972f8fb"},
{file = "PyMuPDF-1.24.7-cp39-none-macosx_10_9_x86_64.whl", hash = "sha256:102d3427fcc3a47084eb2faa670de8a58e5d2061b4e61365b323d12a7bac0afd"},
{file = "PyMuPDF-1.24.7-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:5580c975a166a3fb1908fb055c0427bcd23abe7a7d3113777d15c0e5f8a2133b"},
{file = "PyMuPDF-1.24.7-cp39-none-manylinux2014_aarch64.whl", hash = "sha256:1553df16e6e141314fa33534800aee2bc4eab1daa8057bf791584b318aa114f6"},
{file = "PyMuPDF-1.24.7-cp39-none-manylinux2014_x86_64.whl", hash = "sha256:53cedffedc7ec5c019f8b06d0e18b1f410f4af15e0c122330b79d5e617739042"},
{file = "PyMuPDF-1.24.7-cp39-none-musllinux_1_2_x86_64.whl", hash = "sha256:371b983ba2b396a636518e2cfaa76ea8cccd38c9bdbc942256df678e421f7063"},
{file = "PyMuPDF-1.24.7-cp39-none-win32.whl", hash = "sha256:0a93d0f5c5b5cdc2f1718dbdf4b1c34aafc68ee4e44688b58c0a2894277ca941"},
{file = "PyMuPDF-1.24.7-cp39-none-win_amd64.whl", hash = "sha256:f82db6fd757fb3698075e2e68e4f6df7ae89b82a96ae102e178e5b01a250359b"},
{file = "PyMuPDF-1.24.7.tar.gz", hash = "sha256:a34ceae204f215bad51f49dd43987116c6a6269fc03d8770224f7067013b59b8"},
]
[package.dependencies]
PyMuPDFb = "1.24.6"
[package.source]
type = "legacy"
url = "https://pypi.org/simple"
reference = "localpypi"
[[package]]
name = "pymupdfb"
version = "1.24.6"
description = "MuPDF shared libraries for PyMuPDF."
optional = false
python-versions = ">=3.8"
files = [
{file = "PyMuPDFb-1.24.6-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:21e3ed890f736def68b9a031122ae1fb854d5cb9a53aa144b6e2ca3092416a6b"},
{file = "PyMuPDFb-1.24.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8704d2dfadc9448ce184597d8b0f9c30143e379ac948a517f9c4db7c0c71ed51"},
{file = "PyMuPDFb-1.24.6-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:01662584d5cfa7a91f77585f13fc23a12291cfd76a57e0a28dd5a56bf521cb2c"},
{file = "PyMuPDFb-1.24.6-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e1f7657353529ae3f88575c83ee49eac9adea311a034b9c97248a65cee7df0e5"},
{file = "PyMuPDFb-1.24.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cebc2cedb870d1e1168e2f502eb06f05938f6df69103b0853a2b329611ec19a7"},
{file = "PyMuPDFb-1.24.6-py3-none-win32.whl", hash = "sha256:ac4b865cd1e239db04674f85e02844a0e405f8255ee7a74dfee0d86aad0d3576"},
{file = "PyMuPDFb-1.24.6-py3-none-win_amd64.whl", hash = "sha256:9224e088a0d3c188dea03831807789e245b812fbd071c8d498da8f7cc33142b2"},
{file = "PyMuPDFb-1.24.6.tar.gz", hash = "sha256:f5a40b1732d65a1e519916d698858b9ce7473e23edf9001ddd085c5293d59d30"},
]
[package.source]
type = "legacy"
url = "https://pypi.org/simple"
reference = "localpypi"
[[package]]
name = "setuptools"
version = "70.3.0"
version = "71.0.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.8"
files = [
{file = "setuptools-70.3.0-py3-none-any.whl", hash = "sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc"},
{file = "setuptools-70.3.0.tar.gz", hash = "sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5"},
{file = "setuptools-71.0.0-py3-none-any.whl", hash = "sha256:f06fbe978a91819d250a30e0dc4ca79df713d909e24438a42d0ec300fc52247f"},
{file = "setuptools-71.0.0.tar.gz", hash = "sha256:98da3b8aca443b9848a209ae4165e2edede62633219afa493a58fbba57f72e2e"},
]
[package.extras]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (<7.4)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
[package.source]
type = "legacy"
@@ -295,4 +371,4 @@ reference = "localpypi"
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
content-hash = "dfb034cdc323648effbcfff969cae65cbca1b04130c64d68c8c8968f0d692e71"
content-hash = "080fe35089770ecee25895cdd4ee4aa14b9e9c818c199908f066bc94c4470530"
+2 -1
View File
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "cbz"
version = "3.3.0"
version = "3.3.2"
description = "CBZ simplifies creating, managing, and viewing comic book files in CBZ format, offering seamless packaging, metadata handling, and built-in viewing capabilities"
license = "MIT"
authors = ["hyugogirubato <65763543+hyugogirubato@users.noreply.github.com>"]
@@ -34,6 +34,7 @@ python = "^3.8"
xmltodict = "^0.13.0"
langcodes = "^3.4.0"
Pillow = "^10.4.0"
PyMuPDF = "^1.24.7"
[tool.poetry.scripts]
cbzplayer = "cbz.__main__:main"