diff --git a/.github/workflows/import-test.yml b/.github/workflows/import-test.yml index af769fcb..d9a11d9e 100644 --- a/.github/workflows/import-test.yml +++ b/.github/workflows/import-test.yml @@ -7,7 +7,7 @@ jobs: strategy: max-parallel: 3 matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.10", "3.11", "3.12"] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index a5aadb12..94a21ec4 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -7,7 +7,7 @@ jobs: strategy: max-parallel: 3 matrix: - python-version: ["3.8", "3.9", "3.10"] + python-version: ["3.10"] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 diff --git a/.travis.yml b/.travis.yml index 1ccbd628..28c0f738 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ language: python python: - - "3.8" - - "3.9" - "3.10" before_script: - pip install poetry diff --git a/README.md b/README.md index 1bcd204c..6cedf3f6 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,7 @@ Useful links - http://shining-lucy.com/wiki/page.php?id=appwiki:photoshop:ps_script - http://web.archive.org/web/20140121053819/http://www.pcpix.com/Photoshop/char.html - http://www.tonton-pixel.com/scripts/utility-scripts/get-equivalent-id-code/index.html +- https://github.com/Adobe-CEP/CEP-Resources/tree/master/Documentation/Product%20specific%20Documentation/Photoshop%20Scripting - https://github.com/Adobe-CEP/Samples/tree/master/PhotoshopEvents - https://evanmccall.wordpress.com/2015/03/09/how-to-develop-photoshop-tools-in-python @@ -279,7 +280,7 @@ We value thorough testing to ensure reliability: ### 📦 Development Environment -- **Python Versions**: We support Python 3.8+ (see `pyproject.toml` for specifics) +- **Python Versions**: We support Python 3.10+ (see `pyproject.toml` for specifics) - **Dependency Management**: [Poetry](https://python-poetry.org/) for consistent environments - **Virtual Environment**: Poetry automatically creates and manages virtual environments @@ -295,3 +296,18 @@ We value thorough testing to ensure reliability: 8. **Merge**: Once approved, your PR will be merged Thank you for contributing to the Photoshop Python API project! 🎉 + +### Development Notes + +One way to view the COM API structure is to use Visual Studio. + +1. Install Visual Studio with the .NET desktop development workload +2. Open Visual Studio +3. Choose View -> Object Browser +4. In the Object Browser from the Browse dropdown choose *Edit Custom Component Set...* +5. In the Edit Custom Component Set window's COM tab add Photoshop's Object and Type libraries +6. After pressing OK the libraries should show up in the Object Browser + +If the libraries aren't visible in the COM tab make sure you have the .NET desktop development workload installed. Other things you may try are running Photoshop once as administrator and reinstalling Photoshop and/or your PC. The object library is defined usually in */your/path/to/Adobe Photoshop \/Required/Plug-ins/Extensions/ScriptingSupport.8li* + +The [VBS reference 2020](https://github.com/Adobe-CEP/CEP-Resources/blob/master/Documentation/Product%20specific%20Documentation/Photoshop%20Scripting/photoshop-vbs-ref-2020.pdf) is also quite trustworthy, since Adobe isn't actively developing the COM API anymore. diff --git a/examples/active_layer.py b/examples/active_layer.py index 10a82fca..3c3ab1c2 100644 --- a/examples/active_layer.py +++ b/examples/active_layer.py @@ -28,9 +28,9 @@ docRef.artLayers.add() # Display current active layer name - ps.echo(docRef.activeLayer.name) + print(docRef.activeLayer.name) # Create and rename a new layer new_layer = docRef.artLayers.add() - ps.echo(new_layer.name) + print(new_layer.name) new_layer.name = "test" diff --git a/examples/add_metadata.py b/examples/add_metadata.py index 63d471bd..a8369db2 100644 --- a/examples/add_metadata.py +++ b/examples/add_metadata.py @@ -13,4 +13,4 @@ doc.info.provinceState = "Beijing" doc.info.title = "My Demo" print("Print all metadata of current active document.") - ps.echo(doc.info) + print(doc.info) diff --git a/examples/change_color_of_background_and_foreground.py b/examples/change_color_of_background_and_foreground.py index 8263f90a..8f78f651 100644 --- a/examples/change_color_of_background_and_foreground.py +++ b/examples/change_color_of_background_and_foreground.py @@ -34,10 +34,10 @@ ps.app.backgroundColor = bg_color # Print current colors - ps.echo(f"Foreground RGB: {ps.app.foregroundColor.rgb.red}, " + print(f"Foreground RGB: {ps.app.foregroundColor.rgb.red}, " f"{ps.app.foregroundColor.rgb.green}, " f"{ps.app.foregroundColor.rgb.blue}") - ps.echo(f"Background RGB: {ps.app.backgroundColor.rgb.red}, " + print(f"Background RGB: {ps.app.backgroundColor.rgb.red}, " f"{ps.app.backgroundColor.rgb.green}, " f"{ps.app.backgroundColor.rgb.blue}") diff --git a/examples/compare_colors.py b/examples/compare_colors.py index ab1f1e3b..5a430d57 100644 --- a/examples/compare_colors.py +++ b/examples/compare_colors.py @@ -34,4 +34,4 @@ color1.rgb.green == color2.rgb.green and color1.rgb.blue == color2.rgb.blue) - ps.echo(f"Colors are {'same' if is_same else 'different'}") + print(f"Colors are {'same' if is_same else 'different'}") diff --git a/examples/convert_smartobject_to_layer.py b/examples/convert_smartobject_to_layer.py index 12368bb8..428df623 100644 --- a/examples/convert_smartobject_to_layer.py +++ b/examples/convert_smartobject_to_layer.py @@ -26,12 +26,12 @@ # Convert to smart object layer.convertToSmartObject() - ps.echo("Layer converted to Smart Object") + print("Layer converted to Smart Object") # Check if it's a smart object if layer.kind == ps.LayerKind.SmartObjectLayer: - ps.echo("Layer is now a Smart Object") + print("Layer is now a Smart Object") # Convert back to regular layer layer.rasterize(ps.RasterizeType.EntireLayer) - ps.echo("Smart Object converted back to regular layer") + print("Smart Object converted back to regular layer") diff --git a/examples/current_tool.py b/examples/current_tool.py index 949929e0..0b13289f 100644 --- a/examples/current_tool.py +++ b/examples/current_tool.py @@ -22,4 +22,4 @@ current = ps.app.currentTool # Print current tool name - ps.echo(f"Current tool: {current}") + print(f"Current tool: {current}") diff --git a/examples/eval_javascript.py b/examples/eval_javascript.py index 805a643b..59ec5ccd 100644 --- a/examples/eval_javascript.py +++ b/examples/eval_javascript.py @@ -21,4 +21,4 @@ # Execute JavaScript command js_code = "app.documents.length" result = ps.app.eval_javascript(js_code) - ps.echo(f"Number of open documents: {result}") + print(f"Number of open documents: {result}") diff --git a/examples/export_layers_use_export_options_saveforweb.py b/examples/export_layers_use_export_options_saveforweb.py index aa84ecc2..00c89b76 100644 --- a/examples/export_layers_use_export_options_saveforweb.py +++ b/examples/export_layers_use_export_options_saveforweb.py @@ -33,7 +33,7 @@ def main(): image_path = os.path.join(layer_path, f"{layer.name}.png") doc.exportDocument(image_path, exportAs=ps.ExportType.SaveForWeb, options=options) ps.alert("Task done!") - ps.echo(doc.activeLayer) + print(doc.activeLayer) if __name__ == "__main__": diff --git a/examples/get_document_by_name.py b/examples/get_document_by_name.py index 6ca9c797..b50482ac 100644 --- a/examples/get_document_by_name.py +++ b/examples/get_document_by_name.py @@ -19,7 +19,7 @@ # Try to get document named 'test.psd' for doc in ps.app.documents: if doc.name == "test.psd": - ps.echo(doc.name) + print(doc.name) break else: - ps.echo("Document not found!") + print("Document not found!") diff --git a/examples/get_layer_by_name.py b/examples/get_layer_by_name.py index c287e621..92078784 100644 --- a/examples/get_layer_by_name.py +++ b/examples/get_layer_by_name.py @@ -20,5 +20,5 @@ doc = ps.app.activeDocument for layer in doc.layers: if layer.name == "example layer": - ps.echo(layer.name) + print(layer.name) break diff --git a/examples/link_layer.py b/examples/link_layer.py index 0a327955..de4a520a 100644 --- a/examples/link_layer.py +++ b/examples/link_layer.py @@ -35,9 +35,9 @@ layer2.link(layer3) # Check link status - ps.echo(f"Layer 1 linked: {layer1.linked}") - ps.echo(f"Layer 2 linked: {layer2.linked}") - ps.echo(f"Layer 3 linked: {layer3.linked}") + print(f"Layer 1 linked: {layer1.linked}") + print(f"Layer 2 linked: {layer2.linked}") + print(f"Layer 3 linked: {layer3.linked}") # Move linked layers together layer1.translate(100, 100) diff --git a/examples/load_selection.py b/examples/load_selection.py index 3070f3ce..0c097344 100644 --- a/examples/load_selection.py +++ b/examples/load_selection.py @@ -54,5 +54,5 @@ doc.selection.combine(doc.channels[-1], ps.SelectionType.ExtendSelection) # Clean up - delete added channels - doc.channels[-1].remove() - doc.channels[-1].remove() + doc.channels[-1].delete() + doc.channels[-1].delete() diff --git a/examples/open_psd.py b/examples/open_psd.py index ac03d4d7..ed6e0fb4 100644 --- a/examples/open_psd.py +++ b/examples/open_psd.py @@ -9,4 +9,4 @@ # style 2 with Session("your/psd/or/psb/file_path.psd", action="open") as ps: - ps.echo(ps.active_document.name) + print(ps.active_document.name) diff --git a/examples/operate_channels.py b/examples/operate_channels.py index d64becb3..84f1a126 100644 --- a/examples/operate_channels.py +++ b/examples/operate_channels.py @@ -22,7 +22,7 @@ # List all channels for channel in doc.channels: - ps.echo(f"Channel: {channel.name}") + print(f"Channel: {channel.name}") # Create a new alpha channel new_channel = doc.channels.add() diff --git a/examples/operate_layerSet.py b/examples/operate_layerSet.py index a4a4bb3f..67fdc595 100644 --- a/examples/operate_layerSet.py +++ b/examples/operate_layerSet.py @@ -41,10 +41,10 @@ # List layers in groups for layer in main_group.layers: - ps.echo(f"Layer in main group: {layer.name}") + print(f"Layer in main group: {layer.name}") for layer in sub_group.layers: - ps.echo(f"Layer in sub group: {layer.name}") + print(f"Layer in sub group: {layer.name}") # Move a layer between groups layer1.move(sub_group, ps.ElementPlacement.INSIDE) diff --git a/examples/session_callback.py b/examples/session_callback.py index 9cc2eaf6..cdd97d3c 100644 --- a/examples/session_callback.py +++ b/examples/session_callback.py @@ -23,4 +23,4 @@ def on_close(): with Session(callback=on_close) as ps: - ps.echo("Working in session...") + print("Working in session...") diff --git a/examples/session_new_document.py b/examples/session_new_document.py index 7e34c73f..bdbc03e4 100644 --- a/examples/session_new_document.py +++ b/examples/session_new_document.py @@ -4,4 +4,4 @@ with Session(action="new_document") as ps: - ps.echo(ps.active_document.name) + print(ps.active_document.name) diff --git a/photoshop/api/_active_layer.py b/photoshop/api/_active_layer.py deleted file mode 100644 index 16449766..00000000 --- a/photoshop/api/_active_layer.py +++ /dev/null @@ -1,18 +0,0 @@ -# Import local modules -from photoshop.api._core import Photoshop - - -class ActiveLayer(Photoshop): - """The selected layer.""" - - def __int__(self): - super().__init__() - - @property - def name(self) -> str: - """The name of the layer.""" - return self.active_layer.Typename - - def add(self): - """Adds an element.""" - self.app.ActiveDocument.ArtLayers.Add() diff --git a/photoshop/api/_artlayer.py b/photoshop/api/_artlayer.py index ae144f8e..874f9eb6 100644 --- a/photoshop/api/_artlayer.py +++ b/photoshop/api/_artlayer.py @@ -1,21 +1,34 @@ -# Import built-in modules -from typing import Any +from os import PathLike -# Import local modules from photoshop.api._core import Photoshop -from photoshop.api.enumerations import RasterizeType +from photoshop.api._layer import Layer +from photoshop.api.enumerations import ( + CreateFields, + DepthMaource, + DisplacementMapType, + ElementPlacement, + EliminateFields, + Geometry, + LayerKind, + LensType, + NoiseDistribution, + OffsetUndefinedAreas, + RasterizeType, + TextureType, + UndefinedAreas, +) from photoshop.api.text_item import TextItem # pylint: disable=too-many-public-methods, too-many-arguments -class ArtLayer(Photoshop): +class ArtLayer(Layer): """An object within a document that contains the visual elements of the image (equivalent to a layer in the Adobe Photoshop application). """ - def __init__(self, parent: Any = None): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) self._flag_as_method( "add", @@ -48,79 +61,39 @@ def __init__(self, parent: Any = None): "applyOceanRipple", "applyOffset", "applyPinch", - "delete", - "duplicate", "invert", - "link", "merge", - "move", "posterize", "rasterize", - "unlink", "convertToSmartObject", ) @property - def allLocked(self): - return self.app.allLocked - - @allLocked.setter - def allLocked(self, value): - self.app.allLocked = value - - @property - def blendMode(self): - return self.app.blendMode - - @blendMode.setter - def blendMode(self, mode): - self.app.blendMode = mode - - @property - def bounds(self): - """The bounding rectangle of the layer.""" - return self.app.bounds - - @property - def linkedLayers(self) -> list: - """Get all layers linked to this layer. - - Returns: - list: Layer objects""" - return [ArtLayer(layer) for layer in self.app.linkedLayers] - - @property - def name(self) -> str: - return self.app.name - - @name.setter - def name(self, text: str): - self.app.name = text - - @property - def fillOpacity(self): + def fillOpacity(self) -> float: """The interior opacity of the layer. Range: 0.0 to 100.0.""" return self.app.fillOpacity @fillOpacity.setter - def fillOpacity(self, value): + def fillOpacity(self, value: float) -> None: """The interior opacity of the layer. Range: 0.0 to 100.0.""" self.app.fillOpacity = value @property - def filterMaskDensity(self): + def filterMaskDensity(self) -> float: + """The density of the filter mask (between 0.0 and 100.0)""" return self.app.filterMaskDensity @filterMaskDensity.setter - def filterMaskDensity(self, value): + def filterMaskDensity(self, value: float) -> None: self.app.filterMaskDensity = value @property - def filterMaskFeather(self): + def filterMaskFeather(self) -> float: + """The feather of the filter mask (between 0.0 and 250.0)""" return self.app.filterMaskFeather @filterMaskFeather.setter - def filterMaskFeather(self, value): + def filterMaskFeather(self, value: float) -> None: self.app.filterMaskFeather = value @property @@ -129,97 +102,66 @@ def grouped(self) -> bool: return self.app.grouped @grouped.setter - def grouped(self, value): + def grouped(self, value: bool) -> None: self.app.grouped = value @property - def isBackgroundLayer(self): + def isBackgroundLayer(self) -> bool: """bool: If true, the layer is a background layer.""" return self.app.isBackgroundLayer @isBackgroundLayer.setter - def isBackgroundLayer(self, value): + def isBackgroundLayer(self, value: bool) -> None: self.app.isBackgroundLayer = value @property - def kind(self): + def kind(self) -> LayerKind: """Get the layer kind. Returns: LayerKind: The kind of this layer. """ - try: - js = """ - var ref = new ActionReference(); - ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt")); - var desc = executeActionGet(ref); - var layerType = desc.getInteger(stringIDToTypeID("layerKind")); - layerType; - """ - return int(self.eval_javascript(js)) - except Exception as e: - print(f"Error getting layer kind: {str(e)}") - return None + return LayerKind(self.app.kind) @kind.setter - def kind(self, layer_type): - """set the layer kind.""" - self.app.kind = layer_type + def kind(self, value: LayerKind) -> None: + self.app.kind = value @property - def layerMaskDensity(self): + def layerMaskDensity(self) -> float: """The density of the layer mask (between 0.0 and 100.0).""" return self.app.layerMaskDensity @layerMaskDensity.setter - def layerMaskDensity(self, value): + def layerMaskDensity(self, value: float) -> None: self.app.layerMaskDensity = value @property - def layerMaskFeather(self): + def layerMaskFeather(self) -> float: """The feather of the layer mask (between 0.0 and 250.0).""" return self.app.layerMaskFeather @layerMaskFeather.setter - def layerMaskFeather(self, value): + def layerMaskFeather(self, value: float) -> None: self.app.layerMaskFeather = value @property - def opacity(self): - """The master opacity of the layer.""" - return round(self.app.opacity) - - @opacity.setter - def opacity(self, value): - self.app.opacity = value - - @property - def parent(self): - """The object’s container.""" - return self.app.parent - - @parent.setter - def parent(self, value): - """Set the object’s container.""" - self.app.parent = value - - @property - def pixelsLocked(self): + def pixelsLocked(self) -> bool: """If true, the pixels in the layer’s image cannot be edited.""" return self.app.pixelsLocked @pixelsLocked.setter - def pixelsLocked(self, value): + def pixelsLocked(self, value: bool) -> None: self.app.pixelsLocked = value @property - def positionLocked(self): + def positionLocked(self) -> bool: """bool: If true, the pixels in the layer’s image cannot be moved within the layer.""" return self.app.positionLocked @positionLocked.setter - def positionLocked(self, value): + def positionLocked(self, value: bool) -> None: self.app.positionLocked = value @property @@ -233,49 +175,36 @@ def textItem(self) -> TextItem: return TextItem(self.app.textItem) @textItem.setter - def textItem(self, value): - self.app.textItem = value + def textItem(self, value: TextItem) -> None: + self.app.textItem = value.app @property - def transparentPixelsLocked(self): + def transparentPixelsLocked(self) -> bool: return self.app.transparentPixelsLocked @transparentPixelsLocked.setter - def transparentPixelsLocked(self, value): + def transparentPixelsLocked(self, value: bool) -> None: self.app.transparentPixelsLocked = value @property - def vectorMaskDensity(self): + def vectorMaskDensity(self) -> float: + """The density of the vector mask (between 0.0 and 100.0)""" return self.app.vectorMaskDensity @vectorMaskDensity.setter - def vectorMaskDensity(self, value): + def vectorMaskDensity(self, value: float) -> None: self.app.vectorMaskDensity = value @property - def vectorMaskFeather(self): + def vectorMaskFeather(self) -> float: + """The feather of the vector mask (between 0.0 and 250.0)""" return self.app.vectorMaskFeather @vectorMaskFeather.setter - def vectorMaskFeather(self, value): + def vectorMaskFeather(self, value: float) -> None: self.app.vectorMaskFeather = value - @property - def visible(self): - return self.app.visible - - @visible.setter - def visible(self, value): - self.app.visible = value - - @property - def length(self): - return len(list(self.app)) - - def add(self): - return self.app.add() - - def adjustBrightnessContrast(self, brightness, contrast): + def adjustBrightnessContrast(self, brightness: int, contrast: int) -> None: """Adjusts the brightness and contrast. Args: @@ -283,15 +212,15 @@ def adjustBrightnessContrast(self, brightness, contrast): contrast (int): The contrast amount. Range: -100 to 100. """ - return self.app.adjustBrightnessContrast(brightness, contrast) + self.app.adjustBrightnessContrast(brightness, contrast) def adjustColorBalance( self, - shadows, - midtones, - highlights, - preserveLuminosity, - ): + shadows: tuple[int, int, int], + midtones: tuple[int, int, int], + highlights: tuple[int, int, int], + preserveLuminosity: bool, + ) -> None: """Adjusts the color balance of the layer’s component channels. Args: @@ -310,14 +239,14 @@ def adjustColorBalance( preserveLuminosity: If true, luminosity is preserved. """ - return self.app.adjustColorBalance( + self.app.adjustColorBalance( shadows, midtones, highlights, preserveLuminosity, ) - def adjustCurves(self, curveShape): + def adjustCurves(self, curveShape: list[tuple[float, float]]) -> None: """Adjusts the tonal range of the selected channel using up to fourteen points. @@ -330,16 +259,16 @@ def adjustCurves(self, curveShape): Returns: """ - return self.app.adjustCurves(curveShape) + self.app.adjustCurves(curveShape) def adjustLevels( self, - inputRangeStart, - inputRangeEnd, - inputRangeGamma, - outputRangeStart, - outputRangeEnd, - ): + inputRangeStart: int, + inputRangeEnd: int, + inputRangeGamma: float, + outputRangeStart: int, + outputRangeEnd: int, + ) -> None: """Adjusts levels of the selected channels. Args: @@ -352,7 +281,7 @@ def adjustLevels( Returns: """ - return self.app.adjustLevels( + self.app.adjustLevels( inputRangeStart, inputRangeEnd, inputRangeGamma, @@ -360,10 +289,10 @@ def adjustLevels( outputRangeEnd, ) - def applyAddNoise(self, amount, distribution, monochromatic): - return self.app.applyAddNoise(amount, distribution, monochromatic) + def applyAddNoise(self, amount: float, distribution: NoiseDistribution, monochromatic: bool) -> None: + self.app.applyAddNoise(amount, distribution, monochromatic) - def applyDiffuseGlow(self, graininess, amount, clear_amount): + def applyDiffuseGlow(self, graininess: int, amount: int, clear_amount: int) -> None: """Applies the diffuse glow filter. Args: @@ -374,103 +303,103 @@ def applyDiffuseGlow(self, graininess, amount, clear_amount): Returns: """ - return self.app.applyDiffuseGlow(graininess, amount, clear_amount) + self.app.applyDiffuseGlow(graininess, amount, clear_amount) - def applyAverage(self): + def applyAverage(self) -> None: """Applies the average filter.""" - return self.app.applyAverage() + self.app.applyAverage() - def applyBlur(self): + def applyBlur(self) -> None: """Applies the blur filter.""" - return self.app.applyBlur() + self.app.applyBlur() - def applyBlurMore(self): + def applyBlurMore(self) -> None: """Applies the blur more filter.""" - return self.app.applyBlurMore() + self.app.applyBlurMore() - def applyClouds(self): + def applyClouds(self) -> None: """Applies the clouds filter.""" - return self.app.applyClouds() + self.app.applyClouds() - def applyCustomFilter(self, characteristics, scale, offset): + def applyCustomFilter(self, characteristics: list[int], scale: int, offset: int) -> None: """Applies the custom filter.""" - return self.app.applyCustomFilter(characteristics, scale, offset) + self.app.applyCustomFilter(characteristics, scale, offset) - def applyDeInterlace(self, eliminateFields, createFields): + def applyDeInterlace(self, eliminateFields: EliminateFields, createFields: CreateFields) -> None: """Applies the de-interlace filter.""" - return self.app.applyDeInterlace(eliminateFields, createFields) + self.app.applyDeInterlace(eliminateFields, createFields) - def applyDespeckle(self): - return self.app.applyDespeckle() + def applyDespeckle(self) -> None: + self.app.applyDespeckle() - def applyDifferenceClouds(self): + def applyDifferenceClouds(self) -> None: """Applies the difference clouds filter.""" - return self.app.applyDifferenceClouds() + self.app.applyDifferenceClouds() def applyDisplace( self, - horizontalScale, - verticalScale, - displacementType, - undefinedAreas, - displacementMapFile, - ): + horizontalScale: int, + verticalScale: int, + displacementType: DisplacementMapType, + undefinedAreas: UndefinedAreas, + displacementMapFile: str | PathLike[str], + ) -> None: """Applies the displace filter.""" - return self.app.applyDisplace( + self.app.applyDisplace( horizontalScale, verticalScale, displacementType, undefinedAreas, - displacementMapFile, + str(displacementMapFile), ) - def applyDustAndScratches(self, radius, threshold): + def applyDustAndScratches(self, radius: int, threshold: int) -> None: """Applies the dust and scratches filter.""" - return self.app.applyDustAndScratches(radius, threshold) + self.app.applyDustAndScratches(radius, threshold) - def applyGaussianBlur(self, radius): + def applyGaussianBlur(self, radius: float) -> None: """Applies the gaussian blur filter.""" - return self.app.applyGaussianBlur(radius) + self.app.applyGaussianBlur(radius) def applyGlassEffect( self, - distortion, - smoothness, - scaling, - invert, - texture, - textureFile, - ): - return self.app.applyGlassEffect( + distortion: int, + smoothness: int, + scaling: int, + invert: bool, + texture: TextureType, + textureFile: str | PathLike[str], + ) -> None: + self.app.applyGlassEffect( distortion, smoothness, scaling, invert, texture, - textureFile, + str(textureFile), ) - def applyHighPass(self, radius): + def applyHighPass(self, radius: float) -> None: """Applies the high pass filter.""" - return self.app.applyHighPass(radius) + self.app.applyHighPass(radius) def applyLensBlur( self, - source, - focalDistance, - invertDepthMap, - shape, - radius, - bladeCurvature, - rotation, - brightness, - threshold, - amount, - distribution, - monochromatic, - ): + source: DepthMaource, + focalDistance: int, + invertDepthMap: bool, + shape: Geometry, + radius: int, + bladeCurvature: int, + rotation: int, + brightness: int, + threshold: int, + amount: int, + distribution: NoiseDistribution, + monochromatic: bool, + ) -> None: """Apply the lens blur filter.""" - return self.app.applyLensBlur( + self.app.applyLensBlur( source, focalDistance, invertDepthMap, @@ -485,60 +414,50 @@ def applyLensBlur( monochromatic, ) - def applyLensFlare(self, brightness, flareCenter, lensType): - return self.app.applyLensFlare(brightness, flareCenter, lensType) + def applyLensFlare(self, brightness: int, flareCenter: tuple[float, float], lensType: LensType) -> None: + self.app.applyLensFlare(brightness, flareCenter, lensType) - def applyMaximum(self, radius): + def applyMaximum(self, radius: float) -> None: self.app.applyMaximum(radius) - def applyMedianNoise(self, radius): + def applyMedianNoise(self, radius: float) -> None: self.app.applyMedianNoise(radius) - def applyMinimum(self, radius): + def applyMinimum(self, radius: float) -> None: self.app.applyMinimum(radius) - def applyMotionBlur(self, angle, radius): + def applyMotionBlur(self, angle: int, radius: float) -> None: self.app.applyMotionBlur(angle, radius) - def applyNTSC(self): + def applyNTSC(self) -> None: self.app.applyNTSC() - def applyOceanRipple(self, size, magnitude): + def applyOceanRipple(self, size: int, magnitude: int) -> None: self.app.applyOceanRipple(size, magnitude) - def applyOffset(self, horizontal, vertical, undefinedAreas): + def applyOffset(self, horizontal: int, vertical: int, undefinedAreas: OffsetUndefinedAreas) -> None: self.app.applyOffset(horizontal, vertical, undefinedAreas) - def applyPinch(self, amount): + def applyPinch(self, amount: int) -> None: self.app.applyPinch(amount) - def remove(self): - """Removes this layer from the document.""" - self.app.delete() - - def rasterize(self, target: RasterizeType): + def rasterize(self, target: RasterizeType) -> None: self.app.rasterize(target) - def posterize(self, levels): + def posterize(self, levels: int) -> None: self.app.posterize(levels) - def move(self, relativeObject, insertionLocation): - self.app.move(relativeObject, insertionLocation) - - def merge(self): + def merge(self) -> "ArtLayer": return ArtLayer(self.app.merge()) - def link(self, with_layer): - self.app.link(with_layer) - - def unlink(self): - """Unlink this layer from any linked layers.""" - self.app.unlink() - - def invert(self): + def invert(self) -> None: self.app.invert() - def duplicate(self, relativeObject=None, insertionLocation=None): + def duplicate( + self, + relativeObject: "Layer | None" = None, + insertionLocation: ElementPlacement | None = None, + ) -> "ArtLayer": """Duplicates the layer. Args: @@ -549,10 +468,9 @@ def duplicate(self, relativeObject=None, insertionLocation=None): ArtLayer: The duplicated layer. """ - dup = self.app.duplicate(relativeObject, insertionLocation) - return ArtLayer(dup) + return ArtLayer(self.app.duplicate(relativeObject.app if relativeObject else None, insertionLocation)) - def convertToSmartObject(self): + def convertToSmartObject(self) -> "ArtLayer": """Converts the layer to a smart object. Returns: diff --git a/photoshop/api/_artlayers.py b/photoshop/api/_artlayers.py index dddb7fa7..614aaa0b 100644 --- a/photoshop/api/_artlayers.py +++ b/photoshop/api/_artlayers.py @@ -1,72 +1,18 @@ -# Import third-party modules -from comtypes import ArgumentError - # Import local modules from photoshop.api._artlayer import ArtLayer from photoshop.api._core import Photoshop -from photoshop.api.errors import PhotoshopPythonAPIError +from photoshop.api.collections import CollectionOfNamedObjects +from photoshop.api.collections import CollectionOfRemovables +from photoshop.api.collections import CollectionWithAdd # pylint: disable=too-many-public-methods -class ArtLayers(Photoshop): +class ArtLayers( + CollectionOfRemovables[ArtLayer, int | str], + CollectionOfNamedObjects[ArtLayer, int | str], + CollectionWithAdd[ArtLayer, int | str], +): """The collection of art layer objects in the document.""" - def __init__(self, parent): - super().__init__(parent=parent) - self._flag_as_method( - "add", - ) - - @property - def _layers(self): - return list(self.app) - - def __len__(self): - return self.length - - def __iter__(self): - for layer in self.app: - yield layer - - def __getitem__(self, key: str): - """Access a given ArtLayer using dictionary key lookup.""" - try: - return ArtLayer(self.app[key]) - except ArgumentError: - raise PhotoshopPythonAPIError(f'Could not find an artLayer named "{key}"') - - @property - def length(self): - return len(self._layers) - - @property - def parent(self): - return self.app.parent - - @property - def typename(self): - return self.app.typename - - def add(self): - """Adds an element.""" - return ArtLayer(self.app.add()) - - def getByIndex(self, index: int): - """Access ArtLayer using list index lookup.""" - return ArtLayer(self._layers[index]) - - def getByName(self, name: str) -> ArtLayer: - """Get the first element in the collection with the provided name. - - Raises: - PhotoshopPythonAPIError: Could not find a artLayer. - """ - for layer in self.app: - if layer.name == name: - return ArtLayer(layer) - raise PhotoshopPythonAPIError(f'Could not find an artLayer named "{name}"') - - def removeAll(self): - """Deletes all elements.""" - for layer in self.app: - ArtLayer(layer).remove() + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(ArtLayer, parent) diff --git a/photoshop/api/_channel.py b/photoshop/api/_channel.py index ee47309c..22fc1489 100644 --- a/photoshop/api/_channel.py +++ b/photoshop/api/_channel.py @@ -1,10 +1,20 @@ +# Import built-in modules +from typing import TYPE_CHECKING + # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.enumerations import ChannelType +from photoshop.api.solid_color import SolidColor + + +if TYPE_CHECKING: + # Import local modules + from photoshop.api._document import Document # pylint: disable=too-many-public-methods class Channel(Photoshop): - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) self._flag_as_method( "duplicate", @@ -12,55 +22,54 @@ def __init__(self, parent): ) @property - def color(self): - return self.app.color + def color(self) -> SolidColor: + return SolidColor(self.app.color) @color.setter - def color(self, value): - self.app.color = value + def color(self, value: SolidColor) -> None: + self.app.color = value.app @property - def histogram(self): + def histogram(self) -> tuple[int, ...]: return self.app.histogram @histogram.setter - def histogram(self, value): + def histogram(self, value: tuple[int, ...]) -> None: self.app.histogram = value @property - def kind(self): - return self.app.kind + def kind(self) -> ChannelType: + return ChannelType(self.app.kind) @kind.setter - def kind(self, value): + def kind(self, value: ChannelType) -> None: self.app.kind = value @property - def opacity(self): + def opacity(self) -> float: return self.app.opacity @opacity.setter - def opacity(self, value): + def opacity(self, value: float) -> None: self.app.opacity = value @property - def visible(self): + def visible(self) -> bool: return self.app.visible @visible.setter - def visible(self, value): + def visible(self, value: bool) -> None: self.app.visible = value @property - def name(self): + def name(self) -> str: return self.app.name - def duplicate(self, targetDocument=None): - self.app.duplicate(targetDocument) + def duplicate(self, targetDocument: "Document | None" = None) -> "Channel": + return Channel(self.app.duplicate(targetDocument.app if targetDocument else None)) - def merge(self): + def merge(self) -> None: self.app.merge() - def remove(self): - channel = f'app.activeDocument.channels.getByName("{self.name}")' - self.eval_javascript(f"{channel}.remove()") + def delete(self) -> None: + self.app.delete() diff --git a/photoshop/api/_channels.py b/photoshop/api/_channels.py index 00b3b6a2..f41af88e 100644 --- a/photoshop/api/_channels.py +++ b/photoshop/api/_channels.py @@ -1,44 +1,15 @@ # Import local modules from photoshop.api._channel import Channel from photoshop.api._core import Photoshop -from photoshop.api.errors import PhotoshopPythonAPIError - - -# pylint: disable=too-many-public-methods -class Channels(Photoshop): - def __init__(self, parent): - super().__init__(parent=parent) - self._flag_as_method( - "add", - "removeAll", - ) - - @property - def _channels(self): - return list(self.app) - - def __len__(self): - return self.length - - def __iter__(self): - for layer in self.app: - yield layer - - def __getitem__(self, item): - return self.app[item] - - @property - def length(self): - return len(self._channels) - - def add(self): - self.app.add() - - def removeAll(self): - self.app.removeAll() - - def getByName(self, name) -> Channel: - for channel in self._channels: - if channel.name == name: - return Channel(channel) - raise PhotoshopPythonAPIError(f'Could not find a channel named "{name}"') +from photoshop.api.collections import CollectionOfNamedObjects +from photoshop.api.collections import CollectionOfRemovables +from photoshop.api.collections import CollectionWithAdd + + +class Channels( + CollectionWithAdd[Channel, int | str], + CollectionOfRemovables[Channel, int | str], + CollectionOfNamedObjects[Channel, int | str], +): + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(Channel, parent=parent) diff --git a/photoshop/api/_core.py b/photoshop/api/_core.py index 28be680a..a06ef8c0 100644 --- a/photoshop/api/_core.py +++ b/photoshop/api/_core.py @@ -1,28 +1,26 @@ """This class provides all photoshop API core functions.""" -# Import built-in modules -from contextlib import suppress -from functools import cached_property -from logging import CRITICAL -from logging import DEBUG -from logging import Logger -from logging import getLogger + import os import platform -from typing import Any -from typing import List -from typing import Optional import winreg -# Import third-party modules +from contextlib import suppress +from functools import cached_property +from logging import CRITICAL, DEBUG, Logger, getLogger +from typing import TYPE_CHECKING, Any + from comtypes.client import CreateObject from comtypes.client.dynamic import _Dispatch as FullyDynamicDispatch -from comtypes.client.lazybind import Dispatch -# Import local modules from photoshop.api.constants import PHOTOSHOP_VERSION_MAPPINGS +from photoshop.api.enumerations import JavaScriptExecutionMode from photoshop.api.errors import PhotoshopPythonAPIError +if TYPE_CHECKING: + from photoshop.api.application import Application + + class Photoshop: """Core API for all photoshop objects.""" @@ -30,7 +28,7 @@ class Photoshop: _reg_path = "SOFTWARE\\Adobe\\Photoshop" object_name: str = "Application" - def __init__(self, ps_version: Optional[str] = None, parent: Any = None): + def __init__(self, ps_version: str | None = None, parent: "Photoshop | FullyDynamicDispatch | None" = None): """ Initialize the Photoshop core object. @@ -40,8 +38,9 @@ def __init__(self, ps_version: Optional[str] = None, parent: Any = None): """ # Establish the initial app and program ID ps_version = os.getenv("PS_VERSION", ps_version) - self._app_id = PHOTOSHOP_VERSION_MAPPINGS.get(ps_version, "") - self._has_parent, self.adobe, self.app = False, None, None + self._app_id = PHOTOSHOP_VERSION_MAPPINGS.get(ps_version, "") if ps_version else "" + self.adobe: FullyDynamicDispatch | None = None + app: FullyDynamicDispatch | None = None # Store current photoshop version if ps_version: @@ -49,42 +48,30 @@ def __init__(self, ps_version: Optional[str] = None, parent: Any = None): # Establish the application object using provided version ID if self.app_id: - self.app = self._get_application_object([self.app_id]) - if not self.app: - # Attempt unsuccessful - self._logger.debug( - f"Unable to retrieve Photoshop object '{self.typename}' using version '{ps_version}'." - ) + with suppress(OSError): + app = self._get_application_object([self.app_id]) # Look for version ID in registry data - if not self.app: + if not app: versions = self._get_photoshop_versions() - self.app = self._get_application_object(versions) - if not self.app: - # All attempts exhausted - raise PhotoshopPythonAPIError("Please check if you have Photoshop installed correctly.") + try: + app = self._get_application_object(versions) + except OSError as err: + raise PhotoshopPythonAPIError("Please check if you have Photoshop installed correctly.") from err # Add the parent app object if parent: - self.adobe = self.app - self.app = parent - self._has_parent = True - - def __repr__(self): - return self + self.adobe = app + self.app: Any = parent.app if isinstance(parent, Photoshop) else parent + else: + self.app: Any = app - def __call__(self, *args, **kwargs): + def __call__(self): return self.app - def __str__(self): + def __str__(self) -> str: return f"{self.__class__.__name__} <{self.program_name}>" - def __getattribute__(self, item): - try: - return super().__getattribute__(item) - except AttributeError: - return getattr(self.app, item) - """ * Debug Logger """ @@ -141,14 +128,20 @@ def app_id(self) -> str: return self._app_id @app_id.setter - def app_id(self, value: str): + def app_id(self, value: str) -> None: self._app_id = value + @property + def application(self) -> "Application": + from photoshop.api.application import Application + + return Application(parent=self.app.application) + """ * Private Methods """ - def _flag_as_method(self, *names: str): + def _flag_as_method(self, *names: str) -> None: """ * This is a hack for Photoshop's broken COM implementation. * Photoshop does not implement 'IDispatch::GetTypeInfo', so when @@ -161,7 +154,7 @@ def _flag_as_method(self, *names: str): if isinstance(self.app, FullyDynamicDispatch): self.app._FlagAsMethod(*names) - def _get_photoshop_versions(self) -> List[str]: + def _get_photoshop_versions(self) -> list[str]: """Retrieve a list of Photoshop version ID's from registry.""" with suppress(OSError, IndexError): key = self._open_key(self._reg_path) @@ -172,7 +165,7 @@ def _get_photoshop_versions(self) -> List[str]: self._logger.debug("Unable to find Photoshop version number in HKEY_LOCAL_MACHINE registry!") return [] - def _get_application_object(self, versions: List[str] = None) -> Optional[Dispatch]: + def _get_application_object(self, versions: list[str] | None = None) -> FullyDynamicDispatch: """ Try each version string until a valid Photoshop application Dispatch object is returned. @@ -185,11 +178,20 @@ def _get_application_object(self, versions: List[str] = None) -> Optional[Dispat Raises: OSError: If a Dispatch object wasn't resolved. """ - for v in versions: - self.app_id = v - with suppress(OSError): - return CreateObject(self.program_name, dynamic=True) - return + if versions: + err: OSError | None = None + for v in versions: + self.app_id = v + + try: + return CreateObject(self.program_name, dynamic=True) + except OSError as exc: + err = exc + if err: + self._logger.debug(f"Failed to create Photoshop Application object. Tried versions {versions}") + raise err from err + # Try the regular way if versions aren't available. + return CreateObject("Photoshop.Application", dynamic=True) """ * Public Methods @@ -212,9 +214,14 @@ def get_script_path(self) -> str: """str: The absolute scripts path of Photoshop.""" return os.path.join(self.presets_path, "Scripts") - def eval_javascript(self, javascript: str, Arguments: Any = None, ExecutionMode: Any = None) -> str: + def eval_javascript( + self, + javascript: str, + Arguments: list[Any] | tuple[Any] | None = None, + ExecutionMode: JavaScriptExecutionMode | None = None, + ) -> str: """Instruct the application to execute javascript code.""" - executor = self.adobe if self._has_parent else self.app + executor = self.adobe if self.adobe else self.app return executor.doJavaScript(javascript, Arguments, ExecutionMode) """ diff --git a/photoshop/api/_document.py b/photoshop/api/_document.py index ff8cd36c..c97e75af 100644 --- a/photoshop/api/_document.py +++ b/photoshop/api/_document.py @@ -13,37 +13,58 @@ """ -# Import built-in modules +from _ctypes import COMError +from logging import getLogger +from os import PathLike from pathlib import Path -from typing import List -from typing import NoReturn -from typing import Optional -from typing import TypeVar -from typing import Union +from typing import TYPE_CHECKING, Optional -# Import third-party modules -from comtypes import COMError - -# Import local modules from photoshop.api._artlayer import ArtLayer from photoshop.api._artlayers import ArtLayers +from photoshop.api._channel import Channel from photoshop.api._channels import Channels from photoshop.api._core import Photoshop from photoshop.api._documentinfo import DocumentInfo +from photoshop.api._layer import Layer from photoshop.api._layerComps import LayerComps +from photoshop.api._layers import Layers from photoshop.api._layerSet import LayerSet from photoshop.api._layerSets import LayerSets -from photoshop.api._layers import Layers -from photoshop.api._selection import Selection -from photoshop.api.enumerations import ExportType -from photoshop.api.enumerations import ExtensionType -from photoshop.api.enumerations import SaveOptions -from photoshop.api.enumerations import TrimType +from photoshop.api.enumerations import ( + AnchorPosition, + BitsPerChannelType, + ChangeMode, + ColorProfileType, + Direction, + DocumentMode, + ExportType, + ExtensionType, + Intent, + MeasurementSource, + ResampleMethod, + SaveOptions, + SourceSpaceType, + TrimType, +) +from photoshop.api.path_items import PathItems +from photoshop.api.protocols import HistoryState, MeasurementScale, XMPMetadata from photoshop.api.save_options import ExportOptionsSaveForWeb +from photoshop.api.save_options.bmp import BMPSaveOptions +from photoshop.api.save_options.eps import EPSSaveOptions +from photoshop.api.save_options.gif import GIFSaveOptions +from photoshop.api.save_options.jpg import JPEGSaveOptions +from photoshop.api.save_options.pdf import PDFSaveOptions +from photoshop.api.save_options.png import PNGSaveOptions +from photoshop.api.save_options.psd import PhotoshopSaveOptions +from photoshop.api.save_options.tag import TargaSaveOptions +from photoshop.api.save_options.tif import TiffSaveOptions -# Custom types. -PS_Layer = TypeVar("PS_Layer", LayerSet, ArtLayer) +if TYPE_CHECKING: + # Import local modules + from photoshop.api._selection import Selection + +_logger = getLogger(__name__) # pylint: disable=too-many-public-methods @@ -56,7 +77,7 @@ class Document(Photoshop): object_name = "Application" - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) self._flag_as_method( "autoCount", @@ -64,6 +85,7 @@ def __init__(self, parent): "close", "convertProfile", "Flatten", + "flipCanvas", "mergeVisibleLayers", "crop", "export", @@ -77,7 +99,9 @@ def __init__(self, parent): "splitChannels", "trap", "trim", + "resizeCanvas", "resizeImage", + "rotateCanvas", ) @property @@ -85,15 +109,18 @@ def artLayers(self) -> ArtLayers: return ArtLayers(self.app.artLayers) @property - def activeLayer(self) -> PS_Layer: + def activeLayer(self) -> ArtLayer | LayerSet: """The selected layer.""" type_ = self.eval_javascript("app.activeDocument.activeLayer.typename") - mappings = {"LayerSet": LayerSet, "ArtLayer": ArtLayer} + mappings: dict[str, type[ArtLayer] | type[LayerSet]] = { + "LayerSet": LayerSet, + "ArtLayer": ArtLayer, + } func = mappings[type_] return func(self.app.activeLayer) @activeLayer.setter - def activeLayer(self, layer) -> NoReturn: + def activeLayer(self, layer: Layer) -> None: """Sets the select layer as active layer. Args: @@ -101,67 +128,67 @@ def activeLayer(self, layer) -> NoReturn: ._layerSet.LayerSet): The artLayer. """ - self.app.activeLayer = layer + self.app.activeLayer = layer.app @property - def activeChannels(self): + def activeChannels(self) -> list[Channel]: """The selected channels.""" - return self.app.activeChannels + return [Channel(channel) for channel in self.app.activeChannels] @activeChannels.setter - def activeChannels(self, channels): - self.app.activeChannels = channels + def activeChannels(self, channels: list[Channel]) -> None: + self.app.activeChannels = [channel.app for channel in channels] @property - def activeHistoryBrushSource(self): + def activeHistoryBrushSource(self) -> HistoryState: """The history state to use with the history brush.""" return self.app.activeHistoryBrushSource @property - def activeHistoryState(self): + def activeHistoryState(self) -> HistoryState: """The current history state for this document.""" return self.app.activeHistoryState @activeHistoryState.setter - def activeHistoryState(self, state): + def activeHistoryState(self, state: HistoryState) -> None: self.app.activeHistoryState = state @property - def backgroundLayer(self): + def backgroundLayer(self) -> ArtLayer: """The background layer for the Document.""" - return self.app.backgroundLayer + return ArtLayer(self.app.backgroundLayer) @property - def bitsPerChannel(self): + def bitsPerChannel(self) -> BitsPerChannelType: """The number of bits per channel.""" - return self.app.bitsPerChannel + return BitsPerChannelType(self.app.bitsPerChannel) @bitsPerChannel.setter - def bitsPerChannel(self, value): + def bitsPerChannel(self, value: BitsPerChannelType) -> None: self.app.bitsPerChannel = value @property - def channels(self): + def channels(self) -> Channels: return Channels(self.app.channels) @property - def colorProfileName(self): + def colorProfileName(self) -> str: """The name of the color profile. Valid only when no value is specified for color profile kind (to indicate a custom color profile).""" return self.app.colorProfileName @colorProfileName.setter - def colorProfileName(self, name): + def colorProfileName(self, name: str) -> None: self.app.colorProfileName = name @property - def colorProfileType(self): + def colorProfileType(self) -> ColorProfileType: """The type of color model that defines the working space of the Document.""" - return self.app.colorProfileType + return ColorProfileType(self.app.colorProfileType) @colorProfileType.setter - def colorProfileType(self, profile_type): + def colorProfileType(self, profile_type: ColorProfileType) -> None: self.app.colorProfileType = profile_type @property @@ -170,9 +197,9 @@ def colorSamplers(self): return self.app.colorSamplers @property - def componentChannels(self): + def componentChannels(self) -> list[Channel]: """The color component channels for this Document.""" - return self.app.componentChannels + return [Channel(channel) for channel in self.app.componentChannels] @property def countItems(self): @@ -180,22 +207,20 @@ def countItems(self): return self.app.countItems @property - def fullName(self): + def fullName(self) -> Path | None: """The full path name of the Document.""" try: return Path(self.app.fullName) except COMError: - self.eval_javascript( - 'alert ("Please save your Document first!",' '"{}")'.format(self.name), - ) + _logger.exception(f"Please save your Document first: {self.name}") @property - def height(self): + def height(self) -> float: """The height of the Document.""" return self.app.Height @property - def histogram(self): + def histogram(self) -> tuple[int, ...]: """A histogram showing the number of pixels at each color intensity level for the composite channel.""" return self.app.Histogram @@ -206,44 +231,44 @@ def history_states(self): return self.app.HistoryStates @property - def id(self): + def id(self) -> int: """The unique ID of this Document.""" return self.app.Id @property - def info(self): + def info(self) -> DocumentInfo: """Metadata about the Document.""" return DocumentInfo(self.app.info) @property - def layerComps(self): + def layerComps(self) -> LayerComps: """The layer comps collection in this Document.""" return LayerComps(self.app.layerComps) @property - def layers(self): + def layers(self) -> Layers: """The layers collection in the Document.""" return Layers(self.app.Layers) @property - def layerSets(self): + def layerSets(self) -> LayerSets: """The layer sets collection in the Document.""" return LayerSets(self.app.layerSets) @property - def managed(self): + def managed(self) -> bool: """If true, the Document is a workgroup Document.""" return self.app.Managed @property - def measurement_scale(self): + def measurement_scale(self) -> MeasurementScale: """The measurement scale of the Document.""" return self.app.MeasurementScale @property - def mode(self): + def mode(self) -> DocumentMode: """The color profile.""" - return self.app.Mode + return DocumentMode(self.app.Mode) @property def name(self) -> str: @@ -251,30 +276,28 @@ def name(self) -> str: return self.app.name @property - def parent(self): + def parent(self) -> object: """The object's container.""" return self.app.Parent @property - def path(self) -> str: + def path(self) -> Path | None: """The path to the Document.""" try: return Path(self.app.path) except COMError: - self.eval_javascript( - 'alert ("Please save your Document first!",' '"{}")'.format(self.name), - ) + _logger.exception(f"Please save your Document first: {self.name}") @path.setter - def path(self, path: str) -> NoReturn: - self.app.fullName = path + def path(self, path: str | PathLike[str]) -> None: + self.app.fullName = str(path) @property - def pathItems(self): - return self.app.pathItems + def pathItems(self) -> PathItems: + return PathItems(self.app.pathItems) @property - def pixelAspectRatio(self): + def pixelAspectRatio(self) -> float: """The (custom) pixel aspect ratio of the Document. Range: 0.100 to 10.000. @@ -288,29 +311,26 @@ def printSettings(self): return self.app.printSettings @property - def quickMaskMode(self): + def quickMaskMode(self) -> bool: """If true, the document is in Quick Mask mode.""" return self.app.quickMaskMode @property - def saved(self): + def saved(self) -> bool: """If true, the Document been saved since the last change.""" return self.app.Saved @property - def resolution(self): + def resolution(self) -> float: """The resolution of the Document (in pixels per inch)""" return self.app.resolution @property - def selection(self): + def selection(self) -> "Selection": """The selected area of the Document.""" - return Selection(self.app.selection) + from ._selection import Selection - @property - def typename(self): - """The class name of the object.""" - return self.app.typename + return Selection(self.app.selection) @property def cloudDocument(self): @@ -323,57 +343,71 @@ def cloudWorkAreaDirectory(self): return self.app.cloudWorkAreaDirectory @property - def width(self): + def width(self) -> float: return self.app.Width @property - def xmpMetadata(self): + def xmpMetadata(self) -> XMPMetadata: """The XMP properties of the Document. The Camera RAW settings are stored here.""" return self.app.xmpMetadata # Methods - def autoCount(self, *args, **kwargs): + def autoCount(self, channel: Channel, threshold: int) -> None: """Counts the objects in the Document.""" - return self.app.autoCount(*args, **kwargs) + self.app.autoCount(channel.app, threshold) - def changeMode(self, *args, **kwargs): + def changeMode(self, destinationMode: ChangeMode, options: object) -> None: """Changes the mode of the Document.""" - return self.app.changeMode(*args, **kwargs) + self.app.changeMode(destinationMode, options) - def close(self, saving=SaveOptions.DoNotSaveChanges): - return self.app.close(saving) + def close(self, saving: SaveOptions = SaveOptions.DoNotSaveChanges) -> None: + self.app.close(saving) - def convertProfile(self): - return self.app.convertProfile() - - def flatten(self): + def convertProfile( + self, + destinationProfile: str, + intent: Intent, + blackPointCompensation: bool, + dither: bool, + ) -> None: + self.app.convertProfile(destinationProfile, intent, blackPointCompensation, dither) + + def flatten(self) -> None: """Flattens all layers.""" - return self.app.Flatten() + self.app.Flatten() - def mergeVisibleLayers(self): + def flipCanvas(self, direction: Direction) -> None: + self.app.flipCanvas(direction) + + def mergeVisibleLayers(self) -> None: """Flattens all visible layers in the Document.""" - return self.app.mergeVisibleLayers() + self.app.mergeVisibleLayers() def crop( self, - bounds: List[int], - angle: Optional[float] = None, - width: Optional[int] = None, - height: Optional[int] = None, - ): + bounds: tuple[float, float, float, float], + angle: float | None = None, + width: float | None = None, + height: float | None = None, + ) -> None: """Crops the document. Args: - bounds: Four coordinates for the region remaining after cropping. + bounds: Four coordinates for the region remaining after cropping, in the following order: left, top, right, bottom. angle: The angle of cropping bounds. width: The width of the resulting document. height: The height of the resulting document. """ - return self.app.crop(bounds, angle, width, height) + self.app.crop(bounds, angle, width, height) - def exportDocument(self, file_path: str, exportAs: ExportType, options: Union[ExportOptionsSaveForWeb]): + def exportDocument( + self, + file_path: str, + exportAs: ExportType, + options: ExportOptionsSaveForWeb, + ) -> None: """Exports the Document. Note: @@ -385,53 +419,73 @@ def exportDocument(self, file_path: str, exportAs: ExportType, options: Union[Ex """ file_path = file_path.replace("\\", "/") - self.app.export(file_path, exportAs, options) + self.app.export(file_path, exportAs, options.app) - def duplicate(self, name=None, merge_layers_only=False): + def duplicate(self, name: str | None = None, merge_layers_only: bool = False) -> "Document": return Document(self.app.duplicate(name, merge_layers_only)) - def paste(self): + def paste(self, into_selection: bool | None = None) -> None: """Pastes contents of the clipboard into the Document.""" - self.eval_javascript("app.activeDocument.paste()") - return self.activeLayer + self.app.paste(into_selection) - def print(self): + def print( + self, + sourceSpace: SourceSpaceType, + printSpace: str, + intent: Intent, + blackPointCompensation: bool, + ) -> None: """Prints the document.""" - return self.app.print() + self.app.print(sourceSpace, printSpace, intent, blackPointCompensation) - def printOneCopy(self): + def printOneCopy(self) -> None: self.app.printOneCopy() - def rasterizeAllLayers(self): - return self.app.rasterizeAllLayers() + def rasterizeAllLayers(self) -> None: + self.app.rasterizeAllLayers() - def recordMeasurements(self, source, dataPoints): + def recordMeasurements(self, source: MeasurementSource, dataPoints: str) -> None: """Records the measurements of document.""" self.app.recordMeasurements(source, dataPoints) - def reveal_all(self): + def reveal_all(self) -> None: """Expands the Document to show clipped sections.""" - return self.app.revealAll() + self.app.revealAll() - def save(self): + def save(self) -> None: """Saves the Document.""" - return self.app.save() + self.app.save() - def saveAs(self, file_path, options, asCopy=True, extensionType=ExtensionType.Lowercase): + def saveAs( + self, + file_path: str, + options: BMPSaveOptions + | EPSSaveOptions + | GIFSaveOptions + | JPEGSaveOptions + | PDFSaveOptions + | PNGSaveOptions + | PhotoshopSaveOptions + | TargaSaveOptions + | TiffSaveOptions + | None = None, + asCopy: bool = False, + extensionType: ExtensionType = ExtensionType.Lowercase, + ) -> None: """Saves the documents with the specified save options. Args: - file_path (str): Absolute path of psd file. - options (JPEGSaveOptions): Save options. - asCopy (bool): + file_path: Absolute path of psd file. + options: Save options. + asCopy: Saves the document as a copy, leaving the original open. """ - return self.app.saveAs(file_path, options, asCopy, extensionType) + self.app.saveAs(file_path, options.app if options else None, asCopy, extensionType) - def splitChannels(self): + def splitChannels(self) -> None: """Splits the channels of the document.""" self.app.splitChannels() - def suspendHistory(self, historyString, javaScriptString): + def suspendHistory(self, historyString: str, javaScriptString: str) -> None: """Provides a single history state for the entire script. Allows a single undo for all actions taken in the script. @@ -439,7 +493,7 @@ def suspendHistory(self, historyString, javaScriptString): """ self.eval_javascript(f"app.activeDocument.suspendHistory('{historyString}', '{javaScriptString}')") - def trap(self, width: int): + def trap(self, width: int) -> None: """ Applies trapping to a CMYK document. Valid only when ‘mode’ = CMYK. @@ -454,7 +508,7 @@ def trim( left: Optional[bool] = True, bottom: Optional[bool] = True, right: Optional[bool] = True, - ): + ) -> None: """Trims the transparent area around the image on the specified sides of the canvas. Args: @@ -471,16 +525,35 @@ def trim( right: If true, trims away the right of the document. """ - return self.app.trim(trim_type, top, left, bottom, right) + self.app.trim(trim_type, top, left, bottom, right) - def resizeImage(self, width: int, height: int, resolution: int = 72, automatic: int = 8): + def resizeCanvas( + self, + width: int, + height: int, + anchor: AnchorPosition = AnchorPosition.MiddleCenter, + ) -> None: + self.app.resizeCanvas(width, height, anchor) + + def resizeImage( + self, + width: int, + height: int, + resolution: float = 72, + resampleMethod: ResampleMethod = ResampleMethod.Automatic, + amount: int = 0, + ) -> None: """Changes the size of the image. Args: width: The desired width of the image. height: The desired height of the image. resolution: The resolution (in pixels per inch) - automatic: Value for automatic. + resampleMethod: The downsample method. + amount: Amount of noise value when using preserve details (range: 0 - 100) """ - return self.app.resizeImage(width, height, resolution, automatic) + self.app.resizeImage(width, height, resolution, resampleMethod, amount) + + def rotateCanvas(self, angle: float) -> None: + self.app.rotateCanvas(angle) diff --git a/photoshop/api/_documentinfo.py b/photoshop/api/_documentinfo.py index c24068cd..05f4a1a2 100644 --- a/photoshop/api/_documentinfo.py +++ b/photoshop/api/_documentinfo.py @@ -7,19 +7,22 @@ # Import built-in modules from pprint import pformat +from typing import Sequence # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.enumerations import CopyrightedType +from photoshop.api.enumerations import Urgency # pylint: disable=too-many-public-methods class DocumentInfo(Photoshop): """Metadata about a document object.""" - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) - def __str__(self): + def __str__(self) -> str: return pformat( { "author": self.author, @@ -49,195 +52,195 @@ def __str__(self): ) @property - def author(self): + def author(self) -> str: """str: The author.""" return self.app.author @author.setter - def author(self, name): + def author(self, name: str) -> None: self.app.author = name @property - def authorPosition(self): + def authorPosition(self) -> str: """str:The author’s position.""" return self.app.authorPosition @authorPosition.setter - def authorPosition(self, name): + def authorPosition(self, name: str) -> None: self.app.authorPosition = name @property - def caption(self): + def caption(self) -> str: return self.app.caption @caption.setter - def caption(self, name): + def caption(self, name: str) -> None: self.app.caption = name @property - def captionWriter(self): + def captionWriter(self) -> str: return self.app.captionWriter @captionWriter.setter - def captionWriter(self, name): + def captionWriter(self, name: str) -> None: self.app.captionWriter = name @property - def category(self): + def category(self) -> str: """str: The document category.""" return self.app.category @category.setter - def category(self, name): + def category(self, name: str) -> None: self.app.category = name @property - def city(self): + def city(self) -> str: return self.app.city @city.setter - def city(self, city_name): + def city(self, city_name: str) -> None: self.app.city = city_name @property - def copyrightNotice(self): + def copyrightNotice(self) -> str: """str: The copyright notice.""" return self.app.copyrightNotice @copyrightNotice.setter - def copyrightNotice(self, name): + def copyrightNotice(self, name: str) -> None: self.app.copyrightNotice = name @property - def copyrighted(self): - """str: The copyright status.""" - return self.app.copyrighted + def copyrighted(self) -> CopyrightedType: + """The copyright status.""" + return CopyrightedType(self.app.copyrighted) @copyrighted.setter - def copyrighted(self, info): + def copyrighted(self, info: CopyrightedType) -> None: self.app.copyrighted = info @property - def country(self): + def country(self) -> str: return self.app.country @country.setter - def country(self, name): + def country(self, name: str) -> None: self.app.country = name @property - def creationDate(self): + def creationDate(self) -> str: return self.app.creationDate @creationDate.setter - def creationDate(self, name): + def creationDate(self, name: str) -> None: self.app.creationDate = name @property - def credit(self): + def credit(self) -> str: """str: The author credit.""" return self.app.credit @credit.setter - def credit(self, value): + def credit(self, value: str) -> None: self.app.credit = value @property - def exif(self): + def exif(self) -> tuple[tuple[str, str], ...]: return self.app.exif @exif.setter - def exif(self, info): + def exif(self, info: Sequence[tuple[str, str]]) -> None: self.app.exif = info @property - def headline(self): + def headline(self) -> str: return self.app.headline @headline.setter - def headline(self, value): + def headline(self, value: str) -> None: self.app.headline = value @property - def instructions(self): + def instructions(self) -> str: return self.app.instructions @instructions.setter - def instructions(self, value): + def instructions(self, value: str) -> None: self.app.instructions = value @property - def jobName(self): + def jobName(self) -> str: return self.app.jobName @jobName.setter - def jobName(self, job): + def jobName(self, job: str) -> None: self.app.jobName = job @property - def keywords(self): + def keywords(self) -> tuple[str, ...] | None: return self.app.keywords @keywords.setter - def keywords(self, words): + def keywords(self, words: Sequence[str]) -> None: self.app.keywords = words @property - def ownerUrl(self): + def ownerUrl(self) -> str: return self.app.ownerUrl @ownerUrl.setter - def ownerUrl(self, url): + def ownerUrl(self, url: str) -> None: self.app.ownerUrl = url @property - def provinceState(self): + def provinceState(self) -> str: """str: The state or province.""" return self.app.provinceState @provinceState.setter - def provinceState(self, state_name): + def provinceState(self, state_name: str) -> None: self.app.provinceState = state_name @property - def source(self): + def source(self) -> str: return self.app.source @source.setter - def source(self, source_name): + def source(self, source_name: str) -> None: self.app.source = source_name @property - def supplementalCategories(self): + def supplementalCategories(self) -> tuple[str, ...]: """str: Other categories.""" return self.app.supplementalCategories @supplementalCategories.setter - def supplementalCategories(self, info): + def supplementalCategories(self, info: Sequence[str]) -> None: self.app.supplementalCategories = info @property - def title(self): + def title(self) -> str: return self.app.title @title.setter - def title(self, name): + def title(self, name: str) -> None: self.app.title = name @property - def transmissionReference(self): + def transmissionReference(self) -> str: """str: The transmission reference.""" return self.app.transmissionReference @transmissionReference.setter - def transmissionReference(self, reference): + def transmissionReference(self, reference: str) -> None: self.app.transmissionReference = reference @property - def urgency(self): + def urgency(self) -> Urgency: """The document urgency.""" - return self.app.urgency + return Urgency(self.app.urgency) @urgency.setter - def urgency(self, status): + def urgency(self, status: Urgency) -> None: self.app.urgency = status diff --git a/photoshop/api/_documents.py b/photoshop/api/_documents.py index 365aaefc..86d10d25 100644 --- a/photoshop/api/_documents.py +++ b/photoshop/api/_documents.py @@ -1,41 +1,38 @@ # Import local modules from photoshop.api._core import Photoshop from photoshop.api._document import Document +from photoshop.api.collections import CollectionOfNamedObjects from photoshop.api.enumerations import BitsPerChannelType from photoshop.api.enumerations import DocumentFill from photoshop.api.enumerations import NewDocumentMode -from photoshop.api.errors import PhotoshopPythonAPIError # pylint: disable=too-many-public-methods, too-many-arguments -class Documents(Photoshop): +class Documents(CollectionOfNamedObjects[Document, int | str]): """The collection of open documents.""" - def __init__(self, parent): - super().__init__(parent=parent) + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(Document, parent) self._flag_as_method("add") - def __len__(self) -> int: - return self.length - def add( self, - width: int = 960, - height: int = 540, + width: float = 960, + height: float = 540, resolution: float = 72.0, - name: str = None, - mode: int = NewDocumentMode.NewRGB, - initialFill: int = DocumentFill.White, + name: str | None = None, + mode: NewDocumentMode = NewDocumentMode.NewRGB, + initialFill: DocumentFill = DocumentFill.White, pixelAspectRatio: float = 1.0, - bitsPerChannel: int = BitsPerChannelType.Document8Bits, - colorProfileName: str = None, + bitsPerChannel: BitsPerChannelType = BitsPerChannelType.Document8Bits, + colorProfileName: str | None = None, ) -> Document: """Creates a new document object and adds it to this collections. Args: - width (int): The width of the document. - height (int): The height of the document. - resolution (int): The resolution of the document (in pixels per inch) + width (float): The width of the document. Non-integer values are converted to integers. + height (float): The height of the document. Non-integer values are converted to integers. + resolution (float): The resolution of the document (in pixels per inch) name (str): The name of the document. mode (): The document mode. initialFill : The initial fill of the document. @@ -61,25 +58,3 @@ def add( colorProfileName, ) ) - - def __iter__(self) -> Document: - for doc in self.app: - self.adobe.activeDocument = doc - yield Document(doc) - - def __getitem__(self, item) -> Document: - try: - return Document(self.app[item]) - except IndexError: - raise PhotoshopPythonAPIError("Currently Photoshop did not find Documents.") - - @property - def length(self) -> int: - return len(list(self.app)) - - def getByName(self, document_name: str) -> Document: - """Get document by given document name.""" - for doc in self.app: - if doc.name == document_name: - return Document(doc) - raise PhotoshopPythonAPIError(f'Could not find a document named "{document_name}"') diff --git a/photoshop/api/_layer.py b/photoshop/api/_layer.py new file mode 100644 index 00000000..0be0a39c --- /dev/null +++ b/photoshop/api/_layer.py @@ -0,0 +1,156 @@ +from typing import TYPE_CHECKING + +from photoshop.api._core import Photoshop +from photoshop.api.enumerations import AnchorPosition, BlendMode, ElementPlacement +from photoshop.api.protocols import XMPMetadata + + +if TYPE_CHECKING: + from photoshop.api._document import Document + from photoshop.api._layerSet import LayerSet + + +class Layer(Photoshop): + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(parent=parent) + self._flag_as_method( + "delete", + "duplicate", + "link", + "move", + "moveToEnd", + "resize", + "rotate", + "translate", + "unlink", + ) + + @property + def allLocked(self) -> bool: + return self.app.allLocked + + @allLocked.setter + def allLocked(self, value: bool) -> None: + self.app.allLocked = value + + @property + def blendMode(self) -> BlendMode: + return BlendMode(self.app.blendMode) + + @blendMode.setter + def blendMode(self, mode: BlendMode) -> None: + self.app.blendMode = mode + + @property + def bounds(self) -> tuple[float, float, float, float]: + """The bounding rectangle of the layer.""" + return self.app.bounds + + @property + def boundsNoEffects(self) -> tuple[float, float, float, float]: + """Bounding rectangle of the Layer not including effects.""" + return self.app.boundsNoEffects + + @property + def id(self) -> int: + return self.app.id + + @property + def itemIndex(self) -> int: + return self.app.itemIndex + + @property + def linkedLayers(self) -> list["Layer"]: + """Get all layers linked to this layer. + + Returns: + list: Layer objects""" + return [Layer(layer) for layer in self.app.linkedLayers] + + @property + def name(self) -> str: + return self.app.name + + @name.setter + def name(self, text: str) -> None: + self.app.name = text + + @property + def opacity(self) -> float: + """The layer's master opacity (as a percentage). Range: 0.0 to 100.0.""" + return round(self.app.opacity) + + @opacity.setter + def opacity(self, value: float) -> None: + self.app.opacity = value + + @property + def parent(self) -> "Document | LayerSet": + """The layers's container.""" + parent = self.app.parent + try: + parent.resolution + # Import local modules + from photoshop.api._document import Document + + return Document(parent) + except NameError: + # Import local modules + from photoshop.api._layerSet import LayerSet + + return LayerSet(parent) + + @property + def visible(self) -> bool: + return self.app.visible + + @visible.setter + def visible(self, value: bool) -> None: + self.app.visible = value + + @property + def xmpMetadata(self) -> XMPMetadata: + return self.app.xmpMetadata + + def duplicate( + self, + relativeObject: "Layer | None" = None, + insertionLocation: ElementPlacement | None = None, + ) -> "Layer": + """Duplicates the layer. + + Args: + relativeObject: Layer or LayerSet. + insertionLocation: The location to insert the layer. + + Returns: + Layer: The duplicated layer. + """ + return Layer(self.app.duplicate(relativeObject.app if relativeObject else None, insertionLocation)) + + def link(self, with_layer: "Layer") -> None: + self.app.link(with_layer.app) + + def move(self, relativeObject: "Layer | LayerSet", insertionLocation: ElementPlacement) -> None: + self.app.move(relativeObject.app, insertionLocation) + + def moveToEnd(self, layer_set: "LayerSet") -> None: + self.app.moveToEnd(layer_set.app) + + def remove(self) -> None: + """Removes this layer from the document.""" + self.app.delete() + + def resize(self, horizontal: float, vertical: float, anchor: AnchorPosition) -> None: + """Scales the object.""" + self.app.resize(horizontal, vertical, anchor) + + def rotate(self, angle: float, anchor: AnchorPosition = AnchorPosition.MiddleCenter) -> None: + return self.app.rotate(angle, anchor) + + def translate(self, deltaX: float, deltaY: float) -> None: + return self.app.translate(deltaX, deltaY) + + def unlink(self) -> None: + """Unlink this layer from any linked layers.""" + self.app.unlink() diff --git a/photoshop/api/_layerComp.py b/photoshop/api/_layerComp.py index 79e60049..a9af259b 100644 --- a/photoshop/api/_layerComp.py +++ b/photoshop/api/_layerComp.py @@ -1,11 +1,19 @@ +# Import built-in modules +from typing import TYPE_CHECKING + # Import local modules from photoshop.api._core import Photoshop +if TYPE_CHECKING: + # Import local modules + from photoshop.api._document import Document + + class LayerComp(Photoshop): """A snapshot of a state of the layers in a document (can be used to view different page layouts or compostions).""" - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) self._flag_as_method( "apply", @@ -14,87 +22,82 @@ def __init__(self, parent): "resetfromComp", ) - def __len__(self): - return self.length - @property - def appearance(self): + def appearance(self) -> bool: return self.app.appearance @appearance.setter - def appearance(self, value): + def appearance(self, value: bool) -> None: self.app.appearance = value @property - def childLayerCompState(self): + def childLayerCompState(self) -> bool: return self.app.childLayerCompState @childLayerCompState.setter - def childLayerCompState(self, value): + def childLayerCompState(self, value: bool) -> None: self.app.childLayerCompState = value @property - def comment(self): + def comment(self) -> str: return self.app.comment @comment.setter - def comment(self, text): + def comment(self, text: str) -> None: self.app.comment = text @property - def name(self): + def name(self) -> str: return self.app.name @name.setter - def name(self, text): + def name(self, text: str) -> None: self.app.name = text @property - def parent(self): - return self.app.parent + def parent(self) -> "Document": + from ._document import Document + + return Document(self.app.parent) @property - def position(self): + def position(self) -> bool: return self.app.position @position.setter - def position(self, value): + def position(self, value: bool) -> None: self.app.position = value @property - def selected(self): + def selected(self) -> bool: """True if the layer comp is currently selected.""" return self.app.selected @selected.setter - def selected(self, value): + def selected(self, value: bool) -> None: self.app.selected = value @property - def typename(self): - return self.app.typename - - @property - def visibility(self): + def visibility(self) -> bool: """True to use layer visibility settings.""" return self.app.visibility @visibility.setter - def visibility(self, value): + def visibility(self, value: bool) -> None: self.app.visibility = value - def apply(self): + def apply(self) -> None: """Applies the layer comp to the document.""" self.app.apply() - def recapture(self): + def recapture(self) -> None: """Recaptures the current layer state(s) for this layer comp.""" self.app.recapture() - def remove(self): + def remove(self) -> None: """Deletes the layerComp object.""" self.app.remove() - def resetfromComp(self): + def resetfromComp(self) -> None: """Resets the layer comp state to thedocument state.""" self.app.resetfromComp() diff --git a/photoshop/api/_layerComps.py b/photoshop/api/_layerComps.py index e57dcccf..e453a8d2 100644 --- a/photoshop/api/_layerComps.py +++ b/photoshop/api/_layerComps.py @@ -1,58 +1,27 @@ # Import local modules from photoshop.api._core import Photoshop from photoshop.api._layerComp import LayerComp -from photoshop.api.errors import PhotoshopPythonAPIError +from photoshop.api.collections import CollectionOfNamedObjects +from photoshop.api.collections import CollectionOfRemovables -class LayerComps(Photoshop): +class LayerComps( + CollectionOfRemovables[LayerComp, int | str], + CollectionOfNamedObjects[LayerComp, int | str], +): """The layer comps collection in this document.""" - def __init__(self, parent): - super().__init__(parent=parent) - self._flag_as_method( - "add", - "removeAll", - ) - - def __len__(self): - return self.length - - @property - def length(self): - return len(self._layers) - - @property - def _layers(self): - return list(self.app) - - @property - def parent(self): - return self.app.parent - - @property - def typename(self): - return self.app.typename + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(LayerComp, parent=parent) + self._flag_as_method("add") def add( self, - name, - comment="No Comment.", - appearance=True, - position=True, - visibility=True, - childLayerCompStat=False, - ): + name: str, + comment: str = "No Comment.", + appearance: bool = True, + position: bool = True, + visibility: bool = True, + childLayerCompStat: bool = False, + ) -> LayerComp: return LayerComp(self.app.add(name, comment, appearance, position, visibility, childLayerCompStat)) - - def getByName(self, name): - for layer in self._layers: - if layer.name == name: - return LayerComp(layer) - raise PhotoshopPythonAPIError(f'Could not find a layer named "{name}"') - - def removeAll(self): - self.app.removeAll() - - def __iter__(self): - for layer in self._layers: - yield LayerComp(layer) diff --git a/photoshop/api/_layerSet.py b/photoshop/api/_layerSet.py index 3351da61..ac8020c7 100644 --- a/photoshop/api/_layerSet.py +++ b/photoshop/api/_layerSet.py @@ -1,144 +1,75 @@ -# Import local modules +from collections.abc import Sequence +from typing import TYPE_CHECKING, Iterator + from photoshop.api._artlayer import ArtLayer from photoshop.api._artlayers import ArtLayers +from photoshop.api._channel import Channel +from photoshop.api._channels import Channels from photoshop.api._core import Photoshop -from photoshop.api._layers import Layers -from photoshop.api.enumerations import AnchorPosition -from photoshop.api.enumerations import BlendMode +from photoshop.api._layer import Layer +from photoshop.api.enumerations import ElementPlacement + + +if TYPE_CHECKING: + from photoshop.api._layers import Layers + from photoshop.api._layerSets import LayerSets -class LayerSet(Photoshop): +class LayerSet(Layer): """A group of layer objects, which can include art layer objects and other (nested) layer set objects. A single command or set of commands manipulates all layers in a layer set object. """ - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) self._flag_as_method( - "merge", - "duplicate", "add", - "delete", - "link", - "move", - "resize", - "rotate", - "translate", - "unlink", + "merge", ) @property - def allLocked(self): - return self.app.allLocked - - @allLocked.setter - def allLocked(self, value): - self.app.allLocked = value - - @property - def artLayers(self): + def artLayers(self) -> ArtLayers: return ArtLayers(self.app.artLayers) @property - def blendMode(self): - return BlendMode(self.app.blendMode) - - @property - def bounds(self): - """The bounding rectangle of the layer set.""" - return self.app.bounds - - @property - def enabledChannels(self): - return self.app.enabledChannels + def enabledChannels(self) -> Channels: + return Channels(self.app.enabledChannels) @enabledChannels.setter - def enabledChannels(self, value): - self.app.enabledChannels = value + def enabledChannels(self, value: Sequence[Channel] | Channels) -> None: + self.app.enabledChannels = value.app if isinstance(value, Channels) else [channel.app for channel in value] @property - def layers(self): + def layers(self) -> "Layers": + # pylint: disable=import-outside-toplevel + from ._layers import Layers + return Layers(self.app.layers) @property - def layerSets(self): + def layerSets(self) -> "LayerSets": # pylint: disable=import-outside-toplevel from ._layerSets import LayerSets return LayerSets(self.app.layerSets) - @property - def linkedLayers(self): - """The layers linked to this layerSet object.""" - return self.app.linkedLayers or [] - - @property - def name(self) -> str: - return self.app.name - - @name.setter - def name(self, value): - """The name of this layer set.""" - self.app.name = value - - @property - def opacity(self): - """The master opacity of the set.""" - return round(self.app.opacity) - - @opacity.setter - def opacity(self, value): - self.app.opacity = value - - @property - def parent(self): - return self.app.parent - - @property - def visible(self): - return self.app.visible - - @visible.setter - def visible(self, value): - self.app.visible = value + def duplicate( + self, + relativeObject: Layer | None = None, + insertionLocation: ElementPlacement | None = None, + ): + return LayerSet(self.app.duplicate(relativeObject.app if relativeObject else None, insertionLocation)) - def duplicate(self, relativeObject=None, insertionLocation=None): - return LayerSet(self.app.duplicate(relativeObject, insertionLocation)) - - def link(self, with_layer): - self.app.link(with_layer) - - def add(self): + def add(self) -> "LayerSet": """Adds an element.""" - self.app.add() + return LayerSet(self.app.add()) def merge(self) -> ArtLayer: """Merges the layer set.""" return ArtLayer(self.app.merge()) - def move(self, relativeObject, insertionLocation): - self.app.move(relativeObject, insertionLocation) - - def remove(self): - """Remove this layer set from the document.""" - self.app.delete() - - def resize(self, horizontal=None, vertical=None, anchor: AnchorPosition = None): - self.app.resize(horizontal, vertical, anchor) - - def rotate(self, angle, anchor=None): - self.app.rotate(angle, anchor) - - def translate(self, delta_x, delta_y): - """Moves the position relative to its current position.""" - self.app.translate(delta_x, delta_y) - - def unlink(self): - """Unlinks the layer set.""" - self.app.unlink() - - def __iter__(self): - for layer in self.app: + def __iter__(self) -> Iterator[Layer]: + for layer in self.layers: yield layer diff --git a/photoshop/api/_layerSets.py b/photoshop/api/_layerSets.py index 8b5b3aef..98db50eb 100644 --- a/photoshop/api/_layerSets.py +++ b/photoshop/api/_layerSets.py @@ -1,62 +1,17 @@ -# Import third-party modules -from comtypes import ArgumentError - # Import local modules from photoshop.api._core import Photoshop from photoshop.api._layerSet import LayerSet -from photoshop.api.errors import PhotoshopPythonAPIError +from photoshop.api.collections import CollectionOfNamedObjects +from photoshop.api.collections import CollectionOfRemovables +from photoshop.api.collections import CollectionWithAdd -class LayerSets(Photoshop): +class LayerSets( + CollectionWithAdd[LayerSet, int | str], + CollectionOfRemovables[LayerSet, int | str], + CollectionOfNamedObjects[LayerSet, int | str], +): """The layer sets collection in the document.""" - def __init__(self, parent): - super().__init__(parent=parent) - self._flag_as_method( - "add", - "item", - "removeAll", - ) - - def __len__(self): - return self.length - - def __iter__(self): - for layer_set in self.app: - yield layer_set - - def __getitem__(self, key: str): - """Access a given LayerSet using dictionary key lookup.""" - try: - return LayerSet(self.app[key]) - except ArgumentError: - raise PhotoshopPythonAPIError(f'Could not find a LayerSet named "{key}"') - - @property - def _layerSets(self): - return list(self.app) - - @property - def length(self) -> int: - """Number of elements in the collection.""" - return len(self._layerSets) - - def add(self): - return LayerSet(self.app.add()) - - def item(self, index: int) -> LayerSet: - return LayerSet(self.app.item(index)) - - def removeAll(self): - self.app.removeAll() - - def getByIndex(self, index: int): - """Access LayerSet using list index lookup.""" - return LayerSet(self._layerSets[index]) - - def getByName(self, name: str) -> LayerSet: - """Get the first element in the collection with the provided name.""" - for layer in self.app: - if name == layer.name: - return LayerSet(layer) - raise PhotoshopPythonAPIError(f'Could not find a LayerSet named "{name}"') + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(LayerSet, parent) diff --git a/photoshop/api/_layers.py b/photoshop/api/_layers.py index dfe1d126..fe96aff1 100644 --- a/photoshop/api/_layers.py +++ b/photoshop/api/_layers.py @@ -1,50 +1,56 @@ +# Import built-in modules +from typing import Any +from typing import Iterator + # Import local modules from photoshop.api._artlayer import ArtLayer from photoshop.api._core import Photoshop -from photoshop.api.errors import PhotoshopPythonAPIError +from photoshop.api._layer import Layer +from photoshop.api._layerSet import LayerSet # pylint: disable=too-many-public-methods class Layers(Photoshop): """The layers collection in the document.""" - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) - self._flag_as_method( - "add", - "item", - ) + self._flag_as_method("add", "item", "removeAll") - @property - def _layers(self): - return list(self.app) + def _get_appropriate_layer(self, layer: Any) -> ArtLayer | LayerSet: + try: + layer.layers + return LayerSet(layer) + except NameError: + return ArtLayer(layer) - def __len__(self): + def __len__(self) -> int: return self.length - def __getitem__(self, key): - item = self._layers[key] - return ArtLayer(item) + def __getitem__(self, key: int) -> ArtLayer | LayerSet: + for idx, layer in enumerate(self.app): + if idx == key: + return self._get_appropriate_layer(layer) + raise KeyError(f"Key '{key}' was not found in {type(self)}.") @property - def length(self): - return len(self._layers) + def length(self) -> int: + return len(list(self.app)) - def removeAll(self): + def removeAll(self) -> None: """Deletes all elements.""" - for layer in self.app: - ArtLayer(layer).remove() + self.app.removeAll() - def item(self, index): - return ArtLayer(self.app.item(index)) + def item(self, index: int) -> Layer: + return self[index] - def __iter__(self): - for layer in self._layers: - yield ArtLayer(layer) + def __iter__(self) -> Iterator[ArtLayer | LayerSet]: + for layer in self.app: + yield self._get_appropriate_layer(layer) - def getByName(self, name: str) -> ArtLayer: + def getByName(self, name: str) -> ArtLayer | LayerSet | None: """Get the first element in the collection with the provided name.""" for layer in self.app: if layer.name == name: - return ArtLayer(layer) - raise PhotoshopPythonAPIError("X") + return self._get_appropriate_layer(layer) + return None diff --git a/photoshop/api/_measurement_log.py b/photoshop/api/_measurement_log.py index 1e2d9720..09201412 100644 --- a/photoshop/api/_measurement_log.py +++ b/photoshop/api/_measurement_log.py @@ -1,21 +1,30 @@ +# Import built-in modules +from typing import Sequence + # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.enumerations import MeasurementRange class MeasurementLog(Photoshop): """The log of measurements taken.""" - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) self._flag_as_method( "exportMeasurements", "deleteMeasurements", ) - def exportMeasurements(self, file_path: str, range_: int = None, data_point=None): + def exportMeasurements( + self, + file_path: str, + range_: MeasurementRange | None = None, + data_point: Sequence[str] | None = None, + ): if data_point is None: data_point = [] self.app.exportMeasurements(file_path, range_, data_point) - def deleteMeasurements(self, range_: int): + def deleteMeasurements(self, range_: MeasurementRange) -> None: self.app.deleteMeasurements(range_) diff --git a/photoshop/api/_notifier.py b/photoshop/api/_notifier.py index e0f651de..349d96c9 100644 --- a/photoshop/api/_notifier.py +++ b/photoshop/api/_notifier.py @@ -5,6 +5,7 @@ Notifiers must be enabled using the Application.notifiersEnabled property """ + # Import built-in modules from pathlib import Path @@ -13,19 +14,19 @@ class Notifier(Photoshop): - def __init__(self, parent=None): - super().__init__() + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(parent=parent) self._flag_as_method( "remove", ) @property - def event(self): + def event(self) -> str: """The event identifier, a four-character code or a unique string.""" return self.app.event @property - def eventClass(self): + def eventClass(self) -> str: """The class identifier, a four-character code or a unique string. When an event applies to multiple types of objects, use this @@ -42,7 +43,7 @@ def eventFile(self) -> Path: activates the notifier.""" return Path(self.app.eventFile) - def remove(self): + def remove(self) -> None: """Deletes this object. You can also remove a Notifier object @@ -53,4 +54,4 @@ def remove(self): Photoshop CC help for more information. """ - return self.app.remove() + self.app.remove() diff --git a/photoshop/api/_notifiers.py b/photoshop/api/_notifiers.py index 3ecbcdc3..32515b2f 100644 --- a/photoshop/api/_notifiers.py +++ b/photoshop/api/_notifiers.py @@ -10,47 +10,22 @@ """ -# Import built-in modules -from typing import Any -from typing import Optional - -# Import local modules from photoshop.api._core import Photoshop from photoshop.api._notifier import Notifier +from photoshop.api.collections import CollectionOfRemovables -class Notifiers(Photoshop): +class Notifiers(CollectionOfRemovables[Notifier, int]): """The `notifiers` currently configured (in the Scripts Events Manager menu in the application).""" - def __init__(self, parent: Optional[Any] = None): - super().__init__(parent=parent) - self._flag_as_method( - "add", - "removeAll", - ) - - @property - def _notifiers(self) -> list: - return [n for n in self.app] - - def __len__(self): - return self.length - - def __iter__(self): - for app in self.app: - yield app - - def __getitem__(self, item): - return self._notifiers[item] - - @property - def length(self): - return len(self._notifiers) + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(type=Notifier, parent=parent) + self._flag_as_method("add") - def add(self, event, event_file: Optional[Any] = None, event_class: Optional[Any] = None) -> Notifier: - self.parent.notifiersEnabled = True + def add(self, event: str, event_file: str, event_class: str | None = None) -> Notifier: + self.app.application.notifiersEnabled = True return Notifier(self.app.add(event, event_file, event_class)) - def removeAll(self): + def removeAll(self) -> None: self.app.removeAll() - self.parent.notifiersEnabled = False + self.app.application.notifiersEnabled = False diff --git a/photoshop/api/_preferences.py b/photoshop/api/_preferences.py index c4d57356..b017f488 100644 --- a/photoshop/api/_preferences.py +++ b/photoshop/api/_preferences.py @@ -1,36 +1,67 @@ # Import built-in modules +from os import PathLike from pathlib import Path # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.enumerations import ( + ColorPicker, + EditLogItemsType, + FontPreviewType, + FontSize, + GridLineStyle, + GridSize, + GuideLineStyle, + OtherPaintingCursors, + PaintingCursors, + PointType, + QueryStateType, + ResampleMethod, + SaveBehavior, + TypeUnits, + Units, +) class Preferences(Photoshop): """The application preference settings.""" - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) @property - def additionalPluginFolder(self): + def additionalPluginFolder(self) -> Path: """The path to an additional plug-in folder.""" return Path(self.app.additionalPluginFolder) + @additionalPluginFolder.setter + def additionalPluginFolder(self, value: str | PathLike[str]) -> None: + """The path to an additional plug-in folder.""" + self.app.additionalPluginFolder = str(value) + @property - def appendExtension(self): - return self.app.appendExtension + def appendExtension(self) -> SaveBehavior: + return SaveBehavior(self.app.appendExtension) + + @appendExtension.setter + def appendExtension(self, value: SaveBehavior) -> None: + self.app.appendExtension = value @property def askBeforeSavingLayeredTIFF(self) -> bool: return self.app.askBeforeSavingLayeredTIFF + @askBeforeSavingLayeredTIFF.setter + def askBeforeSavingLayeredTIFF(self, value: bool) -> None: + self.app.askBeforeSavingLayeredTIFF = value + @property def autoUpdateOpenDocuments(self) -> bool: """True to automatically update open documents.""" return self.app.autoUpdateOpenDocuments @autoUpdateOpenDocuments.setter - def autoUpdateOpenDocuments(self, boolean: bool): + def autoUpdateOpenDocuments(self, boolean: bool) -> None: """True to automatically update open documents.""" self.app.autoUpdateOpenDocuments = boolean @@ -40,109 +71,378 @@ def beepWhenDone(self) -> bool: return self.app.beepWhenDone @beepWhenDone.setter - def beepWhenDone(self, boolean): + def beepWhenDone(self, boolean: bool) -> None: self.app.beepWhenDone = boolean @property - def colorChannelsInColor(self): + def colorChannelsInColor(self) -> bool: """True to display component channels in the Channels palette in color.""" return self.app.colorChannelsInColor @colorChannelsInColor.setter - def colorChannelsInColor(self, value): + def colorChannelsInColor(self, value: bool) -> None: self.app.colorChannelsInColor = value @property - def colorPicker(self): + def colorPicker(self) -> ColorPicker: """The preferred color selection tool.""" - return self.app.colorPicker + return ColorPicker(self.app.colorPicker) @colorPicker.setter - def colorPicker(self, value): + def colorPicker(self, value: ColorPicker) -> None: self.app.colorPicker = value @property - def columnGutter(self): + def columnGutter(self) -> float: return self.app.columnGutter @columnGutter.setter - def columnGutter(self, value): + def columnGutter(self, value: float) -> None: self.app.columnGutter = value @property - def columnWidth(self): + def columnWidth(self) -> float: return self.app.columnWidth @columnWidth.setter - def columnWidth(self, value): + def columnWidth(self, value: float) -> None: self.app.columnWidth = value @property - def createFirstSnapshot(self): + def createFirstSnapshot(self) -> bool: """Automatically make the first snapshot when a new document is created.""" return self.app.createFirstSnapshot @createFirstSnapshot.setter - def createFirstSnapshot(self, boolean): + def createFirstSnapshot(self, boolean: bool) -> None: self.app.createFirstSnapshot = boolean @property - def dynamicColorSliders(self): + def dynamicColorSliders(self) -> bool: return self.app.dynamicColorSliders @dynamicColorSliders.setter - def dynamicColorSliders(self, boolean): + def dynamicColorSliders(self, boolean: bool) -> None: self.app.dynamicColorSliders = boolean @property - def editLogItems(self) -> bool: + def editLogItems(self) -> EditLogItemsType: """The preferred level of detail in the history log.""" - return self.app.editLogItems + return EditLogItemsType(self.app.editLogItems) @editLogItems.setter - def editLogItems(self, boolean: bool): + def editLogItems(self, value: EditLogItemsType) -> None: """The preferred level of detail in the history log. Valid only when useHistoryLog = True """ - self.app.editLogItems = boolean + self.app.editLogItems = value @property - def exportClipboard(self): + def exportClipboard(self) -> bool: """Retain Photoshop contents on the clipboard after exit the app.""" return self.app.exportClipboard @exportClipboard.setter - def exportClipboard(self, boolean: bool): + def exportClipboard(self, boolean: bool) -> None: self.app.exportClipboard = boolean @property - def fontPreviewSize(self): - return self.app.fontPreviewSize + def fontPreviewSize(self) -> FontPreviewType: + return FontPreviewType(self.app.fontPreviewSize) @fontPreviewSize.setter - def fontPreviewSize(self, value): + def fontPreviewSize(self, value: FontPreviewType) -> None: self.app.fontPreviewSize = value @property - def fullSizePreview(self): + def fullSizePreview(self) -> bool: return self.app.fullSizePreview @fullSizePreview.setter - def fullSizePreview(self, value): + def fullSizePreview(self, value: bool) -> None: self.app.fullSizePreview = value @property - def gamutWarningOpacity(self): + def gamutWarningOpacity(self) -> float: return self.app.gamutWarningOpacity + @gamutWarningOpacity.setter + def gamutWarningOpacity(self, value: float) -> None: + self.app.gamutWarningOpacity = value + + @property + def gridSize(self) -> GridSize: + return GridSize(self.app.gridSize) + + @gridSize.setter + def gridSize(self, value: GridSize) -> None: + self.app.gridSize = value + + @property + def gridStyle(self) -> GridLineStyle: + return GridLineStyle(self.app.gridStyle) + + @gridStyle.setter + def gridStyle(self, value: GridLineStyle) -> None: + self.app.gridStyle = value + + @property + def gridSubDivisions(self) -> int: + return self.app.gridSubDivisions + + @gridSubDivisions.setter + def gridSubDivisions(self, value: int) -> None: + self.app.gridSubDivisions = value + + @property + def guideStyle(self) -> GuideLineStyle: + return GuideLineStyle(self.app.guideStyle) + + @guideStyle.setter + def guideStyle(self, value: GuideLineStyle) -> None: + self.app.guideStyle = value + + @property + def iconPreview(self) -> bool: + return self.app.iconPreview + + @iconPreview.setter + def iconPreview(self, value: bool) -> None: + self.app.iconPreview = value + + @property + def imageCacheLevels(self) -> int: + return self.app.imageCacheLevels + + @imageCacheLevels.setter + def imageCacheLevels(self, value: int) -> None: + self.app.imageCacheLevels = value + + @property + def imagePreviews(self) -> SaveBehavior: + return SaveBehavior(self.app.imagePreviews) + + @imagePreviews.setter + def imagePreviews(self, value: SaveBehavior) -> None: + self.app.imagePreviews = value + + @property + def interpolation(self) -> ResampleMethod: + return ResampleMethod(self.app.interpolation) + + @interpolation.setter + def interpolation(self, value: ResampleMethod) -> None: + self.app.interpolation = value + + @property + def keyboardZoomResizesWindows(self) -> bool: + return self.app.keyboardZoomResizesWindows + + @keyboardZoomResizesWindows.setter + def keyboardZoomResizesWindows(self, value: bool) -> None: + self.app.keyboardZoomResizesWindows = value + + @property + def maximizeCompatibility(self) -> QueryStateType: + return QueryStateType(self.app.maximizeCompatibility) + + @maximizeCompatibility.setter + def maximizeCompatibility(self, value: QueryStateType) -> None: + self.app.maximizeCompatibility = value + + @property + def maxRAMuse(self) -> int: + return self.app.maxRAMuse + + @maxRAMuse.setter + def maxRAMuse(self, value: int) -> None: + self.app.maxRAMuse = value + + @property + def nonLinearHistory(self) -> bool: + return self.app.nonLinearHistory + + @nonLinearHistory.setter + def nonLinearHistory(self, value: bool) -> None: + self.app.nonLinearHistory = value + + @property + def numberofHistoryStates(self) -> int: + return self.app.numberofHistoryStates + + @numberofHistoryStates.setter + def numberofHistoryStates(self, value: int) -> None: + self.app.numberofHistoryStates = value + + @property + def otherCursors(self) -> OtherPaintingCursors: + return OtherPaintingCursors(self.app.otherCursors) + + @otherCursors.setter + def otherCursors(self, value: OtherPaintingCursors) -> None: + self.app.otherCursors = value + + @property + def paintingCursors(self) -> PaintingCursors: + return PaintingCursors(self.app.paintingCursors) + + @paintingCursors.setter + def paintingCursors(self, value: PaintingCursors) -> None: + self.app.paintingCursors = value + + @property + def pixelDoubling(self) -> bool: + return self.app.pixelDoubling + + @pixelDoubling.setter + def pixelDoubling(self, value: bool) -> None: + self.app.pixelDoubling = value + + @property + def pointSize(self) -> PointType: + return PointType(self.app.pointSize) + + @pointSize.setter + def pointSize(self, value: PointType) -> None: + self.app.pointSize = value + + @property + def recentFileListLength(self) -> int: + return self.app.recentFileListLength + + @recentFileListLength.setter + def recentFileListLength(self, value: int) -> None: + self.app.recentFileListLength = value + @property - def rulerUnits(self): - return self.app.rulerUnits + def rulerUnits(self) -> Units: + return Units(self.app.rulerUnits) @rulerUnits.setter - def rulerUnits(self, value): + def rulerUnits(self, value: Units) -> None: self.app.rulerUnits = value + + @property + def saveLogItems(self) -> Path: + return Path(self.app.saveLogItems) + + @saveLogItems.setter + def saveLogItems(self, value: str | PathLike[str]) -> None: + self.app.saveLogItems = str(value) + + @property + def savePaletteLocations(self) -> bool: + return self.app.savePaletteLocations + + @savePaletteLocations.setter + def savePaletteLocations(self, value: bool) -> None: + self.app.savePaletteLocations = value + + @property + def showAsianTextOptions(self) -> bool: + return self.app.showAsianTextOptions + + @showAsianTextOptions.setter + def showAsianTextOptions(self, value: bool) -> None: + self.app.showAsianTextOptions = value + + @property + def showEnglishFontNames(self) -> bool: + return self.app.showEnglishFontNames + + @showEnglishFontNames.setter + def showEnglishFontNames(self, value: bool) -> None: + self.app.showEnglishFontNames = value + + @property + def showSliceNumber(self) -> bool: + return self.app.showSliceNumber + + @showSliceNumber.setter + def showSliceNumber(self, value: bool) -> None: + self.app.showSliceNumber = value + + @property + def showToolTips(self) -> bool: + return self.app.showToolTips + + @showToolTips.setter + def showToolTips(self, value: bool) -> None: + self.app.showToolTips = value + + @property + def smartQuotes(self) -> bool: + return self.app.smartQuotes + + @smartQuotes.setter + def smartQuotes(self, value: bool) -> None: + self.app.smartQuotes = value + + # textFontSize doesn't seem to be accessible via the COM API + @property + def textFontSize(self) -> FontSize: + return FontSize(self.eval_javascript("app.preferences.textFontSize")) + + @textFontSize.setter + def textFontSize(self, value: FontSize) -> None: + self.eval_javascript(f"app.preferences.textFontSize = {value}") + + @property + def typeUnits(self) -> TypeUnits: + return TypeUnits(self.app.typeUnits) + + @typeUnits.setter + def typeUnits(self, value: TypeUnits) -> None: + self.app.typeUnits = value + + @property + def useAdditionalPluginFolder(self) -> bool: + return self.app.useAdditionalPluginFolder + + @useAdditionalPluginFolder.setter + def useAdditionalPluginFolder(self, value: bool) -> None: + self.app.useAdditionalPluginFolder = value + + @property + def useHistoryLog(self) -> bool: + return self.app.useHistoryLog + + @useHistoryLog.setter + def useHistoryLog(self, value: bool) -> None: + self.app.useHistoryLog = value + + @property + def useLowerCaseExtension(self) -> bool: + return self.app.useLowerCaseExtension + + @useLowerCaseExtension.setter + def useLowerCaseExtension(self, value: bool) -> None: + self.app.useLowerCaseExtension = value + + @property + def useShiftKeyForToolSwitch(self) -> bool: + return self.app.useShiftKeyForToolSwitch + + @useShiftKeyForToolSwitch.setter + def useShiftKeyForToolSwitch(self, value: bool) -> None: + self.app.useShiftKeyForToolSwitch = value + + @property + def useVideoAlpha(self) -> bool: + return self.app.useVideoAlpha + + @useVideoAlpha.setter + def useVideoAlpha(self, value: bool) -> None: + self.app.useVideoAlpha = value + + @property + def windowsThumbnail(self) -> bool: + return self.app.windowsThumbnail + + @windowsThumbnail.setter + def windowsThumbnail(self, value: bool) -> None: + self.app.windowsThumbnail = value diff --git a/photoshop/api/_selection.py b/photoshop/api/_selection.py index 63e19e14..0b75c1f0 100644 --- a/photoshop/api/_selection.py +++ b/photoshop/api/_selection.py @@ -1,9 +1,11 @@ """The selected area of the document or layer.""" -# Import local modules +from collections.abc import Sequence + +from photoshop.api._channel import Channel from photoshop.api._core import Photoshop -from photoshop.api.enumerations import ColorBlendMode -from photoshop.api.enumerations import SelectionType +from photoshop.api._document import Document +from photoshop.api.enumerations import AnchorPosition, ColorBlendMode, SelectionType, StrokeLocation from photoshop.api.solid_color import SolidColor @@ -11,7 +13,7 @@ class Selection(Photoshop): """The selected area of the document.""" - def __init__(self, parent=None): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) self._flag_as_method( "clear", @@ -32,6 +34,7 @@ def __init__(self, parent=None): "rotateBoundary", "select", "selectBorder", + "selectAll", "similar", "smooth", "store", @@ -41,44 +44,46 @@ def __init__(self, parent=None): ) @property - def bounds(self): + def bounds(self) -> tuple[float, float, float, float]: return self.app.bounds - def parent(self): - return self.app.parent + def parent(self) -> Document: + return Document(self.app.parent) @property - def solid(self): + def solid(self) -> bool: return self.app.solid - @property - def typename(self): - return self.app.typename - - def clear(self): + def clear(self) -> None: """Clears the selection and does not copy it to the clipboard.""" self.app.clear() - def contract(self, contract_by): + def contract(self, contract_by: float) -> None: """Contracts the selection.""" self.app.contract(contract_by) - def copy(self): + def copy(self, merge: bool = False) -> None: """Copies the selection to the clipboard.""" - self.app.copy() + self.app.copy(merge) - def cut(self): - """Cuts the current selection to the clipboard.""" + def cut(self) -> None: + """Clears the current selection and copies it to the clipboard.""" self.app.cut() - def select(self, *args, **kwargs): - return self.app.select(*args, **kwargs) - - def deselect(self): + def select( + self, + region: Sequence[tuple[float, float]], + selection_type: SelectionType | None = None, + feather: float = 0, + anti_alias: bool = True, + ) -> None: + self.app.select(region, selection_type, feather, anti_alias) + + def deselect(self) -> None: """Deselects the current selection.""" - return self.app.deselect() + self.app.deselect() - def expand(self, by: int): + def expand(self, by: float) -> None: """Expands the selection. Args: @@ -87,26 +92,26 @@ def expand(self, by: int): """ self.app.expand(by) - def feather(self, by: int): + def feather(self, by: float) -> None: """Feathers the edges of the selection. Args: by: The amount to feather the edge. """ - return self.app.feather(by) + self.app.feather(by) def fill( self, fill_type: SolidColor, - mode: ColorBlendMode = None, - opacity=None, - preserve_transparency=None, - ): + mode: ColorBlendMode | None = None, + opacity: float | None = None, + preserve_transparency: bool = False, + ) -> None: """Fills the selection.""" - return self.app.fill(fill_type, mode, opacity, preserve_transparency) + self.app.fill(fill_type.app, mode, opacity, preserve_transparency) - def grow(self, tolerance, anti_alias): + def grow(self, tolerance: int, anti_alias: bool) -> None: """Grows the selection to include all adjacent pixels falling within The specified tolerance range. @@ -117,38 +122,54 @@ def grow(self, tolerance, anti_alias): """ - return self.app.grow(tolerance, anti_alias) + self.app.grow(tolerance, anti_alias) - def invert(self): + def invert(self) -> None: """Inverts the selection.""" self.app.invert() - def load(self, from_channel, combination, inverting): + def load( + self, + from_channel: Channel, + combination: SelectionType | None = None, + inverting: bool = False, + ) -> None: """Loads the selection from the specified channel.""" - return self.app.load(from_channel, combination, inverting) + self.app.load(from_channel.app, combination, inverting) - def makeWorkPath(self, tolerance): + def makeWorkPath(self, tolerance: float) -> None: """Makes this selection item the workpath for this document.""" self.app.makeWorkPath(tolerance) - def resize(self, horizontal, vertical, anchor): + def resize(self, horizontal: float, vertical: float, anchor: AnchorPosition) -> None: """Resizes the selected area to the specified dimensions and anchor position.""" self.app.resize(horizontal, vertical, anchor) - def resizeBoundary(self, horizontal, vertical, anchor): + def resizeBoundary(self, horizontal: float, vertical: float, anchor: AnchorPosition) -> None: """Scales the boundary of the selection.""" self.app.resizeBoundary(horizontal, vertical, anchor) - def rotate(self, angle, anchor): + def rotate(self, angle: float, anchor: AnchorPosition) -> None: """Rotates the object.""" self.app.rotate(angle, anchor) - def rotateBoundary(self, angle, anchor): + def rotateBoundary(self, angle: float, anchor: AnchorPosition) -> None: """Rotates the boundary of the selection.""" self.app.rotateBoundary(angle, anchor) - def stroke(self, strokeColor, width, location, mode, opacity, preserveTransparency): + def selectAll(self) -> None: + self.app.selectAll() + + def stroke( + self, + strokeColor: SolidColor, + width: int, + location: StrokeLocation | None = None, + mode: ColorBlendMode | None = None, + opacity: int = 100, + preserveTransparency: bool = False, + ) -> None: """Strokes the selection. Args: @@ -161,9 +182,9 @@ def stroke(self, strokeColor, width, location, mode, opacity, preserveTransparen preserveTransparency (bool): If true, preserves transparency. """ - return self.app.stroke(strokeColor, width, location, mode, opacity, preserveTransparency) + self.app.stroke(strokeColor.app, width, location, mode, opacity, preserveTransparency) - def selectBorder(self, width): + def selectBorder(self, width: float) -> None: """Selects the selection border only (in the specified width); subsequent actions do not affect the selected area within the borders. @@ -171,24 +192,24 @@ def selectBorder(self, width): width (int): The width of the border selection. """ - return self.app.selectBorder(width) + self.app.selectBorder(width) - def similar(self, tolerance, antiAlias): - return self.app.similar(tolerance, antiAlias) + def similar(self, tolerance: int, anti_alias: bool = True) -> None: + self.app.similar(tolerance, anti_alias) - def smooth(self, radius): + def smooth(self, radius: int) -> None: """Cleans up stray pixels left inside or outside a color-based selection (within the radius specified in pixels).""" - return self.app.smooth(radius) + self.app.smooth(radius) - def store(self, into, combination=SelectionType.ReplaceSelection): + def store(self, into: Channel, combination: SelectionType = SelectionType.ReplaceSelection) -> None: """Saves the selection as a channel.""" - return self.app.store(into, combination) + self.app.store(into.app, combination) - def translate(self, deltaX, deltaY): + def translate(self, deltaX: float = 0, deltaY: float = 0) -> None: """Moves the object relative to its current position.""" - return self.app.translate(deltaX, deltaY) + self.app.translate(deltaX, deltaY) - def translateBoundary(self, deltaX, deltaY): + def translateBoundary(self, deltaX: float = 0, deltaY: float = 0) -> None: """Moves the boundary of selection relative to its current position.""" - return self.app.translateBoundary(deltaX, deltaY) + self.app.translateBoundary(deltaX, deltaY) diff --git a/photoshop/api/_text_fonts.py b/photoshop/api/_text_fonts.py index dbe43d63..4f7f008a 100644 --- a/photoshop/api/_text_fonts.py +++ b/photoshop/api/_text_fonts.py @@ -1,6 +1,7 @@ # Import built-in modules -from typing import Any -from typing import Union +from typing import Iterator +from typing import TypeVar +from typing import overload # Import third-party modules from comtypes import ArgumentError @@ -12,24 +13,27 @@ from photoshop.api.text_font import TextFont +T = TypeVar("T") + + class TextFonts(Photoshop): """An installed font.""" - def __init__(self, parent=None): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) """ MAGIC METHODS """ - def __len__(self): + def __len__(self) -> int: return self.length - def __iter__(self): + def __iter__(self) -> Iterator[TextFont]: for font in self.app: yield TextFont(font) - def __contains__(self, name: str): + def __contains__(self, name: str) -> bool: """Check if a font is installed. Lookup by font postScriptName (fastest) or name. Args: @@ -50,7 +54,7 @@ def __contains__(self, name: str): continue return False - def __getitem__(self, key: str): + def __getitem__(self, key: str) -> TextFont: """Access a given TextFont using dictionary key lookup, must provide the postScriptName. Args: @@ -69,7 +73,15 @@ def __getitem__(self, key: str): METHODS """ - def get(self, key: str, default: Any = None) -> Union[TextFont, Any]: + @overload + def get(self, key: str, default: T) -> TextFont | T: + ... + + @overload + def get(self, key: str) -> TextFont | None: + ... + + def get(self, key: str, default: T | None = None) -> TextFont | T | None: """ Accesses a given TextFont using dictionary key lookup of postScriptName, returns default if not found. @@ -86,7 +98,7 @@ def get(self, key: str, default: Any = None) -> Union[TextFont, Any]: except (KeyError, ArgumentError): return default - def getByName(self, name: str) -> TextFont: + def getByName(self, name: str) -> TextFont | None: """Gets the font by the font name. Args: @@ -100,17 +112,12 @@ def getByName(self, name: str) -> TextFont: for font in self.app: if font.name == name: return TextFont(font) - raise PhotoshopPythonAPIError('Could not find a TextFont named "{name}"') """ PROPERTIES """ @property - def _fonts(self): - return [a for a in self.app] - - @property - def length(self): + def length(self) -> int: """The number pf elements in the collection.""" - return len(self._fonts) + return len(list(self.app)) diff --git a/photoshop/api/action_descriptor.py b/photoshop/api/action_descriptor.py index 6ecd4b0b..67d197e6 100644 --- a/photoshop/api/action_descriptor.py +++ b/photoshop/api/action_descriptor.py @@ -8,16 +8,16 @@ """ # Import built-in modules -from pathlib import Path +from os import PathLike # Import local modules from photoshop.api._core import Photoshop from photoshop.api.action_list import ActionList from photoshop.api.action_reference import ActionReference -from photoshop.api.enumerations import DescValueType +from photoshop.api.base_action import BaseAction -class ActionDescriptor(Photoshop): +class ActionDescriptor(BaseAction): """A record of key-value pairs for actions, such as those included on the Adobe Photoshop Actions menu. The ActionDescriptor class is part of the Action Manager functionality. @@ -27,30 +27,11 @@ class ActionDescriptor(Photoshop): object_name = "ActionDescriptor" - def __init__(self): - super().__init__() + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(parent=parent) self._flag_as_method( - "clear", "erase", "fromStream", - "getBoolean", - "getClass", - "getData", - "getDouble", - "getEnumerationType", - "getEnumerationValue", - "getInteger", - "getKey", - "getLargeInteger", - "getList", - "getObjectType", - "getObjectValue", - "getPath", - "getReference", - "getString", - "getType", - "getUnitDoubleType", - "getUnitDoubleValue", "hasKey", "isEqual", "putBoolean", @@ -69,177 +50,77 @@ def __init__(self): "toSteadm", ) - @property - def count(self): - """The number of keys contained in the descriptor.""" - return self.app.count - - def clear(self): - """Clears the descriptor.""" - self.app.clear() - - def erase(self, key: int): + def erase(self, key: int) -> None: """Erases a key form the descriptor.""" self.app.erase(key) - def fromStream(self, value: str): - """Create a descriptor from a stream of bytes. - - for reading from disk. - - """ + def fromStream(self, value: str) -> None: + """Create a descriptor from a stream of bytes, + for reading from disk.""" self.app.fromStream(value) - def getBoolean(self, key: int) -> int: - """Gets the text_font of a key of type boolean. - - Args: - key (str): key of type boolean. - - Returns: - bool: The text_font of a key of type boolean. - - """ - return self.app.getBoolean(key) - - def getClass(self, key): - """Gets the text_font of a key of type class. - - Args: - key (str): The key of type class. - - Returns: - int: The text_font of a key of type class. - - """ - return self.app.getClass(key) - - def getData(self, key: int) -> int: - """Gets raw byte data as a string value.""" - return self.app.getData(key) - - def getDouble(self, key: int) -> float: - """Gets the value of a key of type double.""" - return self.app.getDouble(key) - - def getEnumerationType(self, index: int) -> int: - """Gets the enumeration type of a key.""" - return self.app.getEnumerationType(index) - - def getEnumerationValue(self, index: int) -> int: - """Gets the enumeration value of a key.""" - return self.app.getEnumerationValue(index) - - def getInteger(self, index: int) -> int: - """Gets the value of a key of type integer.""" - return self.app.getInteger(index) - - def getKey(self, index: int) -> int: - """Gets the ID of the key provided by index.""" - return self.app.getKey(index) - - def getLargeInteger(self, index: int) -> int: - """Gets the value of a key of type large integer.""" - return self.app.getLargeInteger(index) - - def getList(self, index: int) -> ActionList: - """Gets the value of a key of type list.""" - return ActionList(self.app.getList(index)) - - def getObjectType(self, key: int) -> int: - """Gets the class ID of an object in a key of type object.""" - return self.app.getObjectType(key) - - def getObjectValue(self, key: int) -> int: - """Get the class ID of an object in a key of type object.""" - return self.app.getObjectValue(key) - - def getPath(self, key: int) -> Path: - """Gets the value of a key of type.""" - return Path(self.app.getPath(key)) - - def getReference(self, key: int) -> ActionReference: - """Gets the value of a key of type.""" - return ActionReference(self.app.getReference(key)) - - def getString(self, key: int) -> str: - """Gets the value of a key of type.""" - return self.app.getString(key) - - def getType(self, key: int) -> DescValueType: - """Gets the type of a key.""" - return DescValueType(self.app.getType(key)) - - def getUnitDoubleType(self, key: int) -> int: - """Gets the unit type of a key of type UnitDouble.""" - return self.app.getUnitDoubleType(key) - - def getUnitDoubleValue(self, key: int) -> float: - """Gets the unit type of a key of type UnitDouble.""" - return self.app.getUnitDoubleValue(key) - def hasKey(self, key: int) -> bool: """Checks whether the descriptor contains the provided key.""" return self.app.hasKey(key) - def isEqual(self, otherDesc) -> bool: + def isEqual(self, otherDesc: "ActionDescriptor") -> bool: """Determines whether the descriptor is the same as another descriptor. Args: otherDesc (.action_descriptor.ActionDescriptor): """ - return self.app.isEqual(otherDesc) + return self.app.isEqual(otherDesc.app) - def putBoolean(self, key: int, value: bool): + def putBoolean(self, key: int, value: bool) -> None: """Sets the value for a key whose type is boolean.""" self.app.putBoolean(key, value) - def putClass(self, key: int, value: int): + def putClass(self, key: int, value: int) -> None: """Sets the value for a key whose type is class.""" self.app.putClass(key, value) - def putData(self, key: int, value: str): + def putData(self, key: int, value: str) -> None: """Puts raw byte data as a string value.""" self.app.putData(key, value) - def putDouble(self, key: int, value: float): + def putDouble(self, key: int, value: float) -> None: """Sets the value for a key whose type is double.""" self.app.putDouble(key, value) - def putEnumerated(self, key: int, enum_type: int, value: int): + def putEnumerated(self, key: int, enum_type: int, value: int) -> None: """Sets the enumeration type and value for a key.""" self.app.putEnumerated(key, enum_type, value) - def putInteger(self, key: int, value: int): + def putInteger(self, key: int, value: int) -> None: """Sets the value for a key whose type is integer.""" self.app.putInteger(key, value) - def putLargeInteger(self, key: int, value: int): + def putLargeInteger(self, key: int, value: int) -> None: """Sets the value for a key whose type is large integer.""" self.app.putLargeInteger(key, value) - def putList(self, key: int, value: ActionList): + def putList(self, key: int, value: "ActionList") -> None: """Sets the value for a key whose type is an ActionList object.""" - self.app.putList(key, value) + self.app.putList(key, value.app) - def putObject(self, key: int, class_id: int, value): + def putObject(self, key: int, class_id: int, value: "ActionDescriptor") -> None: """Sets the value for a key whose type is an object.""" - self.app.putObject(key, class_id, value) + self.app.putObject(key, class_id, value.app) - def putPath(self, key: int, value: str): + def putPath(self, key: int, value: str | PathLike[str]) -> None: """Sets the value for a key whose type is path.""" - self.app.putPath(key, value) + self.app.putPath(key, str(value)) - def putReference(self, key: int, value: ActionReference): + def putReference(self, key: int, value: ActionReference) -> None: """Sets the value for a key whose type is an object reference.""" - self.app.putReference(key, value) + self.app.putReference(key, value.app) - def putString(self, key: int, value: str): + def putString(self, key: int, value: str) -> None: """Sets the value for a key whose type is string.""" self.app.putString(key, value) - def putUnitDouble(self, key: int, unit_id: int, value: float): + def putUnitDouble(self, key: int, unit_id: int, value: float) -> None: """Sets the value for a key whose type is a unit value formatted as double.""" self.app.putUnitDouble(key, unit_id, value) diff --git a/photoshop/api/action_list.py b/photoshop/api/action_list.py index b8c1e3f8..78ae7c06 100644 --- a/photoshop/api/action_list.py +++ b/photoshop/api/action_list.py @@ -4,11 +4,23 @@ """ + +# Import built-in modules +from os import PathLike +from typing import TYPE_CHECKING + # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.action_reference import ActionReference +from photoshop.api.base_action import BaseAction + + +if TYPE_CHECKING: + # Import local modules + from photoshop.api.action_descriptor import ActionDescriptor -class ActionList(Photoshop): +class ActionList(BaseAction): """The list of commands that comprise an Action. (such as an Action created using the Actions palette in the Adobe Photoshop application). @@ -19,51 +31,79 @@ class ActionList(Photoshop): object_name = "ActionList" - def __init__(self, parent=None): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) self._flag_as_method( - "getBoolean", - "getClass", - "getData", - "getDouble", - "getEnumerationType", - "getEnumerationValue", - "getInteger", - "getLargeInteger", - "getList", - "getObjectType", + "putBoolean", + "putClass", + "putData", + "putDouble", + "putEnumerated", + "putInteger", + "putLargeInteger", + "putList", + "putObject", + "putPath", + "putReference", + "putString", + "putUnitDouble", + "toSteadm", ) - @property - def count(self): - return self.app.count + def putBoolean(self, value: bool) -> None: + """Sets the value for a key whose type is boolean.""" + self.app.putBoolean(value) + + def putClass(self, value: int) -> None: + """Sets the value for a key whose type is class.""" + self.app.putClass(value) + + def putData(self, value: str) -> None: + """Puts raw byte data as a string value.""" + self.app.putData(value) + + def putDouble(self, value: float) -> None: + """Sets the value for a key whose type is double.""" + self.app.putDouble(value) - def getBoolean(self, index): - return self.app.getBoolean(index) + def putEnumerated(self, enum_type: int, value: int) -> None: + """Sets the enumeration type and value for a key.""" + self.app.putEnumerated(enum_type, value) - def getClass(self, index): - return self.app.getClass(index) + def putInteger(self, value: int) -> None: + """Sets the value for a key whose type is integer.""" + self.app.putInteger(value) - def getData(self, index): - return self.app.getData(index) + def putLargeInteger(self, value: int) -> None: + """Sets the value for a key whose type is large integer.""" + self.app.putLargeInteger(value) - def getDouble(self, index): - return self.app.getDouble(index) + def putList(self, value: "ActionList") -> None: + """Sets the value for a key whose type is an ActionList object.""" + self.app.putList(value.app) - def getEnumerationType(self, index): - return self.app.getEnumerationType(index) + def putObject(self, class_id: int, value: "ActionDescriptor") -> None: + """Sets the value for a key whose type is an object.""" + self.app.putObject(class_id, value.app) - def getEnumerationValue(self, index): - return self.app.getEnumerationValue(index) + def putPath(self, value: str | PathLike[str]) -> None: + """Sets the value for a key whose type is path.""" + self.app.putPath(str(value)) - def getInteger(self, index): - return self.app.getInteger(index) + def putReference(self, value: ActionReference) -> None: + """Sets the value for a key whose type is an object reference.""" + self.app.putReference(value.app) - def getLargeInteger(self, index): - return self.app.getLargeInteger(index) + def putString(self, value: str) -> None: + """Sets the value for a key whose type is string.""" + self.app.putString(value) - def getList(self, index): - return self.app.getList(index) + def putUnitDouble(self, unit_id: int, value: float) -> None: + """Sets the value for a key whose type is a unit value formatted as + double.""" + self.app.putUnitDouble(unit_id, value) - def getObjectType(self, index): - return self.app.getObjectType(index) + def toStream(self) -> str: + """Gets the entire descriptor as as stream of bytes, + for writing to disk.""" + return self.app.toSteadm() diff --git a/photoshop/api/action_reference.py b/photoshop/api/action_reference.py index 2e72e3a4..f73efcd2 100644 --- a/photoshop/api/action_reference.py +++ b/photoshop/api/action_reference.py @@ -8,6 +8,7 @@ with an ActionDescriptor. """ + # Import local modules from photoshop.api._core import Photoshop from photoshop.api.enumerations import ReferenceFormType @@ -23,7 +24,7 @@ class ActionReference(Photoshop): object_name = "ActionReference" - def __init__(self, parent=None): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) self._flag_as_method( "getContainer", @@ -33,6 +34,9 @@ def __init__(self, parent=None): "getForm", "getIdentifier", "getIndex", + "getName", + "getOffset", + "getProperty", "putName", "putClass", "putEnumerated", @@ -42,10 +46,10 @@ def __init__(self, parent=None): "putProperty", ) - def getContainer(self): + def getContainer(self) -> "ActionReference": return self.app.getContainer() - def getDesiredClass(self): + def getDesiredClass(self) -> int: return self.app.getDesiredClass() def getEnumeratedType(self) -> int: @@ -67,25 +71,37 @@ def getIndex(self) -> int: """Gets the index value for a reference in a list or array,""" return self.app.getIndex() - def putName(self, key, value): - return self.app.putName(key, value) + def getName(self) -> str: + """Gets the name of a reference.""" + return self.app.getName() + + def getOffset(self) -> int: + """Gets the offset of the object's index value.""" + return self.app.getOffset() + + def getProperty(self) -> int: + """Gets the property ID value.""" + return self.app.getProperty() + + def putName(self, key: int, value: str) -> None: + self.app.putName(key, value) - def putClass(self, value): - return self.app.putClass(value) + def putClass(self, value: int) -> None: + self.app.putClass(value) - def putEnumerated(self, desired_class, enum_type, value): + def putEnumerated(self, desired_class: int, enum_type: int, value: int) -> None: """Puts an enumeration type and ID into a reference along with the desired class for the reference.""" - return self.app.putEnumerated(desired_class, enum_type, value) + self.app.putEnumerated(desired_class, enum_type, value) - def putIdentifier(self, desired_class, value): - return self.app.putIdentifier(desired_class, value) + def putIdentifier(self, desired_class: int, value: int) -> None: + self.app.putIdentifier(desired_class, value) - def putIndex(self, desired_class, value): - return self.app.putIndex(desired_class, value) + def putIndex(self, desired_class: int, value: int) -> None: + self.app.putIndex(desired_class, value) - def putOffset(self, desired_class, value): - return self.app.putOffset(desired_class, value) + def putOffset(self, desired_class: int, value: int) -> None: + self.app.putOffset(desired_class, value) - def putProperty(self, desired_class, value): - return self.app.putProperty(desired_class, value) + def putProperty(self, desired_class: int, value: int) -> None: + self.app.putProperty(desired_class, value) diff --git a/photoshop/api/application.py b/photoshop/api/application.py index 0df16cfa..3fb9ea80 100644 --- a/photoshop/api/application.py +++ b/photoshop/api/application.py @@ -10,18 +10,16 @@ app.documents.add(800, 600, 72, "docRef") """ -# Import built-in modules + import os -from pathlib import Path import time -from typing import List -from typing import Optional -from typing import Union -# Import third-party modules from _ctypes import COMError +from pathlib import Path +from typing import Any + +from comtypes.client.dynamic import _Dispatch as FullyDynamicDispatch -# Import local modules from photoshop.api._artlayer import ArtLayer from photoshop.api._core import Photoshop from photoshop.api._document import Document @@ -31,8 +29,10 @@ from photoshop.api._notifiers import Notifiers from photoshop.api._preferences import Preferences from photoshop.api._text_fonts import TextFonts -from photoshop.api.enumerations import DialogModes -from photoshop.api.enumerations import PurgeTarget +from photoshop.api.action_descriptor import ActionDescriptor +from photoshop.api.action_reference import ActionReference +from photoshop.api.batch_options import BatchOptions +from photoshop.api.enumerations import DialogModes, JavaScriptExecutionMode, PurgeTarget from photoshop.api.errors import PhotoshopPythonAPIError from photoshop.api.solid_color import SolidColor @@ -45,8 +45,8 @@ class Application(Photoshop): """ - def __init__(self, version: Optional[str] = None): - super().__init__(ps_version=version) + def __init__(self, version: str | None = None, parent: "Photoshop | FullyDynamicDispatch | None" = None) -> None: + super().__init__(ps_version=version, parent=parent) self._flag_as_method( "batch", "charIDToTypeID", @@ -91,8 +91,8 @@ def activeDocument(self) -> Document: return Document(self.app.activeDocument) @activeDocument.setter - def activeDocument(self, document: Document): - self.app.activeDocument = document + def activeDocument(self, document: Document) -> None: + self.app.activeDocument = document.app @property def backgroundColor(self) -> SolidColor: @@ -100,14 +100,14 @@ def backgroundColor(self) -> SolidColor: return SolidColor(self.app.backgroundColor) @backgroundColor.setter - def backgroundColor(self, color: SolidColor): + def backgroundColor(self, color: SolidColor) -> None: """Sets the default background color and color style for documents. Args: color: The SolidColor instance. """ - self.app.backgroundColor = color + self.app.backgroundColor = color.app @property def build(self) -> str: @@ -123,7 +123,7 @@ def colorSettings(self) -> str: return self.app.colorSettings @colorSettings.setter - def colorSettings(self, settings: str): + def colorSettings(self, settings: str) -> None: """Sets the currently selected color settings profile. Args: @@ -141,7 +141,7 @@ def currentTool(self) -> str: return self.app.currentTool @currentTool.setter - def currentTool(self, tool_name: str): + def currentTool(self, tool_name: str) -> None: """Sets the currently selected tool. Args: @@ -157,7 +157,7 @@ def displayDialogs(self) -> DialogModes: return DialogModes(self.app.displayDialogs) @displayDialogs.setter - def displayDialogs(self, dialog_mode: DialogModes): + def displayDialogs(self, dialog_mode: DialogModes) -> None: """The dialog mode for the document, which indicates whether Photoshop displays dialogs when the script runs. """ @@ -185,14 +185,14 @@ def foregroundColor(self) -> SolidColor: return SolidColor(parent=self.app.foregroundColor) @foregroundColor.setter - def foregroundColor(self, color: SolidColor): + def foregroundColor(self, color: SolidColor) -> None: """Set the `foregroundColor`. Args: color: The SolidColor instance. """ - self.app.foregroundColor = color + self.app.foregroundColor = color.app @property def freeMemory(self) -> float: @@ -205,7 +205,7 @@ def locale(self) -> str: return self.app.locale @property - def macintoshFileTypes(self) -> List[str]: + def macintoshFileTypes(self) -> tuple[str]: """A list of the image file types Photoshop can open.""" return self.app.macintoshFileTypes @@ -230,11 +230,11 @@ def notifiersEnabled(self) -> bool: return self.app.notifiersEnabled @notifiersEnabled.setter - def notifiersEnabled(self, value: bool): + def notifiersEnabled(self, value: bool) -> None: self.app.notifiersEnabled = value @property - def parent(self): + def parent(self) -> object: """The object’s container.""" return self.app.parent @@ -244,17 +244,17 @@ def path(self) -> Path: return Path(self.app.path) @property - def playbackDisplayDialogs(self): + def playbackDisplayDialogs(self) -> DialogModes: return self.doJavaScript("app.playbackDisplayDialogs") @property - def playbackParameters(self): + def playbackParameters(self) -> ActionDescriptor: """Stores and retrieves parameters used as part of a recorded action.""" return self.app.playbackParameters @playbackParameters.setter - def playbackParameters(self, value): - self.app.playbackParameters = value + def playbackParameters(self, value: ActionDescriptor) -> None: + self.app.playbackParameters = value.app @property def preferences(self) -> Preferences: @@ -265,62 +265,63 @@ def preferencesFolder(self) -> Path: return Path(self.app.preferencesFolder) @property - def recentFiles(self): - return self.app.recentFiles + def recentFiles(self) -> list[Path]: + return [Path(pth) for pth in self.app.recentFiles] @property - def scriptingBuildDate(self): + def scriptingBuildDate(self) -> str: return self.app.scriptingBuildDate @property - def scriptingVersion(self): + def scriptingVersion(self) -> str: return self.app.scriptingVersion @property - def systemInformation(self): + def systemInformation(self) -> str: return self.app.systemInformation @property - def version(self): + def version(self) -> str: return self.app.version @property - def windowsFileTypes(self): + def windowsFileTypes(self) -> tuple[str, ...]: return self.app.windowsFileTypes # Methods. - def batch(self, files, actionName, actionSet, options): + def batch( + self, + files: list[str], + actionName: str, + actionSet: str, + options: BatchOptions, + ) -> None: """Runs the batch automation routine. Similar to the **File** > **Automate** > **Batch** command. """ - self.app.batch(files, actionName, actionSet, options) + self.app.batch(files, actionName, actionSet, options.app) - def beep(self): + def beep(self) -> None: """Causes a "beep" sound.""" - return self.eval_javascript("app.beep()") + self.eval_javascript("app.beep()") - def bringToFront(self): - return self.eval_javascript("app.bringToFront()") + def bringToFront(self) -> None: + self.eval_javascript("app.bringToFront()") - def changeProgressText(self, text): + def changeProgressText(self, text: str) -> None: """Changes the text that appears in the progress window.""" self.eval_javascript(f"app.changeProgressText('{text}')") - def charIDToTypeID(self, char_id): + def charIDToTypeID(self, char_id: str) -> int: return self.app.charIDToTypeID(char_id) - @staticmethod - def compareWithNumbers(first, second): - return first > second - - def doAction(self, action, action_from="Default Actions"): + def doAction(self, action: str, action_from: str = "Default Actions") -> None: """Plays the specified action from the Actions palette.""" self.app.doAction(action, action_from) - return True - def doForcedProgress(self, title, javascript): + def doForcedProgress(self, title: str, javascript: str) -> None: script = "app.doForcedProgress('{}', '{}')".format( title, javascript, @@ -329,7 +330,7 @@ def doForcedProgress(self, title, javascript): # Ensure the script execute success. time.sleep(1) - def doProgress(self, title, javascript): + def doProgress(self, title: str, javascript: str) -> None: """Performs a task with a progress bar. Other progress APIs must be called periodically to update the progress bar and allow cancelling. @@ -346,7 +347,7 @@ def doProgress(self, title, javascript): # Ensure the script execute success. time.sleep(1) - def doProgressSegmentTask(self, segmentLength, done, total, javascript): + def doProgressSegmentTask(self, segmentLength: int, done: int, total: int, javascript: str) -> None: script = "app.doProgressSegmentTask({}, {}, {}, '{}');".format( segmentLength, done, @@ -357,7 +358,7 @@ def doProgressSegmentTask(self, segmentLength, done, total, javascript): # Ensure the script execute success. time.sleep(1) - def doProgressSubTask(self, index, limit, javascript): + def doProgressSubTask(self, index: int, limit: int, javascript: str) -> None: script = "app.doProgressSubTask({}, {}, '{}');".format( index, limit, @@ -367,27 +368,34 @@ def doProgressSubTask(self, index, limit, javascript): # Ensure the script execute success. time.sleep(1) - def doProgressTask(self, index, javascript): + def doProgressTask(self, taskLength: float, javascript: str) -> None: """Sections off a portion of the unused progress bar for execution of a subtask. Returns false on cancel. """ - script = f"app.doProgressTask({index}, '{javascript}');" + script = f"app.doProgressTask({taskLength}, '{javascript}');" self.eval_javascript(script) # Ensure the script execute success. time.sleep(1) - def eraseCustomOptions(self, key): + def eraseCustomOptions(self, key: str) -> None: """Removes the specified user objects from the Photoshop registry.""" self.app.eraseCustomOptions(key) - def executeAction(self, event_id, descriptor, display_dialogs=2): - return self.app.executeAction(event_id, descriptor, display_dialogs) + def executeAction( + self, + event_id: int, + descriptor: ActionDescriptor | None = None, + display_dialogs: DialogModes = DialogModes.DisplayNoDialogs, + ) -> ActionDescriptor: + return ActionDescriptor( + self.app.executeAction(event_id, descriptor.app if descriptor else None, display_dialogs) + ) - def executeActionGet(self, reference): - return self.app.executeActionGet(reference) + def executeActionGet(self, reference: ActionReference) -> ActionDescriptor: + return ActionDescriptor(self.app.executeActionGet(reference.app)) - def featureEnabled(self, name): + def featureEnabled(self, name: str) -> bool: """Determines whether the feature specified by name is enabled. @@ -401,37 +409,42 @@ def featureEnabled(self, name): """ return self.app.featureEnabled(name) - def getCustomOptions(self, key): + def getCustomOptions(self, key: str) -> ActionDescriptor: """Retrieves user objects in the Photoshop registry for the ID with value key.""" - return self.app.getCustomOptions(key) + return ActionDescriptor(self.app.getCustomOptions(key)) def open( self, - document_file_path, - document_type: str = None, + document_file_path: str | os.PathLike[str], + document_type: str | None = None, as_smart_object: bool = False, ) -> Document: - document = self.app.open(document_file_path, document_type, as_smart_object) + document = self.app.open(str(document_file_path), document_type, as_smart_object) if not as_smart_object: return Document(document) return document - def load(self, document_file_path: Union[str, os.PathLike]) -> Document: + def load(self, document_file_path: str | os.PathLike[str]) -> Document: """Loads a supported Photoshop document.""" self.app.load(str(document_file_path)) return self.activeDocument - def doJavaScript(self, javascript, Arguments=None, ExecutionMode=None): + def doJavaScript( + self, + javascript: str, + Arguments: list[Any] | tuple[Any] | None = None, + ExecutionMode: JavaScriptExecutionMode | None = None, + ): return self.app.doJavaScript(javascript, Arguments, ExecutionMode) def isQuicktimeAvailable(self) -> bool: return self.app.isQuicktimeAvailable - def openDialog(self): - return self.app.openDialog() + def openDialog(self) -> list[Path]: + return [Path(pth) for pth in self.app.openDialog()] - def purge(self, target: PurgeTarget): + def purge(self, target: PurgeTarget) -> None: """Purges one or more caches. Args: @@ -444,50 +457,47 @@ def purge(self, target: PurgeTarget): """ self.app.purge(target) - def putCustomOptions(self, key, custom_object, persistent): - self.app.putCustomOptions(key, custom_object, persistent) + def putCustomOptions(self, key: str, custom_object: ActionDescriptor, persistent: bool) -> None: + self.app.putCustomOptions(key, custom_object.app, persistent) - def refresh(self): + def refresh(self) -> None: """Pauses the script while the application refreshes. - Ues to slow down execution and show the results to the user as the + Use to slow down execution and show the results to the user as the script runs. Use carefully; your script runs much more slowly when using this method. - """ self.app.refresh() - def refreshFonts(self): + def refreshFonts(self) -> None: """Force the font list to get refreshed.""" - return self.eval_javascript("app.refreshFonts();") + self.eval_javascript("app.refreshFonts();") - def runMenuItem(self, menu_id): + def runMenuItem(self, menu_id: int) -> None: """Run a menu item given the menu ID.""" - return self.eval_javascript( + self.eval_javascript( f"app.runMenuItem({menu_id})", ) - def showColorPicker(self): + def showColorPicker(self) -> str: """Returns false if dialog is cancelled, true otherwise.""" return self.eval_javascript("app.showColorPicker();") - def stringIDToTypeID(self, string_id): + def stringIDToTypeID(self, string_id: str) -> int: return self.app.stringIDToTypeID(string_id) - def togglePalettes(self): + def togglePalettes(self) -> None: """Toggle palette visibility.""" - return self.doJavaScript("app.togglePalettes()") - - def toolSupportsBrushes(self, tool): - return self.app.toolSupportsBrushes(tool) + self.eval_javascript("app.togglePalettes()") - def toolSupportsBrushPresets(self, tool): - return self.app.toolSupportsPresets(tool) + def toolSupportsBrushes(self, tool: str) -> bool: + result = self.eval_javascript(f'app.toolSupportsBrushes("{tool}")') + return True if result == "true" else False - @staticmethod - def system(command): - os.system(command) + def toolSupportsBrushPresets(self, tool: str) -> bool: + result = self.eval_javascript(f'app.toolSupportsPresets("{tool}")') + return True if result == "true" else False def typeIDToStringID(self, type_id: int) -> str: return self.app.typeIDToStringID(type_id) @@ -495,5 +505,5 @@ def typeIDToStringID(self, type_id: int) -> str: def typeIDToCharID(self, type_id: int) -> str: return self.app.typeIDToCharID(type_id) - def updateProgress(self, done, total): + def updateProgress(self, done: int, total: int) -> None: self.eval_javascript(f"app.updateProgress({done}, {total})") diff --git a/photoshop/api/base_action.py b/photoshop/api/base_action.py new file mode 100644 index 00000000..4aa2b201 --- /dev/null +++ b/photoshop/api/base_action.py @@ -0,0 +1,146 @@ +# Import built-in modules +from pathlib import Path +from typing import TYPE_CHECKING + +# Import local modules +from photoshop.api._core import Photoshop +from photoshop.api.action_reference import ActionReference +from photoshop.api.enumerations import DescValueType + + +if TYPE_CHECKING: + # Import local modules + from photoshop.api.action_descriptor import ActionDescriptor + from photoshop.api.action_list import ActionList + + +class BaseAction(Photoshop): + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(parent=parent) + self._flag_as_method( + "clear", + "getBoolean", + "getClass", + "getData", + "getDouble", + "getEnumerationType", + "getEnumerationValue", + "getInteger", + "getKey", + "getLargeInteger", + "getList", + "getObjectType", + "getObjectValue", + "getPath", + "getReference", + "getString", + "getType", + "getUnitDoubleType", + "getUnitDoubleValue", + ) + + @property + def count(self) -> int: + """The number of keys contained in the descriptor.""" + return self.app.count + + def clear(self) -> None: + """Clears the descriptor.""" + self.app.clear() + + def getBoolean(self, key: int) -> bool: + """Gets the text_font of a key of type boolean. + + Args: + key (str): key of type boolean. + + Returns: + bool: The text_font of a key of type boolean. + + """ + return self.app.getBoolean(key) + + def getClass(self, key: int) -> int: + """Gets the text_font of a key of type class. + + Args: + key (str): The key of type class. + + Returns: + int: The text_font of a key of type class. + + """ + return self.app.getClass(key) + + def getData(self, key: int) -> str: + """Gets raw byte data as a string value.""" + return self.app.getData(key) + + def getDouble(self, key: int) -> float: + """Gets the value of a key of type double.""" + return self.app.getDouble(key) + + def getEnumerationType(self, index: int) -> int: + """Gets the enumeration type of a key.""" + return self.app.getEnumerationType(index) + + def getEnumerationValue(self, index: int) -> int: + """Gets the enumeration value of a key.""" + return self.app.getEnumerationValue(index) + + def getInteger(self, index: int) -> int: + """Gets the value of a key of type integer.""" + return self.app.getInteger(index) + + def getKey(self, index: int) -> int: + """Gets the ID of the key provided by index.""" + return self.app.getKey(index) + + def getLargeInteger(self, index: int) -> int: + """Gets the value of a key of type large integer.""" + return self.app.getLargeInteger(index) + + def getList(self, index: int) -> "ActionList": + """Gets the value of a key of type list.""" + # Import local modules + from photoshop.api.action_list import ActionList + + return ActionList(self.app.getList(index)) + + def getObjectType(self, key: int) -> int: + """Gets the class ID of an object in a key of type object.""" + return self.app.getObjectType(key) + + def getObjectValue(self, key: int) -> "ActionDescriptor": + """Get the class ID of an object in a key of type object.""" + from .action_descriptor import ActionDescriptor + + return ActionDescriptor(self.app.getObjectValue(key)) + + def getPath(self, key: int) -> Path: + """Gets the value of a key of type File.""" + return Path(self.app.getPath(key)) + + def getReference(self, key: int) -> ActionReference: + """Gets the value of a key of type.""" + return ActionReference(self.app.getReference(key)) + + def getString(self, key: int) -> str: + """Gets the value of a key of type.""" + return self.app.getString(key) + + def getType(self, key: int) -> DescValueType: + """Gets the type of a key.""" + return DescValueType(self.app.getType(key)) + + def getUnitDoubleType(self, key: int) -> int: + """Gets the unit type of a key of type UnitDouble.""" + return self.app.getUnitDoubleType(key) + + def getUnitDoubleValue(self, key: int) -> float: + """Gets the unit type of a key of type UnitDouble.""" + return self.app.getUnitDoubleValue(key) + + def hasKey(self, key: int) -> bool: + """Checks whether the descriptor contains the provided key.""" + return self.app.hasKey(key) diff --git a/photoshop/api/batch_options.py b/photoshop/api/batch_options.py index 87156b24..b7e0fb33 100644 --- a/photoshop/api/batch_options.py +++ b/photoshop/api/batch_options.py @@ -1,49 +1,59 @@ # https://theiviaxx.github.io/photoshop-docs/Photoshop/BatchOptions.html +# Import built-in modules +from os import PathLike +from pathlib import Path +from typing import Sequence + # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.enumerations import BatchDestinationType +from photoshop.api.enumerations import FileNamingType class BatchOptions(Photoshop): object_name = "BatchOptions" - def __init__(self): - super().__init__() - @property - def destination(self): + def destination(self) -> BatchDestinationType: """The type of destination for the processed files.""" - return self.app.destination + return BatchDestinationType(self.app.destination) @destination.setter - def destination(self, value): + def destination(self, value: BatchDestinationType) -> None: self.app.destination = value @property - def destinationFolder(self): - """The folder location for the processed files. Valid only when ‘destination’ = folder.""" - return self.app.destinationFolder + def destinationFolder(self) -> Path | None: + """The folder location for the processed files. Valid only when ‘destination’ == BatchDestinationType.FOLDER.""" + destination = self.app.destinationFolder + if destination: + return Path(self.app.destinationFolder) + return None @destinationFolder.setter - def destinationFolder(self, path): - self.app.destinationFolder = path + def destinationFolder(self, path: str | PathLike[str]) -> None: + self.app.destinationFolder = str(path) @property - def errorFile(self): + def errorFile(self) -> Path | None: """The file in which to log errors encountered. To display errors on the screen and stop batch processing when errors occur, leave blank.""" - return self.app.errorFile + err_file = self.app.errorFile + if err_file: + return Path(self.app.errorFile) + return None @errorFile.setter - def errorFile(self, file_path): - self.app.errorFile = file_path + def errorFile(self, file_path: str | PathLike[str] | None) -> None: + self.app.errorFile = str(file_path) if file_path else None @property - def fileNaming(self) -> list: + def fileNaming(self) -> list[FileNamingType]: """A list of file naming options. Maximum: 6.""" - return self.app.fileNaming + return [FileNamingType(file_naming) for file_naming in self.app.fileNaming] @fileNaming.setter - def fileNaming(self, file_naming: list): + def fileNaming(self, file_naming: Sequence[FileNamingType]) -> None: self.app.fileNaming = file_naming @property @@ -52,7 +62,7 @@ def macintoshCompatible(self) -> bool: return self.app.macintoshCompatible @macintoshCompatible.setter - def macintoshCompatible(self, value: bool): + def macintoshCompatible(self, value: bool) -> None: self.app.macintoshCompatible = value @property @@ -61,7 +71,7 @@ def overrideOpen(self) -> bool: return self.app.overrideOpen @overrideOpen.setter - def overrideOpen(self, value: bool): + def overrideOpen(self, value: bool) -> None: self.app.overrideOpen = value @property @@ -70,7 +80,7 @@ def overrideSave(self) -> bool: return self.app.overrideSave @overrideSave.setter - def overrideSave(self, value: bool): + def overrideSave(self, value: bool) -> None: self.app.overrideSave = value @property @@ -79,7 +89,7 @@ def startingSerial(self) -> int: return self.app.startingSerial @startingSerial.setter - def startingSerial(self, value: int): + def startingSerial(self, value: int) -> None: self.app.startingSerial = value @property @@ -88,7 +98,7 @@ def suppressOpen(self) -> bool: return self.app.suppressOpen @suppressOpen.setter - def suppressOpen(self, value: bool): + def suppressOpen(self, value: bool) -> None: self.app.suppressOpen = value @property @@ -97,7 +107,7 @@ def suppressProfile(self) -> bool: return self.app.suppressProfile @suppressProfile.setter - def suppressProfile(self, value: bool): + def suppressProfile(self, value: bool) -> None: self.app.suppressProfile = value @property @@ -106,7 +116,7 @@ def unixCompatible(self) -> bool: return self.app.unixCompatible @unixCompatible.setter - def unixCompatible(self, value: bool): + def unixCompatible(self, value: bool) -> None: self.app.unixCompatible = value @property @@ -115,5 +125,5 @@ def windowsCompatible(self) -> bool: return self.app.windowsCompatible @windowsCompatible.setter - def windowsCompatible(self, value: bool): + def windowsCompatible(self, value: bool) -> None: self.app.windowsCompatible = value diff --git a/photoshop/api/collections.py b/photoshop/api/collections.py new file mode 100644 index 00000000..d31e2e5d --- /dev/null +++ b/photoshop/api/collections.py @@ -0,0 +1,97 @@ +# Import built-in modules +from typing import Generic +from typing import Iterator +from typing import Protocol +from typing import TypeVar + +# Import third-party modules +from comtypes import ArgumentError + +# Import local modules +from photoshop.api._core import Photoshop +from photoshop.api.errors import PhotoshopPythonAPIError + + +class _PhotoshopObject(Protocol): + def __init__(self, parent: Photoshop | None = None) -> None: + ... + + +class NamedPhotoshopObject(_PhotoshopObject, Protocol): + @property + def name(self) -> str: + ... + + +T = TypeVar("T", bound=_PhotoshopObject) +N = TypeVar("N", bound=NamedPhotoshopObject) +G = TypeVar("G", bound=int | str) + + +class BaseCollection(Photoshop, Generic[T, G]): + """A collection of Photoshop objects.""" + + def __init__(self, type: type[T], parent: Photoshop | None = None) -> None: + super().__init__(parent=parent) + self.type = type + self._flag_as_method("item") + + @property + def length(self) -> int: + return len(list(self.app)) + + def __len__(self) -> int: + return self.length + + def __getitem__(self, key: G) -> T: + try: + return self.type(self.app[key]) + except ArgumentError as exc: + raise PhotoshopPythonAPIError(f"Couldn't find an item with key '{key}' in {type(self)}") from exc + + def __iter__(self) -> Iterator[T]: + for item in self.app: + yield self.type(item) + + def item(self, index: int) -> T: + return self.type(self.app.item(index)) + + def getByIndex(self, index: int) -> T: + for idx, item in enumerate(self.app): + if idx == index: + return self.type(item) + raise IndexError(f"Index {index} is out of range in {type(self)}") + + +class CollectionWithAdd(BaseCollection[T, G]): + """Collection that has a add method that takes no arguments.""" + + def __init__(self, type: type[T], parent: Photoshop | None = None) -> None: + super().__init__(type, parent) + self._flag_as_method("add") + + def add(self) -> T: + return self.type(self.app.add()) + + +class CollectionOfNamedObjects(BaseCollection[N, G]): + """A collection of named Photoshop objects.""" + + def getByName(self, name: str) -> N | None: + """Get the first element in the collection with the provided name.""" + for item in self.app: + if item.name == name: + return self.type(item) + return None + + +class CollectionOfRemovables(BaseCollection[T, G]): + """A collection of removable Photoshop objects.""" + + def __init__(self, type: type[T], parent: Photoshop | None = None) -> None: + super().__init__(type, parent) + self._flag_as_method("removeAll") + + def removeAll(self) -> None: + """Deletes all items.""" + self.app.removeAll() diff --git a/photoshop/api/colors/cmyk.py b/photoshop/api/colors/cmyk.py index dbe260b8..585b7027 100644 --- a/photoshop/api/colors/cmyk.py +++ b/photoshop/api/colors/cmyk.py @@ -9,41 +9,41 @@ class CMYKColor(Photoshop): object_name = "CMYKColor" - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) @property - def black(self) -> int: + def black(self) -> float: """The black color value. Range: 0.0 to 100.0.""" - return round(self.app.black) + return self.app.black @black.setter - def black(self, value: int): + def black(self, value: float) -> None: self.app.black = value @property - def cyan(self) -> int: + def cyan(self) -> float: """The cyan color value. Range: 0.0 to 100.0.""" - return round(self.app.cyan) + return self.app.cyan @cyan.setter - def cyan(self, value: int): + def cyan(self, value: float) -> None: self.app.cyan = value @property - def magenta(self) -> int: + def magenta(self) -> float: """The magenta color value. Range: 0.0 to 100.0.""" - return round(self.app.magenta) + return self.app.magenta @magenta.setter - def magenta(self, value: int): + def magenta(self, value: float) -> None: self.app.magenta = value @property - def yellow(self) -> int: + def yellow(self) -> float: """The yellow color value. Range: 0.0 to 100.0.""" - return round(self.app.yellow) + return self.app.yellow @yellow.setter - def yellow(self, value: int): + def yellow(self, value: float) -> None: self.app.yellow = value diff --git a/photoshop/api/colors/gray.py b/photoshop/api/colors/gray.py index b2321a02..155a9db8 100644 --- a/photoshop/api/colors/gray.py +++ b/photoshop/api/colors/gray.py @@ -9,7 +9,7 @@ class GrayColor(Photoshop): object_name = "GrayColor" - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) @property @@ -18,6 +18,6 @@ def gray(self) -> float: return self.app.gray @gray.setter - def gray(self, value: float): + def gray(self, value: float) -> None: """The gray value.""" self.app.gray = value diff --git a/photoshop/api/colors/hsb.py b/photoshop/api/colors/hsb.py index 76ead8c8..9e28c900 100644 --- a/photoshop/api/colors/hsb.py +++ b/photoshop/api/colors/hsb.py @@ -9,30 +9,30 @@ class HSBColor(Photoshop): object_name = "HSBColor" - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) @property - def brightness(self): - return round(self.app.brightness) + def brightness(self) -> float: + return self.app.brightness @brightness.setter - def brightness(self, value): + def brightness(self, value: float) -> None: self.app.brightness = value @property - def saturation(self): - return round(self.app.saturation) + def saturation(self) -> float: + return self.app.saturation @saturation.setter - def saturation(self, value): + def saturation(self, value: float) -> None: self.app.saturation = value @property - def hue(self): + def hue(self) -> float: """The hue value. Range: 0.0 to 360.0.""" - return round(self.app.hue) + return self.app.hue @hue.setter - def hue(self, value): + def hue(self, value: float) -> None: self.app.hue = value diff --git a/photoshop/api/colors/lab.py b/photoshop/api/colors/lab.py index 282493d9..a0b1b866 100644 --- a/photoshop/api/colors/lab.py +++ b/photoshop/api/colors/lab.py @@ -7,29 +7,29 @@ class LabColor(Photoshop): object_name = "LabColor" - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) @property - def A(self): - return round(self.app.A) + def A(self) -> float: + return self.app.A @A.setter - def A(self, value): + def A(self, value: float) -> None: self.app.A = value @property - def B(self): - return round(self.app.B) + def B(self) -> float: + return self.app.B @B.setter - def B(self, value): + def B(self, value: float) -> None: self.app.B = value @property - def L(self): - return round(self.app.L) + def L(self) -> float: + return self.app.L @L.setter - def L(self, value): + def L(self, value: float) -> None: self.app.L = value diff --git a/photoshop/api/colors/rgb.py b/photoshop/api/colors/rgb.py index 2d6475bd..d1f2575f 100644 --- a/photoshop/api/colors/rgb.py +++ b/photoshop/api/colors/rgb.py @@ -7,43 +7,43 @@ class RGBColor(Photoshop): object_name = "RGBColor" - def __init__(self, parent): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) self.blue = self.app.blue self.green = self.app.green self.red = self.app.red @property - def blue(self) -> int: - return round(self.app.blue) + def blue(self) -> float: + return self.app.blue @blue.setter - def blue(self, value: int): + def blue(self, value: float) -> None: self.app.blue = value @property - def green(self) -> int: - return round(self.app.green) + def green(self) -> float: + return self.app.green @green.setter - def green(self, value: int): + def green(self, value: float) -> None: self.app.green = value @property - def red(self) -> int: - return round(self.app.red) + def red(self) -> float: + return self.app.red @red.setter - def red(self, value: int): + def red(self, value: float) -> None: self.app.red = value @property - def hexValue(self): + def hexValue(self) -> str: return self.app.hexValue @hexValue.setter - def hexValue(self, value): + def hexValue(self, value: str) -> None: self.app.hexValue = value - def __str__(self): + def __str__(self) -> str: return f"[red: {self.red}, green:{self.green}, blue:{self.blue})]" diff --git a/photoshop/api/enumerations.py b/photoshop/api/enumerations.py index f1b40a3d..7d2e5ca4 100644 --- a/photoshop/api/enumerations.py +++ b/photoshop/api/enumerations.py @@ -1,6 +1,6 @@ """constants type of enum for Photoshop.""" # Import built-in modules -from enum import IntEnum +from enum import Enum, IntEnum class LensType(IntEnum): @@ -383,6 +383,12 @@ class FontPreviewType(IntEnum): FontPreviewSmall = 1 +class FontSize(str, Enum): + Large = "FontSize.LARGE" + Medium = "FontSize.MEDIUM" + Small = "FontSize.SMALL" + + class ForcedColors(IntEnum): BlackWhite = 2 NoForced = 1 @@ -1086,7 +1092,7 @@ class Urgency(IntEnum): Two = 2 -class Wartyle(IntEnum): +class WarpStyle(IntEnum): Arc = 2 ArcLower = 3 ArcUpper = 4 @@ -1256,7 +1262,7 @@ class ZigZagType(IntEnum): "UnderlineType", "Units", "Urgency", - "Wartyle", + "WarpStyle", "WaveType", "WhiteBalanceType", "ZigZagType", diff --git a/photoshop/api/open_options/eps.py b/photoshop/api/open_options/eps.py index fee488c9..090964a3 100644 --- a/photoshop/api/open_options/eps.py +++ b/photoshop/api/open_options/eps.py @@ -1,5 +1,6 @@ # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.enumerations import OpenDocumentMode class EPSOpenOptions(Photoshop): @@ -11,37 +12,53 @@ class EPSOpenOptions(Photoshop): object_name = "EPSOpenOptions" - def __init__(self): + def __init__(self) -> None: super().__init__() @property - def antiAlias(self): + def antiAlias(self) -> bool: return self.app.antiAlias + @antiAlias.setter + def antiAlias(self, value: bool) -> None: + self.app.antiAlias = value + @property - def constrainProportions(self): + def constrainProportions(self) -> bool: return self.app.constrainProportions + @constrainProportions.setter + def constrainProportions(self, value: bool) -> None: + self.app.constrainProportions = value + @property - def height(self): + def height(self) -> float: return self.app.height + @height.setter + def height(self, value: float) -> None: + self.app.height = value + @property - def mode(self): - return self.app.mode + def mode(self) -> OpenDocumentMode: + return OpenDocumentMode(self.app.mode) + + @mode.setter + def mode(self, value: OpenDocumentMode) -> None: + self.app.mode = value @property - def resolution(self): + def resolution(self) -> float: return self.app.resolution - @property - def width(self): - return self.app.width + @resolution.setter + def resolution(self, value: float) -> None: + self.app.resolution = value @property - def embedColorProfile(self): - return self.app.embedColorProfile + def width(self) -> float: + return self.app.width - @embedColorProfile.setter - def embedColorProfile(self, boolean): - self.app.embedColorProfile = boolean + @width.setter + def width(self, value: float) -> None: + self.app.width = value diff --git a/photoshop/api/path_item.py b/photoshop/api/path_item.py new file mode 100644 index 00000000..eec6ac76 --- /dev/null +++ b/photoshop/api/path_item.py @@ -0,0 +1,103 @@ +# Import built-in modules +from typing import TYPE_CHECKING, Iterator + +# Import local modules +from photoshop.api._core import Photoshop +from photoshop.api.enumerations import ColorBlendMode, PathKind, SelectionType, ToolType +from photoshop.api.solid_color import SolidColor +from photoshop.api.sub_path_item import SubPathItem + + +if TYPE_CHECKING: + # Import local modules + from photoshop.api._document import Document + + +class PathItem(Photoshop): + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(parent=parent) + self._flag_as_method( + "deselect", + "duplicate", + "fillPath", + "makeClippingPath", + "makeSelection", + "delete", + "select", + "strokePath", + ) + + @property + def kind(self) -> PathKind: + return PathKind(self.app.kind) + + @kind.setter + def kind(self, value: PathKind) -> None: + self.app.kind = value + + @property + def name(self) -> str: + return self.app.name + + @name.setter + def name(self, value: str) -> None: + self.app.name = value + + @property + def parent(self) -> "Document": + # Import local modules + from photoshop.api._document import Document + + return Document(self.app.parent) + + @property + def subPathItems(self) -> Iterator[SubPathItem]: + for sub_path in self.app.subPathItems: + yield SubPathItem(sub_path) + + def deselect(self) -> None: + self.app.deselect() + + def duplicate(self, name: str | None = None) -> None: + name = name if name else f"Duplicate of {self.name}" + return self.app.duplicate(name) + + def fillPath( + self, + fill_color: SolidColor, + mode: ColorBlendMode | None = None, + opacity: float = 100, + preserve_transparency: bool = False, + feather: float = 0, + whole_path: bool = True, + anti_alias: bool = True, + ) -> None: + return self.app.fillPath( + fill_color.app, + mode, + opacity, + preserve_transparency, + feather, + whole_path, + anti_alias, + ) + + def makeClippingPath(self, flatness: float) -> None: + return self.app.makeClippingPath(flatness) + + def makeSelection( + self, + feather: float = 0, + anti_alias: bool = True, + operation: SelectionType | None = None, + ) -> None: + return self.app.makeSelection(feather, anti_alias, operation) + + def remove(self) -> None: + return self.app.delete() + + def select(self) -> None: + return self.app.select() + + def strokePath(self, tool: ToolType, simulate_pressure: bool = False) -> None: + return self.app.strokePath(tool, simulate_pressure) diff --git a/photoshop/api/path_items.py b/photoshop/api/path_items.py new file mode 100644 index 00000000..0f18d316 --- /dev/null +++ b/photoshop/api/path_items.py @@ -0,0 +1,29 @@ +from typing import TYPE_CHECKING, Sequence + +from photoshop.api._core import Photoshop +from photoshop.api.collections import CollectionOfNamedObjects, CollectionOfRemovables +from photoshop.api.path_item import PathItem +from photoshop.api.sub_path_info import SubPathInfo + + +if TYPE_CHECKING: + from photoshop.api._document import Document + + +class PathItems( + CollectionOfRemovables[PathItem, int | str], + CollectionOfNamedObjects[PathItem, int | str], +): + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(PathItem, parent) + self._flag_as_method("add") + + def add(self, name: str, entire_path: Sequence[SubPathInfo]) -> PathItem: + return PathItem(self.app.add(name, [item.app for item in entire_path])) + + @property + def parent(self) -> "Document": + # Import local modules + from photoshop.api._document import Document + + return Document(self.app.parent) diff --git a/photoshop/api/path_point.py b/photoshop/api/path_point.py new file mode 100644 index 00000000..9a09984d --- /dev/null +++ b/photoshop/api/path_point.py @@ -0,0 +1,39 @@ +# Import built-in modules +from typing import TYPE_CHECKING + +# Import local modules +from photoshop.api._core import Photoshop +from photoshop.api.enumerations import PointKind + + +if TYPE_CHECKING: + # Import local modules + from photoshop.api.sub_path_item import SubPathItem + + +class PathPoint(Photoshop): + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(parent=parent) + + @property + def anchor(self) -> tuple[float, float]: + return self.app.anchor + + @property + def kind(self) -> PointKind: + return PointKind(self.app.kind) + + @property + def leftDirection(self) -> tuple[float, float]: + return self.app.leftDirection + + @property + def parent(self) -> "SubPathItem": + # Import local modules + from photoshop.api.sub_path_item import SubPathItem + + return SubPathItem(self.app.parent) + + @property + def rightDirection(self) -> tuple[float, float]: + return self.app.rightDirection diff --git a/photoshop/api/path_point_info.py b/photoshop/api/path_point_info.py new file mode 100644 index 00000000..5dad6bf0 --- /dev/null +++ b/photoshop/api/path_point_info.py @@ -0,0 +1,74 @@ +# Import local modules +from photoshop.api._core import Photoshop +from photoshop.api.enumerations import PointKind + + +class PathPointInfo(Photoshop): + # The COM API somehow uses "object_name" to recognize this as an object of + # that type, which allows instantiating this object in Python and then passing + # it to COM API functions that use objects of that type. + object_name = "PathPointInfo" + + def __init__( + self, + parent: Photoshop | None = None, + anchor: tuple[float, float] | None = None, + left_direction: tuple[float, float] | None = None, + right_direction: tuple[float, float] | None = None, + kind: PointKind | None = None, + ): + super().__init__(parent=parent) + + # Each of anchor, leftDirection and rightDirection have to be set + # for the point to be valid. + if anchor: + self.anchor = anchor + + if left_direction: + self.leftDirection = left_direction + elif anchor: + self.leftDirection = anchor + + if right_direction: + self.rightDirection = right_direction + elif anchor: + self.rightDirection = anchor + + if kind: + self.kind = kind + elif left_direction or right_direction: + self.kind = PointKind.SmoothPoint + elif anchor: + self.kind = PointKind.CornerPoint + + @property + def anchor(self) -> tuple[float, float]: + return self.app.anchor + + @anchor.setter + def anchor(self, value: tuple[float, float]) -> None: + self.app.anchor = value + + @property + def kind(self) -> PointKind: + return PointKind(self.app.kind) + + @kind.setter + def kind(self, value: PointKind) -> None: + self.app.kind = value + + @property + def leftDirection(self) -> tuple[float, float]: + return self.app.leftDirection + + @leftDirection.setter + def leftDirection(self, value: tuple[float, float]) -> None: + self.app.leftDirection = value + + @property + def rightDirection(self) -> tuple[float, float]: + return self.app.rightDirection + + @rightDirection.setter + def rightDirection(self, value: tuple[float, float]) -> None: + self.app.rightDirection = value diff --git a/photoshop/api/protocols.py b/photoshop/api/protocols.py new file mode 100644 index 00000000..989b155c --- /dev/null +++ b/photoshop/api/protocols.py @@ -0,0 +1,42 @@ +# Import built-in modules +from typing import Protocol +from typing import TYPE_CHECKING + + +if TYPE_CHECKING: + # Import local modules + from photoshop.api._document import Document + + +class BaseProtocol(Protocol): + @property + def typename(self) -> str: + ... + + +class HistoryState(BaseProtocol, Protocol): + @property + def name(self) -> str: + ... + + @property + def parent(self) -> "Document": + ... + + @property + def snapshot(self) -> bool: + ... + + +class MeasurementScale(BaseProtocol, Protocol): + logicalLength: float + logicalUnits: str + pixelLength: int + + +class XMPMetadata(BaseProtocol, Protocol): + @property + def parent(self) -> "Document": + ... + + rawData: str diff --git a/photoshop/api/save_options/bmp.py b/photoshop/api/save_options/bmp.py index 8a1c1ae8..6493e00a 100644 --- a/photoshop/api/save_options/bmp.py +++ b/photoshop/api/save_options/bmp.py @@ -2,6 +2,8 @@ # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.enumerations import BMPDepthType +from photoshop.api.enumerations import OperatingSystem class BMPSaveOptions(Photoshop): @@ -9,19 +11,51 @@ class BMPSaveOptions(Photoshop): object_name = "BMPSaveOptions" - def __init__(self): + def __init__(self) -> None: super().__init__() @property - def alphaChannels(self): + def alphaChannels(self) -> bool: """State to save the alpha channels.""" return self.app.alphaChannels @alphaChannels.setter - def alphaChannels(self, value): + def alphaChannels(self, value: bool) -> None: """Sets whether to save the alpha channels or not. Args: """ self.app.alphaChannels = value + + @property + def depth(self) -> BMPDepthType: + return BMPDepthType(self.app.depth) + + @depth.setter + def depth(self, value: BMPDepthType) -> None: + self.app.depth = value + + @property + def flipRowOrder(self) -> bool: + return self.app.flipRowOrder + + @flipRowOrder.setter + def flipRowOrder(self, value: bool) -> None: + self.app.flipRowOrder = value + + @property + def osType(self) -> OperatingSystem: + return OperatingSystem(self.app.osType) + + @osType.setter + def osType(self, value: OperatingSystem) -> None: + self.app.osType = value + + @property + def rleCompression(self) -> bool: + return self.app.rleCompression + + @rleCompression.setter + def rleCompression(self, value: bool) -> None: + self.app.rleCompression = value diff --git a/photoshop/api/save_options/eps.py b/photoshop/api/save_options/eps.py index d44aefb6..ba69fa25 100644 --- a/photoshop/api/save_options/eps.py +++ b/photoshop/api/save_options/eps.py @@ -1,5 +1,7 @@ # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.enumerations import PreviewType +from photoshop.api.enumerations import SaveEncoding class EPSSaveOptions(Photoshop): @@ -11,7 +13,7 @@ class EPSSaveOptions(Photoshop): object_name = "EPSSaveOptions" - def __init__(self): + def __init__(self) -> None: super().__init__() @property @@ -20,56 +22,56 @@ def embedColorProfile(self) -> bool: return self.app.embedColorProfile @embedColorProfile.setter - def embedColorProfile(self, boolean: bool): + def embedColorProfile(self, boolean: bool) -> None: """True to embed the color profile in this document.""" self.app.embedColorProfile = boolean @property - def encoding(self): - return self.app.encoding + def encoding(self) -> SaveEncoding: + return SaveEncoding(self.app.encoding) @encoding.setter - def encoding(self, value: bool): + def encoding(self, value: SaveEncoding) -> None: self.app.encoding = value @property - def halftoneScreen(self): + def halftoneScreen(self) -> bool: return self.app.halftoneScreen @halftoneScreen.setter - def halftoneScreen(self, value: bool): + def halftoneScreen(self, value: bool) -> None: self.app.halftoneScreen = value @property - def interpolation(self): + def interpolation(self) -> bool: return self.app.interpolation @interpolation.setter - def interpolation(self, value: bool): + def interpolation(self, value: bool) -> None: self.app.interpolation = value @property - def preview(self): - return self.app.preview + def preview(self) -> PreviewType: + return PreviewType(self.app.preview) @preview.setter - def preview(self, value: bool): + def preview(self, value: PreviewType) -> None: self.app.preview = value @property - def psColorManagement(self): + def psColorManagement(self) -> bool: return self.app.psColorManagement @psColorManagement.setter - def psColorManagement(self, value: bool): + def psColorManagement(self, value: bool) -> None: self.app.psColorManagement = value @property - def transferFunction(self): + def transferFunction(self) -> bool: return self.app.transferFunction @transferFunction.setter - def transferFunction(self, value: bool): + def transferFunction(self, value: bool) -> None: self.app.transferFunction = value @property @@ -78,17 +80,17 @@ def transparentWhites(self) -> bool: return self.app.transparentWhites @transparentWhites.setter - def transparentWhites(self, value: bool): + def transparentWhites(self, value: bool) -> None: """True to display white areas as transparent""" self.app.transparentWhites = value @property - def vectorData(self): + def vectorData(self) -> bool: """True to include vector data.""" return self.app.vectorData @vectorData.setter - def vectorData(self, value: bool): + def vectorData(self, value: bool) -> None: """True to include vector data. Valid only if the document includes vector data (text). diff --git a/photoshop/api/save_options/gif.py b/photoshop/api/save_options/gif.py index df667305..3eaff8fb 100644 --- a/photoshop/api/save_options/gif.py +++ b/photoshop/api/save_options/gif.py @@ -1,5 +1,9 @@ # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.enumerations import DitherType +from photoshop.api.enumerations import ForcedColors +from photoshop.api.enumerations import MatteType +from photoshop.api.enumerations import PaletteType class GIFSaveOptions(Photoshop): @@ -7,77 +11,77 @@ class GIFSaveOptions(Photoshop): object_name = "GIFSaveOptions" - def __init__(self): + def __init__(self) -> None: super().__init__() @property - def colors(self): + def colors(self) -> int: return self.app.color @colors.setter - def colors(self, value): + def colors(self, value: int) -> None: self.app.colors = value @property - def dither(self): - return self.app.dither + def dither(self) -> DitherType: + return DitherType(self.app.dither) @dither.setter - def dither(self, value): + def dither(self, value: DitherType) -> None: self.app.dither = value @property - def ditherAmount(self): + def ditherAmount(self) -> int: return self.app.ditherAmount @ditherAmount.setter - def ditherAmount(self, value): + def ditherAmount(self, value: int) -> None: self.app.ditherAmount = value @property - def forced(self): - return self.app.forced + def forced(self) -> ForcedColors: + return ForcedColors(self.app.forced) @forced.setter - def forced(self, value): + def forced(self, value: ForcedColors) -> None: self.app.forced = value @property - def interlaced(self): + def interlaced(self) -> bool: return self.app.interlaced @interlaced.setter - def interlaced(self, value): + def interlaced(self, value: bool) -> None: self.app.interlaced = value @property - def matte(self): - return self.app.matte + def matte(self) -> MatteType: + return MatteType(self.app.matte) @matte.setter - def matte(self, value): + def matte(self, value: MatteType) -> None: self.app.matte = value @property - def palette(self): - return self.app.palette + def palette(self) -> PaletteType: + return PaletteType(self.app.palette) @palette.setter - def palette(self, value): + def palette(self, value: PaletteType) -> None: self.app.palette = value @property - def preserveExactColors(self): + def preserveExactColors(self) -> bool: return self.app.preserveExactColors @preserveExactColors.setter - def preserveExactColors(self, value): + def preserveExactColors(self, value: bool) -> None: self.app.preserveExactColors = value @property - def transparency(self): + def transparency(self) -> bool: return self.app.transparency @transparency.setter - def transparency(self, value): + def transparency(self, value: bool) -> None: self.app.transparency = value diff --git a/photoshop/api/save_options/jpg.py b/photoshop/api/save_options/jpg.py index b54a3353..c2d7d0e9 100644 --- a/photoshop/api/save_options/jpg.py +++ b/photoshop/api/save_options/jpg.py @@ -1,5 +1,6 @@ # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.enumerations import FormatOptionsType from photoshop.api.enumerations import MatteType @@ -8,51 +9,56 @@ class JPEGSaveOptions(Photoshop): object_name = "JPEGSaveOptions" - def __init__(self, quality=5, embedColorProfile=True, matte=MatteType.NoMatte): + def __init__( + self, + quality: int = 5, + embedColorProfile: bool = True, + matte: MatteType = MatteType.NoMatte, + ): super().__init__() self.quality = quality self.embedColorProfile = embedColorProfile self.matte = matte @property - def quality(self): + def quality(self) -> int: return self.app.quality @quality.setter - def quality(self, value): + def quality(self, value: int) -> None: self.app.quality = value @property - def formatOptions(self): + def formatOptions(self) -> FormatOptionsType: """The download format to use.""" - return self.app.formatOptions + return FormatOptionsType(self.app.formatOptions) @formatOptions.setter - def formatOptions(self, value): + def formatOptions(self, value: FormatOptionsType) -> None: self.app.formatOptions = value @property - def embedColorProfile(self): + def embedColorProfile(self) -> bool: return self.app.embedColorProfile @embedColorProfile.setter - def embedColorProfile(self, value): + def embedColorProfile(self, value: bool) -> None: self.app.embedColorProfile = value @property - def matte(self): + def matte(self) -> MatteType: """The color to use to fill anti-aliased edges adjacent to transparent""" - return self.app.matte + return MatteType(self.app.matte) @matte.setter - def matte(self, value): + def matte(self, value: MatteType) -> None: self.app.matte = value @property - def scans(self): + def scans(self) -> int: return self.app.scans @scans.setter - def scans(self, value): + def scans(self, value: int) -> None: self.app.scans = value diff --git a/photoshop/api/save_options/pdf.py b/photoshop/api/save_options/pdf.py index fdc4fb18..28dc772a 100644 --- a/photoshop/api/save_options/pdf.py +++ b/photoshop/api/save_options/pdf.py @@ -6,8 +6,10 @@ # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.enumerations import PDFCompatibilityType from photoshop.api.enumerations import PDFEncodingType from photoshop.api.enumerations import PDFResampleType +from photoshop.api.enumerations import PDFStandardType from photoshop.api.errors import COMError @@ -17,80 +19,129 @@ class PDFSaveOptions(Photoshop): object_name = "PDFSaveOptions" - def __init__(self, **kwargs): + def __init__( + self, + alphaChannels: bool = False, + annotations: bool = True, + colorConversion: bool = False, + convertToEightBit: bool = True, + description: str = "No description.", + destinationProfile: str | None = None, + downSample: PDFResampleType = PDFResampleType.NoResample, + downSampleSize: float | None = None, + downSampleSizeLimit: float | None = None, + embedColorProfile: bool = True, + embedThumbnail: bool = False, + encoding: PDFEncodingType = PDFEncodingType.PDFZip, + jpegQuality: int = 12, + layers: bool = False, + optimizeForWeb: bool = False, + outputCondition: str | None = None, + outputConditionID: str | None = None, + PDFCompatibility: PDFCompatibilityType | None = None, + PDFStandard: PDFStandardType | None = None, + preserveEditing: bool = False, + presetFile: str | None = None, + profileInclusionPolicy: bool | None = None, + registryName: str | None = None, + spotColors: bool | None = None, + tileSize: int | None = None, + view: bool = False, + ): super().__init__() - self.layers = False - self.jpegQuality = 12 - self.alphaChannels = False - self.embedThumbnail = True - self.view = False - self.annotations = True - self.colorConversion = False - self.convertToEightBit = True - self.description = "No description." - self.encoding_types = PDFEncodingType - self.downSample = PDFResampleType.NoResample - self.embedColorProfile = True - if kwargs: - if "encoding" in kwargs: - self.encoding = kwargs.get("encoding", self.encoding_types.PDFJPEG) - for key, value in kwargs.items(): - setattr(self, key, value) + self.alphaChannels = alphaChannels + self.annotations = annotations + self.colorConversion = colorConversion + self.convertToEightBit = convertToEightBit + self.description = description + if destinationProfile is not None: + self.destinationProfile + self.downSample = downSample + if downSampleSize is not None: + self.downSampleSize = downSampleSize + if downSampleSizeLimit is not None: + self.downSampleSizeLimit = downSampleSizeLimit + self.embedColorProfile = embedColorProfile + self.embedThumbnail = embedThumbnail + self.encoding = encoding + self.jpegQuality = jpegQuality + self.layers = layers + self.optimizeForWeb = optimizeForWeb + if outputCondition is not None: + self.outputCondition = outputCondition + if outputConditionID is not None: + self.outputConditionID = outputConditionID + if PDFCompatibility is not None: + self.PDFCompatibility = PDFCompatibility + if PDFStandard is not None: + self.PDFStandard = PDFStandard + self.preserveEditing = preserveEditing + if presetFile is not None: + self.presetFile = presetFile + if profileInclusionPolicy is not None: + self.profileInclusionPolicy = profileInclusionPolicy + if registryName is not None: + self.registryName = registryName + if spotColors is not None: + self.spotColors = spotColors + if tileSize is not None: + self.tileSize = tileSize + self.view = view @property - def alphaChannels(self): + def alphaChannels(self) -> bool: """True to save the alpha channels with the file.""" return self.app.alphaChannels @alphaChannels.setter - def alphaChannels(self, value): + def alphaChannels(self, value: bool) -> None: """True to save the alpha channels with the file.""" self.app.alphaChannels = value @property - def annotations(self): + def annotations(self) -> bool: """If true, the annotations are saved.""" return self.app.anotations @annotations.setter - def annotations(self, value): + def annotations(self, value: bool) -> None: """If true, the annotations are saved.""" self.app.annotations = value @property - def colorConversion(self): + def colorConversion(self) -> bool: """If true, converts the color profile to the destination profile.""" return self.app.colorConversion @colorConversion.setter - def colorConversion(self, value): + def colorConversion(self, value: bool) -> None: """If true, converts the color profile to the destination profile.""" self.app.colorConversion = value @property - def convertToEightBit(self): + def convertToEightBit(self) -> bool: """If true, converts a 16-bit image to 8-bit for better compatibility with other applications.""" return self.app.convertToEightBit @convertToEightBit.setter - def convertToEightBit(self, value): + def convertToEightBit(self, value: bool) -> None: """If true, converts a 16-bit image to 8-bit for better compatibility with other applications.""" self.app.convertToEightBit = value @property - def description(self): + def description(self) -> str: """Description of the save options in use.""" return self.app.description @description.setter - def description(self, text): + def description(self, text: str) -> None: """Description of the save options in use.""" self.app.description = text @property - def destinationProfile(self): + def destinationProfile(self) -> str: """Describes the final RGB or CMYK output device, such as a monitor or press standard.""" try: @@ -101,23 +152,23 @@ def destinationProfile(self): ) @destinationProfile.setter - def destinationProfile(self, value): + def destinationProfile(self, value: str) -> None: """Describes the final RGB or CMYK output device, such as a monitor or press standard.""" self.app.destinationProfile = value @property - def downSample(self): + def downSample(self) -> PDFResampleType: """The downsample method to use.""" - return self.app.downSample + return PDFResampleType(self.app.downSample) @downSample.setter - def downSample(self, value): + def downSample(self, value: PDFResampleType) -> None: """The downsample method to use.""" self.app.downSample = value @property - def downSampleSize(self): + def downSampleSize(self) -> float: """The size (in pixels per inch) to downsample images to if they exceed the value specified for down sample size limit.""" try: @@ -128,13 +179,13 @@ def downSampleSize(self): ) @downSampleSize.setter - def downSampleSize(self, value): + def downSampleSize(self, value: float) -> None: """The size (in pixels per inch) to downsample images to if they exceed the value specified for ‘down sample size limit’.""" self.app.downSampleSize = value @property - def downSampleSizeLimit(self): + def downSampleSizeLimit(self) -> float: """Limits downsampling or subsampling to images that exceed this value (in pixels per inch).""" try: @@ -145,51 +196,51 @@ def downSampleSizeLimit(self): ) @downSampleSizeLimit.setter - def downSampleSizeLimit(self, value: float): + def downSampleSizeLimit(self, value: float) -> None: """Limits downsampling or subsampling to images that exceed this value (in pixels per inch).""" self.app.downSampleSizeLimit = value @property - def embedColorProfile(self): + def embedColorProfile(self) -> bool: """If true, the color profile is embedded in the document.""" return self.app.embedColorProfile @embedColorProfile.setter - def embedColorProfile(self, value: bool): + def embedColorProfile(self, value: bool) -> None: """If true, the color profile is embedded in the document.""" self.app.embedColorProfile = value @property - def embedThumbnail(self): + def embedThumbnail(self) -> bool: """If true, includes a small preview image in Acrobat.""" return self.app.embedThumbnail @embedThumbnail.setter - def embedThumbnail(self, value: bool): + def embedThumbnail(self, value: bool) -> None: """If true, includes a small preview image in Acrobat.""" self.app.embedThumbnail = value @property - def encoding(self): + def encoding(self) -> PDFEncodingType: """The encoding method to use.""" try: - return self.app.encoding + return PDFEncodingType(self.app.encoding) except COMError: - return self.encoding_types.PDFJPEG + return PDFEncodingType.PDFJPEG @encoding.setter - def encoding(self, value: str): + def encoding(self, value: PDFEncodingType) -> None: """The encoding method to use.""" self.app.encoding = value @property - def jpegQuality(self): + def jpegQuality(self) -> int: """Get the quality of the produced image.""" return self.app.jpegQuality @jpegQuality.setter - def jpegQuality(self, quality: int): + def jpegQuality(self, quality: int) -> None: """Set the quality of the produced image. Valid only for JPEG-encoded PDF documents. Range: 0 to 12. @@ -198,39 +249,39 @@ def jpegQuality(self, quality: int): self.app.jpegQuality = quality @property - def layers(self): + def layers(self) -> bool: """If true, the layers are saved.""" return self.app.layers @layers.setter - def layers(self, value: bool): + def layers(self, value: bool) -> None: """If true, the layers are saved.""" self.app.layers = value @property - def optimizeForWeb(self): + def optimizeForWeb(self) -> bool: """If true, improves performance of PDFs on Web servers.""" return self.app.optimizeForWeb @optimizeForWeb.setter - def optimizeForWeb(self, value: bool): + def optimizeForWeb(self, value: bool) -> None: """If true, improves performance of PDFs on Web servers.""" self.app.optimizeForWeb = value @property - def outputCondition(self): + def outputCondition(self) -> str: """An optional comment field for inserting descriptions of the output condition. The text is stored in the PDF/X file.""" return self.app.outputCondition @outputCondition.setter - def outputCondition(self, value): + def outputCondition(self, value: str) -> None: """An optional comment field for inserting descriptions of the output condition. The text is stored in the PDF/X file.""" self.app.outputCondition = value @property - def outputConditionID(self): + def outputConditionID(self) -> str: """The identifier for the output condition.""" try: return self.app.outputConditionID @@ -240,12 +291,28 @@ def outputConditionID(self): ) @outputConditionID.setter - def outputConditionID(self, value): + def outputConditionID(self, value: str) -> None: """The identifier for the output condition.""" self.app.outputConditionID = value @property - def preserveEditing(self): + def PDFCompatibility(self) -> PDFCompatibilityType: + return PDFCompatibilityType(self.app.PDFCompatibility) + + @PDFCompatibility.setter + def PDFCompatibility(self, value: PDFCompatibilityType) -> None: + self.app.PDFCompatibility = value + + @property + def PDFStandard(self) -> PDFStandardType: + return PDFStandardType(self.app.PDFStandard) + + @PDFStandard.setter + def PDFStandard(self, value: PDFStandardType) -> None: + self.app.PDFStandard = value + + @property + def preserveEditing(self) -> bool: """If true, allows users to reopen the PDF in Photoshop with native Photoshop data intact.""" try: @@ -256,13 +323,13 @@ def preserveEditing(self): ) @preserveEditing.setter - def preserveEditing(self, value): + def preserveEditing(self, value: bool) -> None: """If true, allows users to reopen the PDF in Photoshop with native Photoshop data intact.""" self.app.preserveEditing = value @property - def presetFile(self): + def presetFile(self) -> str: """The preset file to use for settings; overrides other settings.""" try: return self.app.presetFile @@ -272,12 +339,12 @@ def presetFile(self): ) @presetFile.setter - def presetFile(self, file_name): + def presetFile(self, file_name: str) -> None: """The preset file to use for settings; overrides other settings.""" self.app.presetFile = file_name @property - def profileInclusionPolicy(self): + def profileInclusionPolicy(self) -> bool: """If true, shows which profiles to include.""" try: return self.app.profileInclusionPolicy @@ -287,12 +354,12 @@ def profileInclusionPolicy(self): ) @profileInclusionPolicy.setter - def profileInclusionPolicy(self, value): + def profileInclusionPolicy(self, value: bool) -> None: """If true, shows which profiles to include.""" self.app.profileInclusionPolicy = value @property - def registryName(self): + def registryName(self) -> str: """The URL where the output condition is registered.""" try: return self.app.registryName @@ -302,12 +369,12 @@ def registryName(self): ) @registryName.setter - def registryName(self, value): + def registryName(self, value: str) -> None: """The URL where the output condition is registered.""" self.app.registryName = value @property - def spotColors(self): + def spotColors(self) -> bool: """If true, the spot colors are saved.""" try: return self.app.spotColors @@ -317,12 +384,12 @@ def spotColors(self): ) @spotColors.setter - def spotColors(self, value): + def spotColors(self, value: bool) -> None: """If true, the spot colors are saved.""" self.app.spotColors = value @property - def tileSize(self): + def tileSize(self) -> int: """The compression option. Valid only when encoding is JPEG2000.""" try: return self.app.tileSize @@ -332,25 +399,25 @@ def tileSize(self): ) @tileSize.setter - def tileSize(self, value): + def tileSize(self, value: int) -> None: """The compression option. Valid only when encoding is JPEG2000.""" if self.encoding not in ( - self.encoding_types.PDFJPEG2000HIGH, - self.encoding_types.PDFJPEG2000LOSSLESS, - self.encoding_types.PDFJPEG2000MED, - self.encoding_types.PDFJPEG2000MEDLOW, - self.encoding_types.PDFJPEG2000LOW, - self.encoding_types.PDFJPEG2000MEDHIGH, + PDFEncodingType.PDFJPEG2000HIGH, + PDFEncodingType.PDFJPEG2000LOSSLESS, + PDFEncodingType.PDFJPEG2000MED, + PDFEncodingType.PDFJPEG2000MEDLOW, + PDFEncodingType.PDFJPEG2000LOW, + PDFEncodingType.PDFJPEG2000MEDHIGH, ): raise ValueError("tileSize only work in JPEG2000. Please " "change PDFSaveOptions.encoding to JPEG2000.") self.app.tileSize = value @property - def view(self): + def view(self) -> bool: """If true, opens the saved PDF in Acrobat.""" return self.app.view @view.setter - def view(self, value): + def view(self, value: bool) -> None: """If true, opens the saved PDF in Acrobat.""" self.app.view = value diff --git a/photoshop/api/save_options/png.py b/photoshop/api/save_options/png.py index acf3481a..b873f570 100644 --- a/photoshop/api/save_options/png.py +++ b/photoshop/api/save_options/png.py @@ -1,8 +1,7 @@ # Import local modules from photoshop.api._core import Photoshop -from photoshop.api.enumerations import ColorReductionType -from photoshop.api.enumerations import DitherType -from photoshop.api.enumerations import SaveDocumentType +from photoshop.api.colors.rgb import RGBColor +from photoshop.api.enumerations import ColorReductionType, DitherType, SaveDocumentType class ExportOptionsSaveForWeb(Photoshop): @@ -10,20 +9,19 @@ class ExportOptionsSaveForWeb(Photoshop): object_name = "ExportOptionsSaveForWeb" - def __init__(self): + def __init__(self) -> None: super().__init__() - self._format = SaveDocumentType.PNGSave # Default to PNG self.PNG8 = False # Sets it to PNG-24 bit @property def format(self) -> SaveDocumentType: """The file format to use. One of the SaveDocumentType constants.""" - return self._format + return SaveDocumentType(self.app.format) @format.setter - def format(self, value: SaveDocumentType): + def format(self, value: SaveDocumentType) -> None: """Set the file format to use.""" - self._format = value + self.app.format = value @property def PNG8(self) -> bool: @@ -31,7 +29,7 @@ def PNG8(self) -> bool: return self.app.PNG8 @PNG8.setter - def PNG8(self, value: bool): + def PNG8(self, value: bool) -> None: self.app.PNG8 = value @property @@ -40,16 +38,16 @@ def blur(self) -> float: return self.app.blur @blur.setter - def blur(self, value: float): + def blur(self, value: float) -> None: self.app.blur = value @property def colorReduction(self) -> ColorReductionType: """The color reduction algorithm.""" - return self.app.colorReduction + return ColorReductionType(self.app.colorReduction) @colorReduction.setter - def colorReduction(self, value: ColorReductionType): + def colorReduction(self, value: ColorReductionType) -> None: self.app.colorReduction = value @property @@ -58,25 +56,65 @@ def colors(self) -> int: return self.app.colors @colors.setter - def colors(self, value: int): + def colors(self, value: int) -> None: self.app.colors = value @property def dither(self) -> DitherType: """The type of dither to use.""" - return self.app.dither + return DitherType(self.app.dither) @dither.setter - def dither(self, value: DitherType): + def dither(self, value: DitherType) -> None: self.app.dither = value + @property + def ditherAmount(self) -> int: + return self.app.ditherAmount + + @ditherAmount.setter + def ditherAmount(self, value: int) -> None: + self.app.ditherAmount = value + + @property + def includeProfile(self) -> bool: + return self.app.includeProfile + + @includeProfile.setter + def includeProfile(self, value: bool) -> None: + self.app.includeProfile = value + + @property + def interlaced(self) -> bool: + return self.app.interlaced + + @interlaced.setter + def interlaced(self, value: bool) -> None: + self.app.interlaced = value + + @property + def lossy(self) -> int: + return self.app.lossy + + @lossy.setter + def lossy(self, value: int) -> None: + self.app.lossy = value + + @property + def matteColor(self) -> RGBColor: + return self.app.matteColor + + @matteColor.setter + def matteColor(self, value: RGBColor) -> None: + self.app.matteColor = value.app + @property def optimized(self) -> bool: """If true, optimization is enabled.""" return self.app.optimized @optimized.setter - def optimized(self, value: bool): + def optimized(self, value: bool) -> None: self.app.optimized = value @property @@ -85,16 +123,48 @@ def quality(self) -> int: return self.app.quality @quality.setter - def quality(self, value: int): + def quality(self, value: int) -> None: self.app.quality = value + @property + def transparency(self) -> bool: + return self.app.transparency + + @transparency.setter + def transparency(self, value: bool) -> None: + self.app.transparency = value + + @property + def transparencyAmount(self) -> int: + return self.app.transparencyAmount + + @transparencyAmount.setter + def transparencyAmount(self, value: int) -> None: + self.app.transparencyAmount = value + + @property + def transparencyDither(self) -> DitherType: + return DitherType(self.app.transparencyDither) + + @transparencyDither.setter + def transparencyDither(self, value: DitherType) -> None: + self.app.transparencyDither = value + + @property + def webSnap(self) -> int: + return self.app.webSnap + + @webSnap.setter + def webSnap(self, value: int) -> None: + self.app.webSnap = value + class PNGSaveOptions(Photoshop): """Options for saving file as PNG.""" object_name = "PNGSaveOptions" - def __init__(self, interlaced: bool = False, compression: int = 6): + def __init__(self, interlaced: bool = False, compression: int = 6) -> None: super().__init__() self.interlaced = interlaced self.compression = compression @@ -104,7 +174,7 @@ def interlaced(self) -> bool: return self.app.interlaced @interlaced.setter - def interlaced(self, value: bool): + def interlaced(self, value: bool) -> None: self.app.interlaced = value @property @@ -112,5 +182,5 @@ def compression(self) -> int: return self.app.compression @compression.setter - def compression(self, value: int): + def compression(self, value: int) -> None: self.app.compression = value diff --git a/photoshop/api/save_options/psd.py b/photoshop/api/save_options/psd.py index 2cb79233..dd90e2e8 100644 --- a/photoshop/api/save_options/psd.py +++ b/photoshop/api/save_options/psd.py @@ -7,50 +7,50 @@ class PhotoshopSaveOptions(Photoshop): object_name = "PhotoshopSaveOptions" - def __int__(self): + def __int__(self) -> None: super().__init__() @property - def alphaChannels(self): + def alphaChannels(self) -> bool: """If true, the alpha channels are saved.""" return self.app.alphaChannels() @alphaChannels.setter - def alphaChannels(self, value): + def alphaChannels(self, value: bool) -> None: self.app.alphaChannels = value @property - def annotations(self): + def annotations(self) -> bool: """If true, the annotations are saved.""" return self.app.annotations() @annotations.setter - def annotations(self, value): + def annotations(self, value: bool) -> None: self.app.annotations = value @property - def embedColorProfile(self): + def embedColorProfile(self) -> bool: """If true, the color profile is embedded in the document.""" return self.app.embedColorProfile() @embedColorProfile.setter - def embedColorProfile(self, value): + def embedColorProfile(self, value: bool) -> None: self.app.embedColorProfile = value @property - def layers(self): + def layers(self) -> bool: """If true, the layers are saved.""" return self.app.layers() @layers.setter - def layers(self, value): + def layers(self, value: bool) -> None: self.app.layers = value @property - def spotColors(self): + def spotColors(self) -> bool: """If true, spot colors are saved.""" return self.app.spotColors() @spotColors.setter - def spotColors(self, value): + def spotColors(self, value: bool) -> None: self.app.spotColors = value diff --git a/photoshop/api/save_options/tag.py b/photoshop/api/save_options/tag.py index 622170b6..16babd36 100644 --- a/photoshop/api/save_options/tag.py +++ b/photoshop/api/save_options/tag.py @@ -8,30 +8,30 @@ class TargaSaveOptions(Photoshop): object_name = "TargaSaveOptions" - def __int__(self): + def __int__(self) -> None: super().__init__() @property - def alphaChannels(self): + def alphaChannels(self) -> bool: """If true, the alpha channels are saved.""" return self.app.alphaChannels @alphaChannels.setter - def alphaChannels(self, value): + def alphaChannels(self, value: bool) -> None: self.app.alphaChannels = value @property - def resolution(self): - return self.app.resolution + def resolution(self) -> TargaBitsPerPixels: + return TargaBitsPerPixels(self.app.resolution) @resolution.setter - def resolution(self, value: TargaBitsPerPixels = TargaBitsPerPixels.Targa24Bits): + def resolution(self, value: TargaBitsPerPixels) -> None: self.app.resolution = value @property - def rleCompression(self): + def rleCompression(self) -> bool: return self.app.rleCompression @rleCompression.setter - def rleCompression(self, value): + def rleCompression(self, value: bool) -> None: self.app.rleCompression = value diff --git a/photoshop/api/save_options/tif.py b/photoshop/api/save_options/tif.py index 79f5379c..566dcf1f 100644 --- a/photoshop/api/save_options/tif.py +++ b/photoshop/api/save_options/tif.py @@ -1,5 +1,8 @@ # Import local modules from photoshop.api._core import Photoshop +from photoshop.api.enumerations import ByteOrderType +from photoshop.api.enumerations import LayerCompressionType +from photoshop.api.enumerations import TiffEncodingType class TiffSaveOptions(Photoshop): @@ -7,68 +10,68 @@ class TiffSaveOptions(Photoshop): object_name = "TiffSaveOptions" - def __int__(self): + def __int__(self) -> None: super().__init__() @property - def alphaChannels(self): + def alphaChannels(self) -> bool: """If true, the alpha channels are saved.""" return self.app.alphaChannels @alphaChannels.setter - def alphaChannels(self, value): + def alphaChannels(self, value: bool) -> None: self.app.alphaChannels = value @property - def annotations(self): + def annotations(self) -> bool: """If true, the annotations are saved.""" return self.app.annotations @annotations.setter - def annotations(self, value): + def annotations(self, value: bool) -> None: self.app.annotations = value @property - def byteOrder(self): + def byteOrder(self) -> ByteOrderType: """The order in which the bytes will be read. Default: Mac OS when running in Mac OS, and IBM PC when running in Windows. """ - return self.app.byteOrder + return ByteOrderType(self.app.byteOrder) @byteOrder.setter - def byteOrder(self, value): + def byteOrder(self, value: ByteOrderType) -> None: self.app.byteOrder = value @property - def embedColorProfile(self): + def embedColorProfile(self) -> bool: """If true, the color profile is embedded in the document.""" return self.app.embedColorProfile @embedColorProfile.setter - def embedColorProfile(self, value): + def embedColorProfile(self, value: bool) -> None: self.app.embedColorProfile = value @property - def imageCompression(self): + def imageCompression(self) -> TiffEncodingType: """The compression type.""" - return self.app.imageCompression + return TiffEncodingType(self.app.imageCompression) @imageCompression.setter - def imageCompression(self, value): + def imageCompression(self, value: TiffEncodingType) -> None: self.app.imageCompression = value @property - def interleaveChannels(self): + def interleaveChannels(self) -> bool: """If true, the channels in the image are interleaved.""" return self.app.interleaveChannels @interleaveChannels.setter - def interleaveChannels(self, value): + def interleaveChannels(self, value: bool) -> None: self.app.interleaveChannels = value @property - def jpegQuality(self): + def jpegQuality(self) -> int: """The quality of the produced image, which is inversely proportionate to the amount of JPEG compression. Valid only for JPEG compressed TIFF documents. Range: 0 to 12. @@ -76,15 +79,15 @@ def jpegQuality(self): return self.app.jpegQuality @jpegQuality.setter - def jpegQuality(self, value): + def jpegQuality(self, value: int) -> None: self.app.jpegQuality = value @property - def layerCompression(self): - return self.app.layerCompression + def layerCompression(self) -> LayerCompressionType: + return LayerCompressionType(self.app.layerCompression) @layerCompression.setter - def layerCompression(self, value): + def layerCompression(self, value: LayerCompressionType) -> None: """The method of compression to use when saving layers (as opposed to saving composite data). Valid only when `layers` = true. @@ -92,38 +95,38 @@ def layerCompression(self, value): self.app.layerCompression = value @property - def layers(self): + def layers(self) -> bool: """If true, the layers are saved.""" return self.app.layers @layers.setter - def layers(self, value): + def layers(self, value: bool) -> None: self.app.layers = value @property - def saveImagePyramid(self): + def saveImagePyramid(self) -> bool: """If true, preserves multi-resolution information.""" return self.app.saveImagePyramid @saveImagePyramid.setter - def saveImagePyramid(self, value): + def saveImagePyramid(self, value: bool) -> None: self.app.saveImagePyramid = value @property - def spotColors(self): + def spotColors(self) -> bool: """If true, spot colors are saved.""" return self.app.spotColors @spotColors.setter - def spotColors(self, value): + def spotColors(self, value: bool) -> None: self.app.spotColors = value @property - def transparency(self): + def transparency(self) -> bool: return self.app.transparency @transparency.setter - def transparency(self, value): + def transparency(self, value: bool) -> None: """If true, saves the transparency as an additional alpha channel when the file is opened in another application.""" self.app.transparency = value diff --git a/photoshop/api/solid_color.py b/photoshop/api/solid_color.py index c0ed302c..d3275907 100644 --- a/photoshop/api/solid_color.py +++ b/photoshop/api/solid_color.py @@ -23,7 +23,7 @@ class SolidColor(Photoshop): object_name = "SolidColor" - def __init__(self, parent=None): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) self._flag_as_method( "isEqual", @@ -40,28 +40,32 @@ def cmyk(self) -> CMYKColor: return CMYKColor(self.app.cmyk) @cmyk.setter - def cmyk(self, value: CMYKColor): - self.app.cmyk = value + def cmyk(self, value: CMYKColor) -> None: + self.app.cmyk = value.app @property def gray(self) -> GrayColor: return GrayColor(self.app.gray) + @gray.setter + def gray(self, value: GrayColor) -> None: + self.app.gray = value.app + @property def hsb(self) -> HSBColor: return HSBColor(self.app.hsb) @hsb.setter - def hsb(self, value: HSBColor): - self.app.hsb = value + def hsb(self, value: HSBColor) -> None: + self.app.hsb = value.app @property def lab(self) -> LabColor: return LabColor(self.app.lab) @lab.setter - def lab(self, value: LabColor): - self.app.lab = value + def lab(self, value: LabColor) -> None: + self.app.lab = value.app @property def model(self) -> ColorModel: @@ -69,7 +73,7 @@ def model(self) -> ColorModel: return ColorModel(self.app.model) @model.setter - def model(self, value: ColorModel): + def model(self, value: ColorModel) -> None: """The color model.""" self.app.model = value @@ -84,9 +88,9 @@ def rgb(self) -> RGBColor: return RGBColor(self.app.rgb) @rgb.setter - def rgb(self, value: RGBColor): - self.app.rgb = value + def rgb(self, value: RGBColor) -> None: + self.app.rgb = value.app - def isEqual(self, color: RGBColor): + def isEqual(self, color: RGBColor) -> bool: """`SolidColor` object is visually equal to the specified color.""" - return self.app.isEqual(color) + return self.app.isEqual(color.app) diff --git a/photoshop/api/sub_path_info.py b/photoshop/api/sub_path_info.py new file mode 100644 index 00000000..e2954b2f --- /dev/null +++ b/photoshop/api/sub_path_info.py @@ -0,0 +1,48 @@ +from typing import Iterator, Sequence + +from photoshop.api._core import Photoshop +from photoshop.api.enumerations import ShapeOperation +from photoshop.api.path_point_info import PathPointInfo + + +class SubPathInfo(Photoshop): + object_name = "SubPathInfo" + + def __init__( + self, + parent: Photoshop | None = None, + entire_sub_path: Sequence[PathPointInfo] | None = None, + closed: bool = True, + operation: ShapeOperation = ShapeOperation.ShapeAdd, + ): + super().__init__(parent=parent) + + if entire_sub_path: + self.entireSubPath = entire_sub_path + self.closed = closed + self.operation = operation + + @property + def closed(self) -> bool: + return self.app.closed + + @closed.setter + def closed(self, value: bool) -> None: + self.app.closed = value + + @property + def entireSubPath(self) -> Iterator[PathPointInfo]: + for point in self.app.entireSubPath: + yield PathPointInfo(point) + + @entireSubPath.setter + def entireSubPath(self, value: Sequence[PathPointInfo]) -> None: + self.app.entireSubPath = [info.app for info in value] + + @property + def operation(self) -> ShapeOperation: + return ShapeOperation(self.app.operation) + + @operation.setter + def operation(self, value: ShapeOperation) -> None: + self.app.operation = value diff --git a/photoshop/api/sub_path_item.py b/photoshop/api/sub_path_item.py new file mode 100644 index 00000000..95e62dff --- /dev/null +++ b/photoshop/api/sub_path_item.py @@ -0,0 +1,38 @@ +# Import built-in modules +from typing import Iterator +from typing import TYPE_CHECKING + +# Import local modules +from photoshop.api._core import Photoshop +from photoshop.api.enumerations import ShapeOperation +from photoshop.api.path_point import PathPoint + + +if TYPE_CHECKING: + # Import local modules + from photoshop.api.path_item import PathItem + + +class SubPathItem(Photoshop): + def __init__(self, parent: Photoshop | None = None) -> None: + super().__init__(parent=parent) + + @property + def closed(self) -> bool: + return self.app.closed + + @property + def operation(self) -> ShapeOperation: + return ShapeOperation(self.app.operation) + + @property + def parent(self) -> "PathItem": + # Import local modules + from photoshop.api.path_item import PathItem + + return PathItem(self.app.parent) + + @property + def pathPoints(self) -> Iterator[PathPoint]: + for point in self.app.pathPoints: + yield PathPoint(point) diff --git a/photoshop/api/text_font.py b/photoshop/api/text_font.py index c5e83f82..1bc81488 100644 --- a/photoshop/api/text_font.py +++ b/photoshop/api/text_font.py @@ -5,7 +5,7 @@ class TextFont(Photoshop): """An installed font.""" - def __init__(self, parent=None): + def __init__(self, parent: Photoshop | None = None) -> None: super().__init__(parent=parent) @property @@ -14,16 +14,16 @@ def family(self) -> str: return self.app.family @property - def name(self): + def name(self) -> str: """The name of the font.""" return self.app.name @property - def postScriptName(self): + def postScriptName(self) -> str: """The PostScript name of the font.""" return self.app.postScriptName @property - def style(self): + def style(self) -> str: """The font style.""" return self.app.style diff --git a/photoshop/api/text_item.py b/photoshop/api/text_item.py index 38b338d3..d60c4239 100644 --- a/photoshop/api/text_item.py +++ b/photoshop/api/text_item.py @@ -1,22 +1,32 @@ -# Import local modules +from typing import TYPE_CHECKING + from photoshop.api._core import Photoshop -from photoshop.api.enumerations import AntiAlias -from photoshop.api.enumerations import AutoKernType -from photoshop.api.enumerations import Direction -from photoshop.api.enumerations import Justification -from photoshop.api.enumerations import Language -from photoshop.api.enumerations import StrikeThruType -from photoshop.api.enumerations import TextComposer -from photoshop.api.enumerations import TextType +from photoshop.api.enumerations import ( + AntiAlias, + AutoKernType, + Case, + Direction, + Justification, + Language, + StrikeThruType, + TextComposer, + TextType, + UnderlineType, + WarpStyle, +) from photoshop.api.solid_color import SolidColor +if TYPE_CHECKING: + from photoshop.api._artlayer import ArtLayer + + class TextItem(Photoshop): """The text that is associated with the layer. Valid only when ‘kind’ is text layer.""" object_name = "Application" - def __init__(self, parent): + def __init__(self, parent: Photoshop) -> None: super().__init__(parent=parent) self._flag_as_method( "convertToShape", @@ -24,11 +34,11 @@ def __init__(self, parent): ) @property - def alternateLigatures(self): + def alternateLigatures(self) -> bool: return self.app.alternateLigatures @alternateLigatures.setter - def alternateLigatures(self, value): + def alternateLigatures(self, value: bool) -> None: self.app.alternateLigatures = value @property @@ -37,7 +47,7 @@ def antiAliasMethod(self) -> AntiAlias: return AntiAlias(self.app.antiAliasMethod) @antiAliasMethod.setter - def antiAliasMethod(self, value): + def antiAliasMethod(self, value: AntiAlias) -> None: self.app.antiAliasMethod = value @property @@ -46,15 +56,15 @@ def autoKerning(self) -> AutoKernType: return AutoKernType(self.app.autoKerning) @autoKerning.setter - def autoKerning(self, value): + def autoKerning(self, value: AutoKernType) -> None: self.app.autoKerning = value @property - def autoLeadingAmount(self): + def autoLeadingAmount(self) -> float: return self.app.autoLeadingAmount @autoLeadingAmount.setter - def autoLeadingAmount(self, value): + def autoLeadingAmount(self, value: float) -> None: """The percentage to use for auto (default) leading (in points). Valid only when useAutoLeading = True. @@ -64,21 +74,21 @@ def autoLeadingAmount(self, value): self.app.autoLeadingAmount = value @property - def baselineShift(self): + def baselineShift(self) -> float: """The unit value to use in the baseline offset of text.""" return self.app.baselineShift @baselineShift.setter - def baselineShift(self, value): + def baselineShift(self, value: float) -> None: self.app.baselineShift = value @property - def capitalization(self): + def capitalization(self) -> Case: """Gets text case.""" - return self.app.capitalization + return Case(self.app.capitalization) @capitalization.setter - def capitalization(self, value): + def capitalization(self, value: Case) -> None: """Sets text case.""" self.app.capitalization = value @@ -88,9 +98,9 @@ def color(self) -> SolidColor: return SolidColor(self.app.color) @color.setter - def color(self, color_value): + def color(self, color_value: SolidColor) -> None: """The color of textItem.""" - self.app.color = color_value + self.app.color = color_value.app @property def contents(self) -> str: @@ -98,7 +108,7 @@ def contents(self) -> str: return self.app.contents @contents.setter - def contents(self, text: str): + def contents(self, text: str) -> None: """Set the actual text in the layer. Args: @@ -108,18 +118,18 @@ def contents(self, text: str): self.app.contents = text @property - def desiredGlyphScaling(self): + def desiredGlyphScaling(self) -> float: """The desired amount by which to scale the horizontal size of the text letters. A percentage value; at 100, the width of characters is not scaled.""" return self.app.desiredGlyphScaling @desiredGlyphScaling.setter - def desiredGlyphScaling(self, value): + def desiredGlyphScaling(self, value: float) -> None: self.app.desiredGlyphScaling = value @property - def desiredLetterScaling(self): + def desiredLetterScaling(self) -> float: """The amount of space between letters . (at 0, no space is added between letters). Equivalent to Letter Spacing in the Justification @@ -135,11 +145,11 @@ def desiredLetterScaling(self): return self.app.desiredLetterScaling @desiredLetterScaling.setter - def desiredLetterScaling(self, value): + def desiredLetterScaling(self, value: float) -> None: self.app.desiredGlyphScaling = value @property - def desiredWordScaling(self): + def desiredWordScaling(self) -> float: """ The amount (percentage) of space between words (at 100, no additional space is added @@ -158,20 +168,20 @@ def desiredWordScaling(self): return self.app.desiredWordScaling @desiredWordScaling.setter - def desiredWordScaling(self, value): + def desiredWordScaling(self, value: float) -> None: self.app.desiredWordScaling = value @property - def direction(self): + def direction(self) -> Direction: """The text orientation.""" return Direction(self.app.direction) @direction.setter - def direction(self, value): + def direction(self, value: Direction) -> None: self.app.direction = value @property - def fauxBold(self): + def fauxBold(self) -> bool: """True to use faux bold (default: false). Setting this to true is equivalent to selecting text and @@ -181,11 +191,11 @@ def fauxBold(self): return self.app.fauxBold @fauxBold.setter - def fauxBold(self, value): + def fauxBold(self, value: bool) -> None: self.app.fauxBold = value @property - def fauxItalic(self): + def fauxItalic(self) -> bool: """True to use faux italic (default: false). Setting this to true is equivalent to selecting text and @@ -195,16 +205,16 @@ def fauxItalic(self): return self.app.fauxItalic @fauxItalic.setter - def fauxItalic(self, value): + def fauxItalic(self, value: bool) -> None: self.app.fauxItalic = value @property - def firstLineIndent(self): + def firstLineIndent(self) -> float: """The amount (unit value) to indent the first line of paragraphs.""" return self.app.firstLineIndent @firstLineIndent.setter - def firstLineIndent(self, value): + def firstLineIndent(self, value: float) -> None: self.app.firstLineIndent = value @property @@ -213,7 +223,7 @@ def font(self) -> str: return self.app.font @font.setter - def font(self, text_font: str): + def font(self, text_font: str) -> None: """Set the font of this TextItem. Args: @@ -227,16 +237,16 @@ def hangingPunctuation(self) -> bool: return self.app.hangingPunctuation @hangingPunctuation.setter - def hangingPunctuation(self, value: bool): + def hangingPunctuation(self, value: bool) -> None: self.app.hangingPunctuation = value @property - def height(self): + def height(self) -> float: """int: The height of the bounding box for paragraph text.""" return self.app.height @height.setter - def height(self, value): + def height(self, value: float) -> None: self.app.height = value @property @@ -245,7 +255,7 @@ def horizontalScale(self) -> int: return self.app.horizontalScale @horizontalScale.setter - def horizontalScale(self, value: int): + def horizontalScale(self, value: int) -> None: """Set the horizontalScale of this TextItem. Args: @@ -254,122 +264,122 @@ def horizontalScale(self, value: int): self.app.horizontalScale = value @property - def hyphenateAfterFirst(self): + def hyphenateAfterFirst(self) -> int: """The number of letters after which hyphenation in word wrap is allowed.""" return self.app.hyphenateAfterFirst @hyphenateAfterFirst.setter - def hyphenateAfterFirst(self, value): + def hyphenateAfterFirst(self, value: int) -> None: self.app.hyphenateAfterFirst = value @property - def hyphenateBeforeLast(self): + def hyphenateBeforeLast(self) -> int: """The number of letters before which hyphenation in word wrap is allowed.""" return self.app.hyphenateBeforeLast @hyphenateBeforeLast.setter - def hyphenateBeforeLast(self, value): + def hyphenateBeforeLast(self, value: int) -> None: self.app.hyphenateBeforeLast = value @property - def hyphenateCapitalWords(self): + def hyphenateCapitalWords(self) -> bool: """True to allow hyphenation in word wrap of capitalized words""" return self.app.hyphenateCapitalWords @hyphenateCapitalWords.setter - def hyphenateCapitalWords(self, value): + def hyphenateCapitalWords(self, value: bool) -> None: self.app.hyphenateCapitalWords = value @property - def hyphenateWordsLongerThan(self): + def hyphenateWordsLongerThan(self) -> int: """The minimum number of letters a word must have in order for hyphenation in word wrap to be allowed.""" return self.app.hyphenateWordsLongerThan @hyphenateWordsLongerThan.setter - def hyphenateWordsLongerThan(self, value): + def hyphenateWordsLongerThan(self, value: int) -> None: self.app.hyphenateWordsLongerThan = value @property - def hyphenation(self): + def hyphenation(self) -> bool: """True to use hyphenation in word wrap.""" return self.app.hyphenation @hyphenation.setter - def hyphenation(self, value): + def hyphenation(self, value: bool) -> None: self.app.hyphenation = value @property - def hyphenationZone(self): + def hyphenationZone(self) -> float: """The distance at the end of a line that will cause a word to break in unjustified type.""" return self.app.hyphenationZone @hyphenationZone.setter - def hyphenationZone(self, value): + def hyphenationZone(self, value: float) -> None: self.app.hyphenationZone = value @property - def hyphenLimit(self): + def hyphenLimit(self) -> int: return self.app.hyphenLimit @hyphenLimit.setter - def hyphenLimit(self, value): + def hyphenLimit(self, value: int) -> None: self.app.hyphenLimit = value @property - def justification(self): + def justification(self) -> Justification: """The paragraph justification.""" return Justification(self.app.justification) @justification.setter - def justification(self, value): + def justification(self, value: Justification) -> None: self.app.justification = value @property - def kind(self): + def kind(self) -> TextType: return TextType(self.app.kind) @kind.setter - def kind(self, kind_type): + def kind(self, kind_type: TextType) -> None: self.app.kind = kind_type @property - def language(self): + def language(self) -> Language: return Language(self.app.language) @language.setter - def language(self, text): + def language(self, text: Language) -> None: self.app.language = text @property - def leading(self): + def leading(self) -> float: return self.app.leading @leading.setter - def leading(self, value): + def leading(self, value: float) -> None: self.app.leading = value @property - def leftIndent(self): + def leftIndent(self) -> float: """The amoun of space to indent text from the left.""" return self.app.leftIndent @leftIndent.setter - def leftIndent(self, value): + def leftIndent(self, value: float) -> None: self.app.leftIndent = value @property - def ligatures(self): + def ligatures(self) -> bool: """True to use ligatures.""" return self.app.ligatures @ligatures.setter - def ligatures(self, value): + def ligatures(self, value: bool) -> None: self.app.ligatures = value @property - def maximumGlyphScaling(self): + def maximumGlyphScaling(self) -> float: """The maximum amount to scale the horizontal size of the text letters (a percentage value; at 100, the width of characters is not scaled). @@ -384,11 +394,11 @@ def maximumGlyphScaling(self): return self.app.maximumGlyphScaling @maximumGlyphScaling.setter - def maximumGlyphScaling(self, value): + def maximumGlyphScaling(self, value: float) -> None: self.app.maximumGlyphScaling = value @property - def maximumLetterScaling(self): + def maximumLetterScaling(self) -> float: """The maximum amount of space to allow between letters (at 0, no space is added between letters). @@ -406,19 +416,19 @@ def maximumLetterScaling(self): return self.app.maximumLetterScaling @maximumLetterScaling.setter - def maximumLetterScaling(self, value): + def maximumLetterScaling(self, value: float) -> None: self.app.maximumLetterScaling = value @property - def maximumWordScaling(self): + def maximumWordScaling(self) -> float: return self.app.maximumWordScaling @maximumWordScaling.setter - def maximumWordScaling(self, value): + def maximumWordScaling(self, value: float) -> None: self.app.maximumWordScaling = value @property - def minimumGlyphScaling(self): + def minimumGlyphScaling(self) -> float: """The minimum amount to scale the horizontal size of the text letters (a percentage value; at 100, the width of characters is not scaled). @@ -433,11 +443,11 @@ def minimumGlyphScaling(self): return self.app.minimumGlyphScaling @minimumGlyphScaling.setter - def minimumGlyphScaling(self, value): + def minimumGlyphScaling(self, value: float) -> None: self.app.minimumGlyphScaling = value @property - def minimumLetterScaling(self): + def minimumLetterScaling(self) -> float: """The minimum amount of space to allow between letters (a percentage value; at 0, no space is removed between letters). @@ -456,11 +466,11 @@ def minimumLetterScaling(self): return self.app.minimumLetterScaling @minimumLetterScaling.setter - def minimumLetterScaling(self, value): + def minimumLetterScaling(self, value: float) -> None: self.app.minimumLetterScaling = value @property - def minimumWordScaling(self): + def minimumWordScaling(self) -> float: """The minimum amount of space to allow between words (a percentage value; at 100, no additional space is removed between words). @@ -479,11 +489,11 @@ def minimumWordScaling(self): return self.app.minimumWordScaling @minimumWordScaling.setter - def minimumWordScaling(self, value): + def minimumWordScaling(self, value: float) -> None: self.app.minimumWordScaling = value @property - def noBreak(self): + def noBreak(self) -> bool: """True to disallow line breaks in this text. Tip: When true for many consecutive characters, can @@ -494,31 +504,33 @@ def noBreak(self): return self.app.noBreak @noBreak.setter - def noBreak(self, value): + def noBreak(self, value: bool) -> None: self.app.noBreak = value @property - def oldStyle(self): + def oldStyle(self) -> bool: return self.app.oldStyle @oldStyle.setter - def oldStyle(self, value): + def oldStyle(self, value: bool) -> None: self.app.oldStyle = value @property - def parent(self): - return self.app.parent + def parent(self) -> "ArtLayer": + from ._artlayer import ArtLayer + + return ArtLayer(self.app.parent) @parent.setter - def parent(self, value): - self.app.parent = value + def parent(self, value: "ArtLayer") -> None: + self.app.parent = value.app @property - def position(self): + def position(self) -> tuple[int, int]: return self.app.position @position.setter - def position(self, array): + def position(self, array: tuple[int, int]) -> None: """The position of the origin for the text. The array must contain two values. Setting this property is basically @@ -529,15 +541,15 @@ def position(self, array): self.app.position = array @property - def rightIndent(self): + def rightIndent(self) -> float: return self.app.rightIndent @rightIndent.setter - def rightIndent(self, value): + def rightIndent(self, value: float) -> None: self.app.rightIndent = value @property - def size(self): + def size(self) -> float: """The font size in UnitValue. NOTE: Type was points for CS3 and older. @@ -546,83 +558,83 @@ def size(self): return self.app.size @size.setter - def size(self, value): + def size(self, value: float) -> None: self.app.size = value @property - def spaceAfter(self): + def spaceAfter(self) -> float: """The amount of space to use after each paragraph.""" return self.app.spaceAfter @spaceAfter.setter - def spaceAfter(self, value): + def spaceAfter(self, value: float) -> None: self.app.spaceAfter = value @property - def spaceBefore(self): + def spaceBefore(self) -> float: return self.app.spaceBefore @spaceBefore.setter - def spaceBefore(self, value): + def spaceBefore(self, value: float) -> None: self.app.spaceBefore = value @property - def strikeThru(self): + def strikeThru(self) -> StrikeThruType: """The text strike-through option to use.""" return StrikeThruType(self.app.strikeThru) @strikeThru.setter - def strikeThru(self, value): + def strikeThru(self, value: StrikeThruType) -> None: self.app.strikeThru = value @property - def textComposer(self): + def textComposer(self) -> TextComposer: return TextComposer(self.app.textComposer) @textComposer.setter - def textComposer(self, value): + def textComposer(self, value: TextComposer) -> None: self.app.textComposer = value @property - def tracking(self): + def tracking(self) -> float: return self.app.tracking @tracking.setter - def tracking(self, value): + def tracking(self, value: float) -> None: self.app.tracking = value @property - def underline(self): + def underline(self) -> UnderlineType: """The text underlining options.""" - return self.app.underline + return UnderlineType(self.app.underline) @underline.setter - def underline(self, value): + def underline(self, value: UnderlineType) -> None: self.app.underline = value @property - def useAutoLeading(self): + def useAutoLeading(self) -> bool: return self.app.useAutoLeading @useAutoLeading.setter - def useAutoLeading(self, value): + def useAutoLeading(self, value: bool) -> None: self.app.useAutoLeading = value @property - def verticalScale(self): + def verticalScale(self) -> int: return self.app.verticalScale @verticalScale.setter - def verticalScale(self, value): + def verticalScale(self, value: int) -> None: self.app.verticalScale = value @property - def warpBend(self): + def warpBend(self) -> float: """The warp bend percentage.""" return self.app.warpBend @warpBend.setter - def warpBend(self, value): + def warpBend(self, value: float) -> None: self.app.warpBend = value @property @@ -631,36 +643,36 @@ def warpDirection(self) -> Direction: return Direction(self.app.warpDirection) @warpDirection.setter - def warpDirection(self, value): + def warpDirection(self, value: Direction) -> None: self.app.warpDirection = value @property - def warpHorizontalDistortion(self): + def warpHorizontalDistortion(self) -> float: return self.app.warpHorizontalDistortion @warpHorizontalDistortion.setter - def warpHorizontalDistortion(self, value): + def warpHorizontalDistortion(self, value: float) -> None: self.app.warpHorizontalDistortion = value @property - def warpStyle(self): + def warpStyle(self) -> WarpStyle: """The style of warp to use.""" - return self.app.warpStyle + return WarpStyle(self.app.warpStyle) @warpStyle.setter - def warpStyle(self, value): + def warpStyle(self, value: WarpStyle) -> None: self.app.warpStyle = value @property - def warpVerticalDistortion(self): + def warpVerticalDistortion(self) -> float: return self.app.warpVerticalDistortion @warpVerticalDistortion.setter - def warpVerticalDistortion(self, value): + def warpVerticalDistortion(self, value: float) -> None: self.app.warpVerticalDistortion = value @property - def width(self): + def width(self) -> float: """The width of the bounding box for paragraph text. @@ -670,7 +682,7 @@ def width(self): return self.app.width @width.setter - def width(self, value: float): + def width(self, value: float) -> None: """The width of the bounding box for paragraph text. @@ -679,15 +691,15 @@ def width(self, value: float): """ self.app.width = value - def convertToShape(self): + def convertToShape(self) -> None: """Converts the text item and its containing layer to a fill layer with the text changed to a clipping path.""" - return self.app.convertToShape() + self.app.convertToShape() - def createPath(self): + def createPath(self) -> None: """Creates a clipping path from the outlines of the actual text items (such as letters or words). """ - return self.app.createPath() + self.app.createPath() diff --git a/photoshop/py.typed b/photoshop/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/photoshop/session.py b/photoshop/session.py index d5976e1b..eb5f0588 100644 --- a/photoshop/session.py +++ b/photoshop/session.py @@ -27,7 +27,11 @@ """ # Import built-in modules +from contextlib import AbstractContextManager +from os import PathLike +from types import TracebackType from typing import Any +from typing import Literal # Import local modules from photoshop.api import ActionDescriptor @@ -55,10 +59,11 @@ from photoshop.api import TiffSaveOptions from photoshop.api import enumerations from photoshop.api import errors +from photoshop.api._document import Document # pylint: disable=too-many-arguments -class Session: +class Session(AbstractContextManager["Session"]): """Session of photoshop. We can control active documents in this Session. @@ -72,11 +77,11 @@ class Session: def __init__( self, - file_path: str = None, - action: str = None, + file_path: str | PathLike[str] | None = None, + action: Literal["open", "new_document", "document_duplicate"] | None = None, callback: Any = None, auto_close: bool = False, - ps_version: str = None, + ps_version: str | None = None, ): """Session of Photoshop. @@ -87,7 +92,7 @@ def __init__( from photoshop import Session with Session("your/psd/or/psb/file_path.psd", action="open") as ps: - ps.echo(ps.active_document.name) + print(ps.active_document.name) ``` Args: @@ -116,11 +121,11 @@ def __init__( """ super().__init__() - self.path = file_path + self.path: str | PathLike[str] | None = file_path self._auto_close = auto_close self._callback = callback self._action = action - self._active_document = None + self._active_document: Document | None = None self.app: Application = Application(version=ps_version) self.ActionReference: ActionReference = ActionReference() @@ -277,17 +282,17 @@ def __init__( self.UnderlineType = enumerations.UnderlineType self.Units = enumerations.Units self.Urgency = enumerations.Urgency - self.Wartyle = enumerations.Wartyle + self.WarpStyle = enumerations.WarpStyle self.WaveType = enumerations.WaveType self.WhiteBalanceType = enumerations.WhiteBalanceType self.ZigZagType = enumerations.ZigZagType @property - def active_document(self): + def active_document(self) -> Document: """Get current active document. Raises: - - PhotoshopPythonAPICOMError: No active document available. + - PhotoshopPythonAPIError: No active document available. """ try: @@ -297,12 +302,7 @@ def active_document(self): except errors.PhotoshopPythonAPICOMError: raise errors.PhotoshopPythonAPIError("No active document available.") - @staticmethod - def echo(*args, **kwargs): - """Print message.""" - print(*args, **kwargs) - - def alert(self, text: str): + def alert(self, text: str) -> None: """Alert message box in photoshop. Args: @@ -312,36 +312,44 @@ def alert(self, text: str): self.app.doJavaScript(f"alert('{text}')") @active_document.setter - def active_document(self, active_document): + def active_document(self, active_document: Document) -> None: """Set active document.""" self._active_document = active_document - def _action_open(self): - self.active_document = self.app.open(self.path) + def _action_open(self) -> None: + if self.path: + self.active_document = self.app.open(self.path) + else: + print("Specify the document's path before trying to open it.") - def _action_new_document(self): + def _action_new_document(self) -> None: self.active_document = self.app.documents.add() - def _action_document_duplicate(self): + def _action_document_duplicate(self) -> None: self.active_document = self.active_document.duplicate() - def run_action(self): + def run_action(self) -> None: try: _action = getattr(self, f"_action_{self._action}") _action() except AttributeError: pass - def close(self): + def close(self) -> None: """closing current session.""" if self._auto_close: self.active_document.close() - def __enter__(self): + def __enter__(self) -> "Session": self.run_action() return self - def __exit__(self, exc_type, exc_val, exc_tb): + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: try: if self._callback: self._callback(self) diff --git a/poetry.lock b/poetry.lock index af8ac845..3ec8e102 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. [[package]] name = "argcomplete" @@ -6,6 +6,7 @@ version = "2.0.6" description = "Bash tab completion for argparse" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "argcomplete-2.0.6-py3-none-any.whl", hash = "sha256:6c2170b3e0ab54683cb28d319b65261bde1f11388be688b68118b7d281e34c94"}, {file = "argcomplete-2.0.6.tar.gz", hash = "sha256:dc33528d96727882b576b24bc89ed038f3c6abbb6855ff9bb6be23384afff9d6"}, @@ -21,6 +22,7 @@ version = "2.15.8" description = "An abstract syntax tree for Python with inference support." optional = false python-versions = ">=3.7.2" +groups = ["dev"] files = [ {file = "astroid-2.15.8-py3-none-any.whl", hash = "sha256:1aa149fc5c6589e3d0ece885b4491acd80af4f087baafa3fb5203b113e68cd3c"}, {file = "astroid-2.15.8.tar.gz", hash = "sha256:6c107453dffee9055899705de3c9ead36e74119cee151e5a9aaf7f0b0e020a6a"}, @@ -34,64 +36,51 @@ wrapt = [ {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, ] -[[package]] -name = "astunparse" -version = "1.6.3" -description = "An AST unparser for Python" -optional = false -python-versions = "*" -files = [ - {file = "astunparse-1.6.3-py2.py3-none-any.whl", hash = "sha256:c2652417f2c8b5bb325c885ae329bdf3f86424075c4fd1a128674bc6fba4b8e8"}, - {file = "astunparse-1.6.3.tar.gz", hash = "sha256:5ad93a8456f0d084c3456d059fd9a92cce667963232cbf763eac3bc5b7940872"}, -] - -[package.dependencies] -six = ">=1.6.1,<2.0" -wheel = ">=0.23.0,<1.0" - [[package]] name = "babel" -version = "2.13.1" +version = "2.18.0" description = "Internationalization utilities" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "Babel-2.13.1-py3-none-any.whl", hash = "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed"}, - {file = "Babel-2.13.1.tar.gz", hash = "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900"}, + {file = "babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35"}, + {file = "babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d"}, ] -[package.dependencies] -pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} -setuptools = {version = "*", markers = "python_version >= \"3.12\""} - [package.extras] -dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] +dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] [[package]] name = "black" -version = "23.10.1" +version = "23.12.1" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" -files = [ - {file = "black-23.10.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:ec3f8e6234c4e46ff9e16d9ae96f4ef69fa328bb4ad08198c8cee45bb1f08c69"}, - {file = "black-23.10.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:1b917a2aa020ca600483a7b340c165970b26e9029067f019e3755b56e8dd5916"}, - {file = "black-23.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c74de4c77b849e6359c6f01987e94873c707098322b91490d24296f66d067dc"}, - {file = "black-23.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:7b4d10b0f016616a0d93d24a448100adf1699712fb7a4efd0e2c32bbb219b173"}, - {file = "black-23.10.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b15b75fc53a2fbcac8a87d3e20f69874d161beef13954747e053bca7a1ce53a0"}, - {file = "black-23.10.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:e293e4c2f4a992b980032bbd62df07c1bcff82d6964d6c9496f2cd726e246ace"}, - {file = "black-23.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d56124b7a61d092cb52cce34182a5280e160e6aff3137172a68c2c2c4b76bcb"}, - {file = "black-23.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:3f157a8945a7b2d424da3335f7ace89c14a3b0625e6593d21139c2d8214d55ce"}, - {file = "black-23.10.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:cfcce6f0a384d0da692119f2d72d79ed07c7159879d0bb1bb32d2e443382bf3a"}, - {file = "black-23.10.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:33d40f5b06be80c1bbce17b173cda17994fbad096ce60eb22054da021bf933d1"}, - {file = "black-23.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:840015166dbdfbc47992871325799fd2dc0dcf9395e401ada6d88fe11498abad"}, - {file = "black-23.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:037e9b4664cafda5f025a1728c50a9e9aedb99a759c89f760bd83730e76ba884"}, - {file = "black-23.10.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:7cb5936e686e782fddb1c73f8aa6f459e1ad38a6a7b0e54b403f1f05a1507ee9"}, - {file = "black-23.10.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:7670242e90dc129c539e9ca17665e39a146a761e681805c54fbd86015c7c84f7"}, - {file = "black-23.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed45ac9a613fb52dad3b61c8dea2ec9510bf3108d4db88422bacc7d1ba1243d"}, - {file = "black-23.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:6d23d7822140e3fef190734216cefb262521789367fbdc0b3f22af6744058982"}, - {file = "black-23.10.1-py3-none-any.whl", hash = "sha256:d431e6739f727bb2e0495df64a6c7a5310758e87505f5f8cde9ff6c0f2d7e4fe"}, - {file = "black-23.10.1.tar.gz", hash = "sha256:1f8ce316753428ff68749c65a5f7844631aa18c8679dfd3ca9dc1a289979c258"}, +groups = ["dev"] +files = [ + {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, + {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, + {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, + {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, + {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, + {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, + {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, + {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, + {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, + {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, + {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, + {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, + {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, + {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, + {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, + {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, + {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, + {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, + {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, + {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, + {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, + {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, ] [package.dependencies] @@ -105,30 +94,32 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] +d = ["aiohttp (>=3.7.4) ; sys_platform != \"win32\" or implementation_name != \"pypy\"", "aiohttp (>=3.7.4,!=3.9.0) ; sys_platform == \"win32\" and implementation_name == \"pypy\""] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2023.7.22" +version = "2026.1.4" description = "Python package for providing Mozilla's CA Bundle." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c"}, + {file = "certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120"}, ] [[package]] name = "cfgv" -version = "3.4.0" +version = "3.5.0" description = "Validate configuration and produce human readable error messages." optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, - {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, + {file = "cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0"}, + {file = "cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132"}, ] [[package]] @@ -137,6 +128,7 @@ version = "2.1.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.6.0" +groups = ["dev"] files = [ {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, @@ -147,13 +139,14 @@ unicode-backport = ["unicodedata2"] [[package]] name = "click" -version = "8.1.7" +version = "8.3.1" description = "Composable command line interface toolkit" optional = false -python-versions = ">=3.7" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, + {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, + {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, ] [package.dependencies] @@ -165,6 +158,7 @@ version = "2.1.13" description = "Hosted coverage reports for GitHub, Bitbucket and Gitlab" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] files = [ {file = "codecov-2.1.13-py2.py3-none-any.whl", hash = "sha256:c2ca5e51bba9ebb43644c43d0690148a55086f7f5e6fd36170858fa4206744d5"}, {file = "codecov-2.1.13.tar.gz", hash = "sha256:2362b685633caeaf45b9951a9b76ce359cd3581dd515b430c6c3f5dfb4d92a8c"}, @@ -180,6 +174,7 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -191,6 +186,7 @@ version = "2.42.1" description = "Python commitizen client tool" optional = false python-versions = ">=3.6.2,<4.0.0" +groups = ["dev"] files = [ {file = "commitizen-2.42.1-py3-none-any.whl", hash = "sha256:fad7d37cfae361a859b713d4ac591859d5ca03137dd52de4e1bd208f7f45d5dc"}, {file = "commitizen-2.42.1.tar.gz", hash = "sha256:eac18c7c65587061aac6829534907aeb208405b8230bfd35ec08503c228a7f17"}, @@ -211,81 +207,137 @@ typing-extensions = ">=4.0.1,<5.0.0" [[package]] name = "comtypes" -version = "1.4.10" +version = "1.4.15" description = "Pure Python COM package" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "comtypes-1.4.10-py3-none-any.whl", hash = "sha256:e078555721ee7ab40648a3363697d420b845b323e5944b55846e96aff97d2534"}, - {file = "comtypes-1.4.10.zip", hash = "sha256:b92372e76299836177b41aeda784225e18c5071c6bacdab88a7433224a4dc912"}, + {file = "comtypes-1.4.15-py3-none-any.whl", hash = "sha256:cda90486de8762ec57d7ce04e68721920911f3f03415cb29afdf7609c427c7e3"}, + {file = "comtypes-1.4.15.tar.gz", hash = "sha256:c72b9968a4e920087183a364c5a13b174e02b11c302cdd92690d14c95ac1b312"}, ] [[package]] name = "coverage" -version = "7.3.2" +version = "7.13.4" description = "Code coverage measurement for Python" optional = false -python-versions = ">=3.8" -files = [ - {file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"}, - {file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"}, - {file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"}, - {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"}, - {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"}, - {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"}, - {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"}, - {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"}, - {file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"}, - {file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"}, - {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"}, - {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"}, - {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"}, - {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"}, - {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"}, - {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"}, - {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"}, - {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"}, - {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"}, - {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"}, - {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"}, - {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"}, - {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"}, - {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"}, - {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"}, - {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"}, - {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"}, - {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"}, - {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"}, - {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"}, - {file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"}, - {file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"}, - {file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"}, - {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"}, - {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"}, - {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"}, - {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"}, - {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"}, - {file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"}, - {file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"}, - {file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"}, - {file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"}, - {file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"}, - {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"}, - {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"}, - {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"}, - {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"}, - {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"}, - {file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"}, - {file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"}, - {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"}, - {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"}, +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "coverage-7.13.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0fc31c787a84f8cd6027eba44010517020e0d18487064cd3d8968941856d1415"}, + {file = "coverage-7.13.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a32ebc02a1805adf637fc8dec324b5cdacd2e493515424f70ee33799573d661b"}, + {file = "coverage-7.13.4-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e24f9156097ff9dc286f2f913df3a7f63c0e333dcafa3c196f2c18b4175ca09a"}, + {file = "coverage-7.13.4-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8041b6c5bfdc03257666e9881d33b1abc88daccaf73f7b6340fb7946655cd10f"}, + {file = "coverage-7.13.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a09cfa6a5862bc2fc6ca7c3def5b2926194a56b8ab78ffcf617d28911123012"}, + {file = "coverage-7.13.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:296f8b0af861d3970c2a4d8c91d48eb4dd4771bcef9baedec6a9b515d7de3def"}, + {file = "coverage-7.13.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e101609bcbbfb04605ea1027b10dc3735c094d12d40826a60f897b98b1c30256"}, + {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:aa3feb8db2e87ff5e6d00d7e1480ae241876286691265657b500886c98f38bda"}, + {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4fc7fa81bbaf5a02801b65346c8b3e657f1d93763e58c0abdf7c992addd81a92"}, + {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:33901f604424145c6e9c2398684b92e176c0b12df77d52db81c20abd48c3794c"}, + {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:bb28c0f2cf2782508a40cec377935829d5fcc3ad9a3681375af4e84eb34b6b58"}, + {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9d107aff57a83222ddbd8d9ee705ede2af2cc926608b57abed8ef96b50b7e8f9"}, + {file = "coverage-7.13.4-cp310-cp310-win32.whl", hash = "sha256:a6f94a7d00eb18f1b6d403c91a88fd58cfc92d4b16080dfdb774afc8294469bf"}, + {file = "coverage-7.13.4-cp310-cp310-win_amd64.whl", hash = "sha256:2cb0f1e000ebc419632bbe04366a8990b6e32c4e0b51543a6484ffe15eaeda95"}, + {file = "coverage-7.13.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d490ba50c3f35dd7c17953c68f3270e7ccd1c6642e2d2afe2d8e720b98f5a053"}, + {file = "coverage-7.13.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:19bc3c88078789f8ef36acb014d7241961dbf883fd2533d18cb1e7a5b4e28b11"}, + {file = "coverage-7.13.4-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3998e5a32e62fdf410c0dbd3115df86297995d6e3429af80b8798aad894ca7aa"}, + {file = "coverage-7.13.4-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8e264226ec98e01a8e1054314af91ee6cde0eacac4f465cc93b03dbe0bce2fd7"}, + {file = "coverage-7.13.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a3aa4e7b9e416774b21797365b358a6e827ffadaaca81b69ee02946852449f00"}, + {file = "coverage-7.13.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:71ca20079dd8f27fcf808817e281e90220475cd75115162218d0e27549f95fef"}, + {file = "coverage-7.13.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e2f25215f1a359ab17320b47bcdaca3e6e6356652e8256f2441e4ef972052903"}, + {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d65b2d373032411e86960604dc4edac91fdfb5dca539461cf2cbe78327d1e64f"}, + {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94eb63f9b363180aff17de3e7c8760c3ba94664ea2695c52f10111244d16a299"}, + {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e856bf6616714c3a9fbc270ab54103f4e685ba236fa98c054e8f87f266c93505"}, + {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:65dfcbe305c3dfe658492df2d85259e0d79ead4177f9ae724b6fb245198f55d6"}, + {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b507778ae8a4c915436ed5c2e05b4a6cecfa70f734e19c22a005152a11c7b6a9"}, + {file = "coverage-7.13.4-cp311-cp311-win32.whl", hash = "sha256:784fc3cf8be001197b652d51d3fd259b1e2262888693a4636e18879f613a62a9"}, + {file = "coverage-7.13.4-cp311-cp311-win_amd64.whl", hash = "sha256:2421d591f8ca05b308cf0092807308b2facbefe54af7c02ac22548b88b95c98f"}, + {file = "coverage-7.13.4-cp311-cp311-win_arm64.whl", hash = "sha256:79e73a76b854d9c6088fe5d8b2ebe745f8681c55f7397c3c0a016192d681045f"}, + {file = "coverage-7.13.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:02231499b08dabbe2b96612993e5fc34217cdae907a51b906ac7fca8027a4459"}, + {file = "coverage-7.13.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40aa8808140e55dc022b15d8aa7f651b6b3d68b365ea0398f1441e0b04d859c3"}, + {file = "coverage-7.13.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5b856a8ccf749480024ff3bd7310adaef57bf31fd17e1bfc404b7940b6986634"}, + {file = "coverage-7.13.4-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2c048ea43875fbf8b45d476ad79f179809c590ec7b79e2035c662e7afa3192e3"}, + {file = "coverage-7.13.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b7b38448866e83176e28086674fe7368ab8590e4610fb662b44e345b86d63ffa"}, + {file = "coverage-7.13.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:de6defc1c9badbf8b9e67ae90fd00519186d6ab64e5cc5f3d21359c2a9b2c1d3"}, + {file = "coverage-7.13.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7eda778067ad7ffccd23ecffce537dface96212576a07924cbf0d8799d2ded5a"}, + {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e87f6c587c3f34356c3759f0420693e35e7eb0e2e41e4c011cb6ec6ecbbf1db7"}, + {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8248977c2e33aecb2ced42fef99f2d319e9904a36e55a8a68b69207fb7e43edc"}, + {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:25381386e80ae727608e662474db537d4df1ecd42379b5ba33c84633a2b36d47"}, + {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ee756f00726693e5ba94d6df2bdfd64d4852d23b09bb0bc700e3b30e6f333985"}, + {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fdfc1e28e7c7cdce44985b3043bc13bbd9c747520f94a4d7164af8260b3d91f0"}, + {file = "coverage-7.13.4-cp312-cp312-win32.whl", hash = "sha256:01d4cbc3c283a17fc1e42d614a119f7f438eabb593391283adca8dc86eff1246"}, + {file = "coverage-7.13.4-cp312-cp312-win_amd64.whl", hash = "sha256:9401ebc7ef522f01d01d45532c68c5ac40fb27113019b6b7d8b208f6e9baa126"}, + {file = "coverage-7.13.4-cp312-cp312-win_arm64.whl", hash = "sha256:b1ec7b6b6e93255f952e27ab58fbc68dcc468844b16ecbee881aeb29b6ab4d8d"}, + {file = "coverage-7.13.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b66a2da594b6068b48b2692f043f35d4d3693fb639d5ea8b39533c2ad9ac3ab9"}, + {file = "coverage-7.13.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3599eb3992d814d23b35c536c28df1a882caa950f8f507cef23d1cbf334995ac"}, + {file = "coverage-7.13.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:93550784d9281e374fb5a12bf1324cc8a963fd63b2d2f223503ef0fd4aa339ea"}, + {file = "coverage-7.13.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b720ce6a88a2755f7c697c23268ddc47a571b88052e6b155224347389fdf6a3b"}, + {file = "coverage-7.13.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b322db1284a2ed3aa28ffd8ebe3db91c929b7a333c0820abec3d838ef5b3525"}, + {file = "coverage-7.13.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4594c67d8a7c89cf922d9df0438c7c7bb022ad506eddb0fdb2863359ff78242"}, + {file = "coverage-7.13.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:53d133df809c743eb8bce33b24bcababb371f4441340578cd406e084d94a6148"}, + {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76451d1978b95ba6507a039090ba076105c87cc76fc3efd5d35d72093964d49a"}, + {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7f57b33491e281e962021de110b451ab8a24182589be17e12a22c79047935e23"}, + {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1731dc33dc276dafc410a885cbf5992f1ff171393e48a21453b78727d090de80"}, + {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:bd60d4fe2f6fa7dff9223ca1bbc9f05d2b6697bc5961072e5d3b952d46e1b1ea"}, + {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9181a3ccead280b828fae232df12b16652702b49d41e99d657f46cc7b1f6ec7a"}, + {file = "coverage-7.13.4-cp313-cp313-win32.whl", hash = "sha256:f53d492307962561ac7de4cd1de3e363589b000ab69617c6156a16ba7237998d"}, + {file = "coverage-7.13.4-cp313-cp313-win_amd64.whl", hash = "sha256:e6f70dec1cc557e52df5306d051ef56003f74d56e9c4dd7ddb07e07ef32a84dd"}, + {file = "coverage-7.13.4-cp313-cp313-win_arm64.whl", hash = "sha256:fb07dc5da7e849e2ad31a5d74e9bece81f30ecf5a42909d0a695f8bd1874d6af"}, + {file = "coverage-7.13.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:40d74da8e6c4b9ac18b15331c4b5ebc35a17069410cad462ad4f40dcd2d50c0d"}, + {file = "coverage-7.13.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4223b4230a376138939a9173f1bdd6521994f2aff8047fae100d6d94d50c5a12"}, + {file = "coverage-7.13.4-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1d4be36a5114c499f9f1f9195e95ebf979460dbe2d88e6816ea202010ba1c34b"}, + {file = "coverage-7.13.4-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:200dea7d1e8095cc6e98cdabe3fd1d21ab17d3cee6dab00cadbb2fe35d9c15b9"}, + {file = "coverage-7.13.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8eb931ee8e6d8243e253e5ed7336deea6904369d2fd8ae6e43f68abbf167092"}, + {file = "coverage-7.13.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:75eab1ebe4f2f64d9509b984f9314d4aa788540368218b858dad56dc8f3e5eb9"}, + {file = "coverage-7.13.4-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c35eb28c1d085eb7d8c9b3296567a1bebe03ce72962e932431b9a61f28facf26"}, + {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb88b316ec33760714a4720feb2816a3a59180fd58c1985012054fa7aebee4c2"}, + {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7d41eead3cc673cbd38a4417deb7fd0b4ca26954ff7dc6078e33f6ff97bed940"}, + {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:fb26a934946a6afe0e326aebe0730cdff393a8bc0bbb65a2f41e30feddca399c"}, + {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:dae88bc0fc77edaa65c14be099bd57ee140cf507e6bfdeea7938457ab387efb0"}, + {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:845f352911777a8e722bfce168958214951e07e47e5d5d9744109fa5fe77f79b"}, + {file = "coverage-7.13.4-cp313-cp313t-win32.whl", hash = "sha256:2fa8d5f8de70688a28240de9e139fa16b153cc3cbb01c5f16d88d6505ebdadf9"}, + {file = "coverage-7.13.4-cp313-cp313t-win_amd64.whl", hash = "sha256:9351229c8c8407645840edcc277f4a2d44814d1bc34a2128c11c2a031d45a5dd"}, + {file = "coverage-7.13.4-cp313-cp313t-win_arm64.whl", hash = "sha256:30b8d0512f2dc8c8747557e8fb459d6176a2c9e5731e2b74d311c03b78451997"}, + {file = "coverage-7.13.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:300deaee342f90696ed186e3a00c71b5b3d27bffe9e827677954f4ee56969601"}, + {file = "coverage-7.13.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29e3220258d682b6226a9b0925bc563ed9a1ebcff3cad30f043eceea7eaf2689"}, + {file = "coverage-7.13.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:391ee8f19bef69210978363ca930f7328081c6a0152f1166c91f0b5fdd2a773c"}, + {file = "coverage-7.13.4-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0dd7ab8278f0d58a0128ba2fca25824321f05d059c1441800e934ff2efa52129"}, + {file = "coverage-7.13.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78cdf0d578b15148b009ccf18c686aa4f719d887e76e6b40c38ffb61d264a552"}, + {file = "coverage-7.13.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:48685fee12c2eb3b27c62f2658e7ea21e9c3239cba5a8a242801a0a3f6a8c62a"}, + {file = "coverage-7.13.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4e83efc079eb39480e6346a15a1bcb3e9b04759c5202d157e1dd4303cd619356"}, + {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ecae9737b72408d6a950f7e525f30aca12d4bd8dd95e37342e5beb3a2a8c4f71"}, + {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ae4578f8528569d3cf303fef2ea569c7f4c4059a38c8667ccef15c6e1f118aa5"}, + {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:6fdef321fdfbb30a197efa02d48fcd9981f0d8ad2ae8903ac318adc653f5df98"}, + {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b0f6ccf3dbe577170bebfce1318707d0e8c3650003cb4b3a9dd744575daa8b5"}, + {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75fcd519f2a5765db3f0e391eb3b7d150cce1a771bf4c9f861aeab86c767a3c0"}, + {file = "coverage-7.13.4-cp314-cp314-win32.whl", hash = "sha256:8e798c266c378da2bd819b0677df41ab46d78065fb2a399558f3f6cae78b2fbb"}, + {file = "coverage-7.13.4-cp314-cp314-win_amd64.whl", hash = "sha256:245e37f664d89861cf2329c9afa2c1fe9e6d4e1a09d872c947e70718aeeac505"}, + {file = "coverage-7.13.4-cp314-cp314-win_arm64.whl", hash = "sha256:ad27098a189e5838900ce4c2a99f2fe42a0bf0c2093c17c69b45a71579e8d4a2"}, + {file = "coverage-7.13.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:85480adfb35ffc32d40918aad81b89c69c9cc5661a9b8a81476d3e645321a056"}, + {file = "coverage-7.13.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:79be69cf7f3bf9b0deeeb062eab7ac7f36cd4cc4c4dd694bd28921ba4d8596cc"}, + {file = "coverage-7.13.4-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:caa421e2684e382c5d8973ac55e4f36bed6821a9bad5c953494de960c74595c9"}, + {file = "coverage-7.13.4-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:14375934243ee05f56c45393fe2ce81fe5cc503c07cee2bdf1725fb8bef3ffaf"}, + {file = "coverage-7.13.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25a41c3104d08edb094d9db0d905ca54d0cd41c928bb6be3c4c799a54753af55"}, + {file = "coverage-7.13.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f01afcff62bf9a08fb32b2c1d6e924236c0383c02c790732b6537269e466a72"}, + {file = "coverage-7.13.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eb9078108fbf0bcdde37c3f4779303673c2fa1fe8f7956e68d447d0dd426d38a"}, + {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e086334e8537ddd17e5f16a344777c1ab8194986ec533711cbe6c41cde841b6"}, + {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:725d985c5ab621268b2edb8e50dfe57633dc69bda071abc470fed55a14935fd3"}, + {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:3c06f0f1337c667b971ca2f975523347e63ec5e500b9aa5882d91931cd3ef750"}, + {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:590c0ed4bf8e85f745e6b805b2e1c457b2e33d5255dd9729743165253bc9ad39"}, + {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:eb30bf180de3f632cd043322dad5751390e5385108b2807368997d1a92a509d0"}, + {file = "coverage-7.13.4-cp314-cp314t-win32.whl", hash = "sha256:c4240e7eded42d131a2d2c4dec70374b781b043ddc79a9de4d55ca71f8e98aea"}, + {file = "coverage-7.13.4-cp314-cp314t-win_amd64.whl", hash = "sha256:4c7d3cc01e7350f2f0f6f7036caaf5673fb56b6998889ccfe9e1c1fe75a9c932"}, + {file = "coverage-7.13.4-cp314-cp314t-win_arm64.whl", hash = "sha256:23e3f687cf945070d1c90f85db66d11e3025665d8dafa831301a0e0038f3db9b"}, + {file = "coverage-7.13.4-py3-none-any.whl", hash = "sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0"}, + {file = "coverage-7.13.4.tar.gz", hash = "sha256:e5c8f6ed1e61a8b2dcdf31eb0b9bbf0130750ca79c1c49eb898e2ad86f5ccc91"}, ] [package.dependencies] tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] -toml = ["tomli"] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "csscompressor" @@ -293,6 +345,7 @@ version = "0.9.5" description = "A python port of YUI CSS Compressor" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "csscompressor-0.9.5.tar.gz", hash = "sha256:afa22badbcf3120a4f392e4d22f9fff485c044a1feda4a950ecc5eba9dd31a05"}, ] @@ -303,6 +356,7 @@ version = "0.5.2" description = "Minimal, easy-to-use, declarative cli tool" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "decli-0.5.2-py3-none-any.whl", hash = "sha256:d3207bc02d0169bf6ed74ccca09ce62edca0eb25b0ebf8bf4ae3fb8333e15ca0"}, {file = "decli-0.5.2.tar.gz", hash = "sha256:f2cde55034a75c819c630c7655a844c612f2598c42c21299160465df6ad463ad"}, @@ -310,65 +364,70 @@ files = [ [[package]] name = "dill" -version = "0.3.7" +version = "0.4.1" description = "serialize all of Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, - {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, + {file = "dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d"}, + {file = "dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa"}, ] [package.extras] graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] [[package]] name = "distlib" -version = "0.3.7" +version = "0.4.0" description = "Distribution utilities" optional = false python-versions = "*" +groups = ["dev"] files = [ - {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, - {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, + {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, + {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, ] [[package]] name = "exceptiongroup" -version = "1.1.3" +version = "1.3.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\"" files = [ - {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, - {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, + {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, + {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, ] +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + [package.extras] test = ["pytest (>=6)"] [[package]] name = "filelock" -version = "3.13.1" +version = "3.23.0" description = "A platform independent file lock." optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, - {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, + {file = "filelock-3.23.0-py3-none-any.whl", hash = "sha256:4203c3f43983c7c95e4bbb68786f184f6acb7300899bf99d686bb82d526bdf62"}, + {file = "filelock-3.23.0.tar.gz", hash = "sha256:f64442f6f4707b9385049bb490be0bc48e3ab8e74ad27d4063435252917f4d4b"}, ] -[package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] -typing = ["typing-extensions (>=4.8)"] - [[package]] name = "flake8" version = "4.0.1" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, @@ -385,6 +444,7 @@ version = "2.1.0" description = "Copy your docs directly to the gh-pages branch." optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, @@ -398,13 +458,14 @@ dev = ["flake8", "markdown", "twine", "wheel"] [[package]] name = "gitdb" -version = "4.0.11" +version = "4.0.12" description = "Git Object Database" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"}, - {file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"}, + {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, + {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, ] [package.dependencies] @@ -412,35 +473,69 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.40" +version = "3.1.46" description = "GitPython is a Python library used to interact with Git repositories" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "GitPython-3.1.40-py3-none-any.whl", hash = "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a"}, - {file = "GitPython-3.1.40.tar.gz", hash = "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4"}, + {file = "gitpython-3.1.46-py3-none-any.whl", hash = "sha256:79812ed143d9d25b6d176a10bb511de0f9c67b1fa641d82097b0ab90398a2058"}, + {file = "gitpython-3.1.46.tar.gz", hash = "sha256:400124c7d0ef4ea03f7310ac2fbf7151e09ff97f2a3288d64a440c584a29c37f"}, ] [package.dependencies] gitdb = ">=4.0.1,<5" [package.extras] -test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-instafail", "pytest-subtests", "pytest-sugar"] +doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] +test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy (==1.18.2) ; python_version >= \"3.9\"", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] [[package]] name = "griffe" -version = "1.4.0" +version = "2.0.0" description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "griffe-1.4.0-py3-none-any.whl", hash = "sha256:e589de8b8c137e99a46ec45f9598fc0ac5b6868ce824b24db09c02d117b89bc5"}, - {file = "griffe-1.4.0.tar.gz", hash = "sha256:8fccc585896d13f1221035d32c50dec65830c87d23f9adb9b1e6f3d63574f7f5"}, + {file = "griffe-2.0.0-py3-none-any.whl", hash = "sha256:5418081135a391c3e6e757a7f3f156f1a1a746cc7b4023868ff7d5e2f9a980aa"}, +] + +[package.dependencies] +griffecli = "2.0.0" +griffelib = "2.0.0" + +[package.extras] +pypi = ["griffelib[pypi] (==2.0.0)"] + +[[package]] +name = "griffecli" +version = "2.0.0" +description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "griffecli-2.0.0-py3-none-any.whl", hash = "sha256:9f7cd9ee9b21d55e91689358978d2385ae65c22f307a63fb3269acf3f21e643d"}, ] [package.dependencies] -astunparse = {version = ">=1.6", markers = "python_version < \"3.9\""} colorama = ">=0.4" +griffelib = "2.0.0" + +[[package]] +name = "griffelib" +version = "2.0.0" +description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "griffelib-2.0.0-py3-none-any.whl", hash = "sha256:01284878c966508b6d6f1dbff9b6fa607bc062d8261c5c7253cb285b06422a7f"}, +] + +[package.extras] +pypi = ["pip (>=24.0)", "platformdirs (>=4.2)", "wheel (>=0.42)"] [[package]] name = "htmlmin2" @@ -448,19 +543,21 @@ version = "0.1.13" description = "An HTML Minifier" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "htmlmin2-0.1.13-py3-none-any.whl", hash = "sha256:75609f2a42e64f7ce57dbff28a39890363bde9e7e5885db633317efbdf8c79a2"}, ] [[package]] name = "identify" -version = "2.5.31" +version = "2.6.16" description = "File identification library for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "identify-2.5.31-py2.py3-none-any.whl", hash = "sha256:90199cb9e7bd3c5407a9b7e81b4abec4bb9d249991c79439ec8af740afc6293d"}, - {file = "identify-2.5.31.tar.gz", hash = "sha256:7736b3c7a28233637e3c36550646fc6389bedd74ae84cb788200cc8e2dd60b75"}, + {file = "identify-2.6.16-py2.py3-none-any.whl", hash = "sha256:391ee4d77741d994189522896270b787aed8670389bfd60f326d677d64a6dfb0"}, + {file = "identify-2.6.16.tar.gz", hash = "sha256:846857203b5511bbe94d5a352a48ef2359532bc8f6727b5544077a0dcfb24980"}, ] [package.extras] @@ -468,43 +565,29 @@ license = ["ukkonen"] [[package]] name = "idna" -version = "3.4" +version = "3.11" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.5" -files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, -] - -[[package]] -name = "importlib-metadata" -version = "6.8.0" -description = "Read metadata from Python packages" -optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, - {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, + {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, + {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, ] -[package.dependencies] -zipp = ">=0.5" - [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] [[package]] name = "iniconfig" -version = "2.0.0" +version = "2.3.0" description = "brain-dead simple config-ini parsing" optional = false -python-versions = ">=3.7" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, + {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, + {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, ] [[package]] @@ -513,6 +596,7 @@ version = "5.13.2" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.8.0" +groups = ["dev"] files = [ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, @@ -523,13 +607,14 @@ colors = ["colorama (>=0.4.6)"] [[package]] name = "jinja2" -version = "3.1.2" +version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, + {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, + {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, ] [package.dependencies] @@ -544,140 +629,279 @@ version = "3.0.1" description = "JavaScript minifier." optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "jsmin-3.0.1.tar.gz", hash = "sha256:c0959a121ef94542e807a674142606f7e90214a2b3d1eb17300244bbb5cc2bfc"}, ] [[package]] name = "lazy-object-proxy" -version = "1.9.0" +version = "1.12.0" description = "A fast and thorough lazy object proxy." optional = false -python-versions = ">=3.7" -files = [ - {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "lazy_object_proxy-1.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61d5e3310a4aa5792c2b599a7a78ccf8687292c8eb09cf187cca8f09cf6a7519"}, + {file = "lazy_object_proxy-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1ca33565f698ac1aece152a10f432415d1a2aa9a42dfe23e5ba2bc255ab91f6"}, + {file = "lazy_object_proxy-1.12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d01c7819a410f7c255b20799b65d36b414379a30c6f1684c7bd7eb6777338c1b"}, + {file = "lazy_object_proxy-1.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:029d2b355076710505c9545aef5ab3f750d89779310e26ddf2b7b23f6ea03cd8"}, + {file = "lazy_object_proxy-1.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc6e3614eca88b1c8a625fc0a47d0d745e7c3255b21dac0e30b3037c5e3deeb8"}, + {file = "lazy_object_proxy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:be5fe974e39ceb0d6c9db0663c0464669cf866b2851c73971409b9566e880eab"}, + {file = "lazy_object_proxy-1.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1cf69cd1a6c7fe2dbcc3edaa017cf010f4192e53796538cc7d5e1fedbfa4bcff"}, + {file = "lazy_object_proxy-1.12.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:efff4375a8c52f55a145dc8487a2108c2140f0bec4151ab4e1843e52eb9987ad"}, + {file = "lazy_object_proxy-1.12.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1192e8c2f1031a6ff453ee40213afa01ba765b3dc861302cd91dbdb2e2660b00"}, + {file = "lazy_object_proxy-1.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3605b632e82a1cbc32a1e5034278a64db555b3496e0795723ee697006b980508"}, + {file = "lazy_object_proxy-1.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a61095f5d9d1a743e1e20ec6d6db6c2ca511961777257ebd9b288951b23b44fa"}, + {file = "lazy_object_proxy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:997b1d6e10ecc6fb6fe0f2c959791ae59599f41da61d652f6c903d1ee58b7370"}, + {file = "lazy_object_proxy-1.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ee0d6027b760a11cc18281e702c0309dd92da458a74b4c15025d7fc490deede"}, + {file = "lazy_object_proxy-1.12.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4ab2c584e3cc8be0dfca422e05ad30a9abe3555ce63e9ab7a559f62f8dbc6ff9"}, + {file = "lazy_object_proxy-1.12.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:14e348185adbd03ec17d051e169ec45686dcd840a3779c9d4c10aabe2ca6e1c0"}, + {file = "lazy_object_proxy-1.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c4fcbe74fb85df8ba7825fa05eddca764138da752904b378f0ae5ab33a36c308"}, + {file = "lazy_object_proxy-1.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:563d2ec8e4d4b68ee7848c5ab4d6057a6d703cb7963b342968bb8758dda33a23"}, + {file = "lazy_object_proxy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:53c7fd99eb156bbb82cbc5d5188891d8fdd805ba6c1e3b92b90092da2a837073"}, + {file = "lazy_object_proxy-1.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:86fd61cb2ba249b9f436d789d1356deae69ad3231dc3c0f17293ac535162672e"}, + {file = "lazy_object_proxy-1.12.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:81d1852fb30fab81696f93db1b1e55a5d1ff7940838191062f5f56987d5fcc3e"}, + {file = "lazy_object_proxy-1.12.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be9045646d83f6c2664c1330904b245ae2371b5c57a3195e4028aedc9f999655"}, + {file = "lazy_object_proxy-1.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:67f07ab742f1adfb3966c40f630baaa7902be4222a17941f3d85fd1dae5565ff"}, + {file = "lazy_object_proxy-1.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:75ba769017b944fcacbf6a80c18b2761a1795b03f8899acdad1f1c39db4409be"}, + {file = "lazy_object_proxy-1.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:7b22c2bbfb155706b928ac4d74c1a63ac8552a55ba7fff4445155523ea4067e1"}, + {file = "lazy_object_proxy-1.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4a79b909aa16bde8ae606f06e6bbc9d3219d2e57fb3e0076e17879072b742c65"}, + {file = "lazy_object_proxy-1.12.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:338ab2f132276203e404951205fe80c3fd59429b3a724e7b662b2eb539bb1be9"}, + {file = "lazy_object_proxy-1.12.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c40b3c9faee2e32bfce0df4ae63f4e73529766893258eca78548bac801c8f66"}, + {file = "lazy_object_proxy-1.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:717484c309df78cedf48396e420fa57fc8a2b1f06ea889df7248fdd156e58847"}, + {file = "lazy_object_proxy-1.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a6b7ea5ea1ffe15059eb44bcbcb258f97bcb40e139b88152c40d07b1a1dfc9ac"}, + {file = "lazy_object_proxy-1.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:08c465fb5cd23527512f9bd7b4c7ba6cec33e28aad36fbbe46bf7b858f9f3f7f"}, + {file = "lazy_object_proxy-1.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c9defba70ab943f1df98a656247966d7729da2fe9c2d5d85346464bf320820a3"}, + {file = "lazy_object_proxy-1.12.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6763941dbf97eea6b90f5b06eb4da9418cc088fce0e3883f5816090f9afcde4a"}, + {file = "lazy_object_proxy-1.12.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fdc70d81235fc586b9e3d1aeef7d1553259b62ecaae9db2167a5d2550dcc391a"}, + {file = "lazy_object_proxy-1.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0a83c6f7a6b2bfc11ef3ed67f8cbe99f8ff500b05655d8e7df9aab993a6abc95"}, + {file = "lazy_object_proxy-1.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:256262384ebd2a77b023ad02fbcc9326282bcfd16484d5531154b02bc304f4c5"}, + {file = "lazy_object_proxy-1.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:7601ec171c7e8584f8ff3f4e440aa2eebf93e854f04639263875b8c2971f819f"}, + {file = "lazy_object_proxy-1.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ae575ad9b674d0029fc077c5231b3bc6b433a3d1a62a8c363df96974b5534728"}, + {file = "lazy_object_proxy-1.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31020c84005d3daa4cc0fa5a310af2066efe6b0d82aeebf9ab199292652ff036"}, + {file = "lazy_object_proxy-1.12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:800f32b00a47c27446a2b767df7538e6c66a3488632c402b4fb2224f9794f3c0"}, + {file = "lazy_object_proxy-1.12.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:15400b18893f345857b9e18b9bd87bd06aba84af6ed086187add70aeaa3f93f1"}, + {file = "lazy_object_proxy-1.12.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3d3964fbd326578bcdfffd017ef101b6fb0484f34e731fe060ba9b8816498c36"}, + {file = "lazy_object_proxy-1.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:424a8ab6695400845c39f13c685050eab69fa0bbac5790b201cd27375e5e41d7"}, + {file = "lazy_object_proxy-1.12.0-pp39.pp310.pp311.graalpy311-none-any.whl", hash = "sha256:c3b2e0af1f7f77c4263759c4824316ce458fabe0fceadcd24ef8ca08b2d1e402"}, + {file = "lazy_object_proxy-1.12.0.tar.gz", hash = "sha256:1f5a462d92fd0cfb82f1fab28b51bfb209fabbe6aabf7f0d51472c0c124c0c61"}, +] + +[[package]] +name = "librt" +version = "0.8.0" +description = "Mypyc runtime library" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +markers = "platform_python_implementation != \"PyPy\"" +files = [ + {file = "librt-0.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef"}, + {file = "librt-0.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6"}, + {file = "librt-0.8.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5"}, + {file = "librt-0.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb"}, + {file = "librt-0.8.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e"}, + {file = "librt-0.8.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e"}, + {file = "librt-0.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630"}, + {file = "librt-0.8.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567"}, + {file = "librt-0.8.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4"}, + {file = "librt-0.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf"}, + {file = "librt-0.8.0-cp310-cp310-win32.whl", hash = "sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f"}, + {file = "librt-0.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9"}, + {file = "librt-0.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369"}, + {file = "librt-0.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6"}, + {file = "librt-0.8.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa"}, + {file = "librt-0.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f"}, + {file = "librt-0.8.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef"}, + {file = "librt-0.8.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9"}, + {file = "librt-0.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4"}, + {file = "librt-0.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6"}, + {file = "librt-0.8.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da"}, + {file = "librt-0.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1"}, + {file = "librt-0.8.0-cp311-cp311-win32.whl", hash = "sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258"}, + {file = "librt-0.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817"}, + {file = "librt-0.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4"}, + {file = "librt-0.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645"}, + {file = "librt-0.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467"}, + {file = "librt-0.8.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a"}, + {file = "librt-0.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45"}, + {file = "librt-0.8.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d"}, + {file = "librt-0.8.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c"}, + {file = "librt-0.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f"}, + {file = "librt-0.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9"}, + {file = "librt-0.8.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a"}, + {file = "librt-0.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79"}, + {file = "librt-0.8.0-cp312-cp312-win32.whl", hash = "sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c"}, + {file = "librt-0.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8"}, + {file = "librt-0.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e"}, + {file = "librt-0.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1"}, + {file = "librt-0.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf"}, + {file = "librt-0.8.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8"}, + {file = "librt-0.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad"}, + {file = "librt-0.8.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01"}, + {file = "librt-0.8.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada"}, + {file = "librt-0.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae"}, + {file = "librt-0.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d"}, + {file = "librt-0.8.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3"}, + {file = "librt-0.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b"}, + {file = "librt-0.8.0-cp313-cp313-win32.whl", hash = "sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935"}, + {file = "librt-0.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab"}, + {file = "librt-0.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2"}, + {file = "librt-0.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda"}, + {file = "librt-0.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556"}, + {file = "librt-0.8.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06"}, + {file = "librt-0.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376"}, + {file = "librt-0.8.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816"}, + {file = "librt-0.8.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e"}, + {file = "librt-0.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52"}, + {file = "librt-0.8.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da"}, + {file = "librt-0.8.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab"}, + {file = "librt-0.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3"}, + {file = "librt-0.8.0-cp314-cp314-win32.whl", hash = "sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a"}, + {file = "librt-0.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7"}, + {file = "librt-0.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4"}, + {file = "librt-0.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb"}, + {file = "librt-0.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5"}, + {file = "librt-0.8.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c"}, + {file = "librt-0.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546"}, + {file = "librt-0.8.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944"}, + {file = "librt-0.8.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e"}, + {file = "librt-0.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61"}, + {file = "librt-0.8.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05"}, + {file = "librt-0.8.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25"}, + {file = "librt-0.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c"}, + {file = "librt-0.8.0-cp314-cp314t-win32.whl", hash = "sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447"}, + {file = "librt-0.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9"}, + {file = "librt-0.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc"}, + {file = "librt-0.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d"}, + {file = "librt-0.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6"}, + {file = "librt-0.8.0-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141"}, + {file = "librt-0.8.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d"}, + {file = "librt-0.8.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d"}, + {file = "librt-0.8.0-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216"}, + {file = "librt-0.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787"}, + {file = "librt-0.8.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6"}, + {file = "librt-0.8.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25"}, + {file = "librt-0.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de"}, + {file = "librt-0.8.0-cp39-cp39-win32.whl", hash = "sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9"}, + {file = "librt-0.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf"}, + {file = "librt-0.8.0.tar.gz", hash = "sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b"}, ] [[package]] name = "markdown" -version = "3.7" +version = "3.10.2" description = "Python implementation of John Gruber's Markdown." optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"}, - {file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"}, + {file = "markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36"}, + {file = "markdown-3.10.2.tar.gz", hash = "sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950"}, ] -[package.dependencies] -importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} - [package.extras] -docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] +docs = ["mdx_gh_links (>=0.2)", "mkdocs (>=1.6)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python] (>=0.28.3)"] testing = ["coverage", "pyyaml"] [[package]] name = "markupsafe" -version = "2.1.3" +version = "3.0.3" description = "Safely add untrusted strings to HTML/XML markup." optional = false -python-versions = ">=3.7" -files = [ - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, - {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"}, + {file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"}, + {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695"}, + {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591"}, + {file = "markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c"}, + {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f"}, + {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6"}, + {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1"}, + {file = "markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa"}, + {file = "markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8"}, + {file = "markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1"}, + {file = "markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad"}, + {file = "markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a"}, + {file = "markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19"}, + {file = "markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01"}, + {file = "markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c"}, + {file = "markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e"}, + {file = "markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b"}, + {file = "markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d"}, + {file = "markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c"}, + {file = "markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f"}, + {file = "markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795"}, + {file = "markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219"}, + {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6"}, + {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676"}, + {file = "markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9"}, + {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1"}, + {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc"}, + {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12"}, + {file = "markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed"}, + {file = "markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5"}, + {file = "markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485"}, + {file = "markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73"}, + {file = "markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37"}, + {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19"}, + {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025"}, + {file = "markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6"}, + {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f"}, + {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb"}, + {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009"}, + {file = "markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354"}, + {file = "markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218"}, + {file = "markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287"}, + {file = "markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe"}, + {file = "markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026"}, + {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737"}, + {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97"}, + {file = "markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d"}, + {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda"}, + {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf"}, + {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe"}, + {file = "markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9"}, + {file = "markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581"}, + {file = "markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4"}, + {file = "markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab"}, + {file = "markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175"}, + {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634"}, + {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50"}, + {file = "markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e"}, + {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5"}, + {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523"}, + {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc"}, + {file = "markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d"}, + {file = "markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9"}, + {file = "markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa"}, + {file = "markupsafe-3.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26"}, + {file = "markupsafe-3.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc"}, + {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c"}, + {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42"}, + {file = "markupsafe-3.0.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b"}, + {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758"}, + {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2"}, + {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d"}, + {file = "markupsafe-3.0.3-cp39-cp39-win32.whl", hash = "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7"}, + {file = "markupsafe-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e"}, + {file = "markupsafe-3.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8"}, + {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] [[package]] @@ -686,6 +910,7 @@ version = "0.6.1" description = "McCabe checker, plugin for flake8" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, @@ -697,6 +922,7 @@ version = "1.3.4" description = "A deep merge function for 🐍." optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, @@ -708,6 +934,7 @@ version = "1.6.1" description = "Project documentation with Markdown." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e"}, {file = "mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2"}, @@ -717,7 +944,6 @@ files = [ click = ">=7.0" colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} ghp-import = ">=1.0" -importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} jinja2 = ">=2.11.1" markdown = ">=3.3.6" markupsafe = ">=2.0.1" @@ -731,7 +957,7 @@ watchdog = ">=2.0" [package.extras] i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4) ; platform_system == \"Windows\"", "ghp-import (==1.0)", "importlib-metadata (==4.4) ; python_version < \"3.10\"", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] [[package]] name = "mkdocs-autolinks-plugin" @@ -739,6 +965,7 @@ version = "0.7.1" description = "An MkDocs plugin" optional = false python-versions = ">=3.4" +groups = ["dev"] files = [ {file = "mkdocs-autolinks-plugin-0.7.1.tar.gz", hash = "sha256:445ddb9b417b7795856c30801bb430773186c1daf210bdeecf8305f55a47d151"}, {file = "mkdocs_autolinks_plugin-0.7.1-py3-none-any.whl", hash = "sha256:5c6c17f6649b68e79a9ef0b2648d59f3072e18002b90ee1586a64c505f11ab12"}, @@ -749,13 +976,14 @@ mkdocs = ">=1.2.3" [[package]] name = "mkdocs-autorefs" -version = "1.2.0" +version = "1.4.4" description = "Automatically link across pages in MkDocs." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "mkdocs_autorefs-1.2.0-py3-none-any.whl", hash = "sha256:d588754ae89bd0ced0c70c06f58566a4ee43471eeeee5202427da7de9ef85a2f"}, - {file = "mkdocs_autorefs-1.2.0.tar.gz", hash = "sha256:a86b93abff653521bda71cf3fc5596342b7a23982093915cb74273f67522190f"}, + {file = "mkdocs_autorefs-1.4.4-py3-none-any.whl", hash = "sha256:834ef5408d827071ad1bc69e0f39704fa34c7fc05bc8e1c72b227dfdc5c76089"}, + {file = "mkdocs_autorefs-1.4.4.tar.gz", hash = "sha256:d54a284f27a7346b9c38f1f852177940c222da508e66edc816a0fa55fc6da197"}, ] [package.dependencies] @@ -769,6 +997,7 @@ version = "0.5.0" description = "MkDocs plugin to programmatically generate documentation pages during the build" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "mkdocs_gen_files-0.5.0-py3-none-any.whl", hash = "sha256:7ac060096f3f40bd19039e7277dd3050be9a453c8ac578645844d4d91d7978ea"}, {file = "mkdocs_gen_files-0.5.0.tar.gz", hash = "sha256:4c7cf256b5d67062a788f6b1d035e157fc1a9498c2399be9af5257d4ff4d19bc"}, @@ -783,33 +1012,34 @@ version = "0.2.0" description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"}, {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"}, ] [package.dependencies] -importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} mergedeep = ">=1.3.4" platformdirs = ">=2.2.0" pyyaml = ">=5.1" [[package]] name = "mkdocs-git-revision-date-localized-plugin" -version = "1.2.1" +version = "1.5.1" description = "Mkdocs plugin that enables displaying the localized date of the last git modification of a markdown file." optional = false -python-versions = ">=3.6" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "mkdocs-git-revision-date-localized-plugin-1.2.1.tar.gz", hash = "sha256:fc5b23a9d572cbba0114e9e17152001d01724990cb308830e58291fa614faf73"}, - {file = "mkdocs_git_revision_date_localized_plugin-1.2.1-py3-none-any.whl", hash = "sha256:d57dc99d67af917899e69c392f1ebccd1779fa243d641255469b03f8a3596b96"}, + {file = "mkdocs_git_revision_date_localized_plugin-1.5.1-py3-none-any.whl", hash = "sha256:b00fd36ed0f9b2326b1488fd8fa31bf2ce64e68c4aa60a9ce857f10719571903"}, + {file = "mkdocs_git_revision_date_localized_plugin-1.5.1.tar.gz", hash = "sha256:2b0239455cd84784dd87ac8dfc9253fe4b2dd35e102696f21b5d34e2175981c6"}, ] [package.dependencies] babel = ">=2.7.0" -GitPython = "*" +gitpython = ">=3.1.44" mkdocs = ">=1.0" -pytz = "*" +tzdata = {version = ">=2023.3", markers = "sys_platform == \"win32\""} [[package]] name = "mkdocs-git-revision-date-plugin" @@ -817,6 +1047,7 @@ version = "0.3.2" description = "MkDocs plugin for setting revision date from git per markdown file." optional = false python-versions = ">=3.4" +groups = ["dev"] files = [ {file = "mkdocs_git_revision_date_plugin-0.3.2-py3-none-any.whl", hash = "sha256:2e67956cb01823dd2418e2833f3623dee8604cdf223bddd005fe36226a56f6ef"}, ] @@ -832,6 +1063,7 @@ version = "3.9.1" description = "Mkdocs Markdown includer plugin." optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "mkdocs_include_markdown_plugin-3.9.1-py3-none-any.whl", hash = "sha256:f33687e29ac66d045ba181ea50f054646b0090b42b0a4318f08e7f1d1235e6f6"}, {file = "mkdocs_include_markdown_plugin-3.9.1.tar.gz", hash = "sha256:5e5698e78d7fea111be9873a456089daa333497988405acaac8eba2924a19152"}, @@ -843,17 +1075,18 @@ test = ["mkdocs (==1.4.0)", "pytest (==7.1.3)", "pytest-cov (==3.0.0)"] [[package]] name = "mkdocs-literate-nav" -version = "0.6.1" +version = "0.6.2" description = "MkDocs plugin to specify the navigation in Markdown instead of YAML" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "mkdocs_literate_nav-0.6.1-py3-none-any.whl", hash = "sha256:e70bdc4a07050d32da79c0b697bd88e9a104cf3294282e9cb20eec94c6b0f401"}, - {file = "mkdocs_literate_nav-0.6.1.tar.gz", hash = "sha256:78a7ab6d878371728acb0cdc6235c9b0ffc6e83c997b037f4a5c6ff7cef7d759"}, + {file = "mkdocs_literate_nav-0.6.2-py3-none-any.whl", hash = "sha256:0a6489a26ec7598477b56fa112056a5e3a6c15729f0214bea8a4dbc55bd5f630"}, + {file = "mkdocs_literate_nav-0.6.2.tar.gz", hash = "sha256:760e1708aa4be86af81a2b56e82c739d5a8388a0eab1517ecfd8e5aa40810a75"}, ] [package.dependencies] -mkdocs = ">=1.0.3" +mkdocs = ">=1.4.1" [[package]] name = "mkdocs-material" @@ -861,6 +1094,7 @@ version = "8.5.11" description = "Documentation that simply works" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "mkdocs_material-8.5.11-py3-none-any.whl", hash = "sha256:c907b4b052240a5778074a30a78f31a1f8ff82d7012356dc26898b97559f082e"}, {file = "mkdocs_material-8.5.11.tar.gz", hash = "sha256:b0ea0513fd8cab323e8a825d6692ea07fa83e917bb5db042e523afecc7064ab7"}, @@ -877,13 +1111,14 @@ requests = ">=2.26" [[package]] name = "mkdocs-material-extensions" -version = "1.3" +version = "1.3.1" description = "Extension pack for Python Markdown and MkDocs Material." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "mkdocs_material_extensions-1.3-py3-none-any.whl", hash = "sha256:0297cc48ba68a9fdd1ef3780a3b41b534b0d0df1d1181a44676fda5f464eeadc"}, - {file = "mkdocs_material_extensions-1.3.tar.gz", hash = "sha256:f0446091503acb110a7cab9349cbc90eeac51b58d1caa92a704a81ca1e24ddbd"}, + {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"}, + {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"}, ] [[package]] @@ -892,6 +1127,7 @@ version = "0.8.0" description = "An MkDocs plugin to minify HTML, JS or CSS files prior to being written to disk" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mkdocs-minify-plugin-0.8.0.tar.gz", hash = "sha256:bc11b78b8120d79e817308e2b11539d790d21445eb63df831e393f76e52e753d"}, {file = "mkdocs_minify_plugin-0.8.0-py3-none-any.whl", hash = "sha256:5fba1a3f7bd9a2142c9954a6559a57e946587b21f133165ece30ea145c66aee6"}, @@ -909,6 +1145,7 @@ version = "2.8" description = "Plugin to extend MkDocs Material theme." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mkdocs_pymdownx_material_extras-2.8-py3-none-any.whl", hash = "sha256:81b68789420c51b9b15514180d0f3ab7136d56ee512c830c998d2edb77ca3d77"}, {file = "mkdocs_pymdownx_material_extras-2.8.tar.gz", hash = "sha256:7b22bb119cd9592f98d6c6d4d269506d9a68d7038355c71525aadc88169ee9fe"}, @@ -923,6 +1160,7 @@ version = "0.1.3" description = "MkDocs plugin to allow placing mkdocs.yml in the same directory as documentation" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mkdocs_same_dir-0.1.3-py3-none-any.whl", hash = "sha256:3d094649e2e47efcf90a8b0051a4c2b837aaf4137a28c8e334ba9465804a317e"}, {file = "mkdocs_same_dir-0.1.3.tar.gz", hash = "sha256:c849556b1d79ae270947f41bb89d442aa1e858ab6ec6423eb178ae76a7f984fc"}, @@ -933,97 +1171,99 @@ mkdocs = ">=1.0.3" [[package]] name = "mkdocstrings" -version = "0.26.1" +version = "1.0.3" description = "Automatic documentation from sources, for MkDocs." optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "mkdocstrings-0.26.1-py3-none-any.whl", hash = "sha256:29738bfb72b4608e8e55cc50fb8a54f325dc7ebd2014e4e3881a49892d5983cf"}, - {file = "mkdocstrings-0.26.1.tar.gz", hash = "sha256:bb8b8854d6713d5348ad05b069a09f3b79edbc6a0f33a34c6821141adb03fe33"}, + {file = "mkdocstrings-1.0.3-py3-none-any.whl", hash = "sha256:0d66d18430c2201dc7fe85134277382baaa15e6b30979f3f3bdbabd6dbdb6046"}, + {file = "mkdocstrings-1.0.3.tar.gz", hash = "sha256:ab670f55040722b49bb45865b2e93b824450fb4aef638b00d7acb493a9020434"}, ] [package.dependencies] -click = ">=7.0" -importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} -Jinja2 = ">=2.11.1" +Jinja2 = ">=3.1" Markdown = ">=3.6" MarkupSafe = ">=1.1" -mkdocs = ">=1.4" -mkdocs-autorefs = ">=1.2" -platformdirs = ">=2.2" +mkdocs = ">=1.6" +mkdocs-autorefs = ">=1.4" pymdown-extensions = ">=6.3" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.10\""} [package.extras] crystal = ["mkdocstrings-crystal (>=0.3.4)"] -python = ["mkdocstrings-python (>=0.5.2)"] +python = ["mkdocstrings-python (>=1.16.2)"] python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] [[package]] name = "mkdocstrings-python" -version = "1.11.1" +version = "1.19.0" description = "A Python handler for mkdocstrings." optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "mkdocstrings_python-1.11.1-py3-none-any.whl", hash = "sha256:a21a1c05acef129a618517bb5aae3e33114f569b11588b1e7af3e9d4061a71af"}, - {file = "mkdocstrings_python-1.11.1.tar.gz", hash = "sha256:8824b115c5359304ab0b5378a91f6202324a849e1da907a3485b59208b797322"}, + {file = "mkdocstrings_python-1.19.0-py3-none-any.whl", hash = "sha256:395c1032af8f005234170575cc0c5d4d20980846623b623b35594281be4a3059"}, + {file = "mkdocstrings_python-1.19.0.tar.gz", hash = "sha256:917aac66cf121243c11db5b89f66b0ded6c53ec0de5318ff5e22424eb2f2e57c"}, ] [package.dependencies] -griffe = ">=0.49" -mkdocs-autorefs = ">=1.2" -mkdocstrings = ">=0.26" +griffe = ">=1.13" +mkdocs-autorefs = ">=1.4" +mkdocstrings = ">=0.30" +typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} [[package]] name = "mypy" -version = "1.14.1" +version = "1.19.1" description = "Optional static typing for Python" optional = false -python-versions = ">=3.8" -files = [ - {file = "mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb"}, - {file = "mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b"}, - {file = "mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427"}, - {file = "mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f"}, - {file = "mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1"}, - {file = "mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e"}, - {file = "mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89"}, - {file = "mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9"}, - {file = "mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd"}, - {file = "mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac"}, - {file = "mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b"}, - {file = "mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb"}, - {file = "mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60"}, - {file = "mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c"}, - {file = "mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1"}, - {file = "mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6"}, +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec"}, + {file = "mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b"}, + {file = "mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6"}, + {file = "mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74"}, + {file = "mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1"}, + {file = "mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac"}, + {file = "mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288"}, + {file = "mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab"}, + {file = "mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6"}, + {file = "mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331"}, + {file = "mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925"}, + {file = "mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042"}, + {file = "mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1"}, + {file = "mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e"}, + {file = "mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2"}, + {file = "mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8"}, + {file = "mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a"}, + {file = "mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13"}, + {file = "mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250"}, + {file = "mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b"}, + {file = "mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e"}, + {file = "mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef"}, + {file = "mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75"}, + {file = "mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd"}, + {file = "mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1"}, + {file = "mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718"}, + {file = "mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b"}, + {file = "mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045"}, + {file = "mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957"}, + {file = "mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f"}, + {file = "mypy-1.19.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3"}, + {file = "mypy-1.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a"}, + {file = "mypy-1.19.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67"}, + {file = "mypy-1.19.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e"}, + {file = "mypy-1.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376"}, + {file = "mypy-1.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24"}, + {file = "mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247"}, + {file = "mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba"}, ] [package.dependencies] +librt = {version = ">=0.6.2", markers = "platform_python_implementation != \"PyPy\""} mypy_extensions = ">=1.0.0" +pathspec = ">=0.9.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing_extensions = ">=4.6.0" @@ -1036,80 +1276,85 @@ reports = ["lxml"] [[package]] name = "mypy-extensions" -version = "1.0.0" +version = "1.1.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, + {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, + {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, ] [[package]] name = "nodeenv" -version = "1.8.0" +version = "1.10.0" description = "Node.js virtual environment builder" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] files = [ - {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, - {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, + {file = "nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827"}, + {file = "nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb"}, ] -[package.dependencies] -setuptools = "*" - [[package]] name = "packaging" -version = "23.2" +version = "26.0" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["main", "dev"] files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, + {file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"}, + {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"}, ] [[package]] name = "pathspec" -version = "0.11.2" +version = "1.0.4" description = "Utility library for gitignore style pattern matching of file paths." optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, - {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, + {file = "pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723"}, + {file = "pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645"}, ] +[package.extras] +hyperscan = ["hyperscan (>=0.7)"] +optional = ["typing-extensions (>=4)"] +re2 = ["google-re2 (>=1.1)"] +tests = ["pytest (>=9)", "typing-extensions (>=4.15)"] + [[package]] name = "platformdirs" -version = "3.11.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +version = "4.8.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false -python-versions = ">=3.7" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"}, - {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"}, + {file = "platformdirs-4.8.0-py3-none-any.whl", hash = "sha256:1c1328b4d2ea997bbcb904175a9bde14e824a3fa79f751ea3888d63d7d727557"}, + {file = "platformdirs-4.8.0.tar.gz", hash = "sha256:c1d4a51ab04087041dd602707fbe7ee8b62b64e590f30e336e5c99c2d0c542d2"}, ] -[package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] - [[package]] name = "pluggy" -version = "1.5.0" +version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, ] [package.extras] dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] +testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "pre-commit" @@ -1117,6 +1362,7 @@ version = "2.21.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"}, {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"}, @@ -1131,13 +1377,14 @@ virtualenv = ">=20.10.0" [[package]] name = "prompt-toolkit" -version = "3.0.39" +version = "3.0.52" description = "Library for building powerful interactive command lines in Python" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"}, - {file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"}, + {file = "prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955"}, + {file = "prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855"}, ] [package.dependencies] @@ -1149,6 +1396,7 @@ version = "2.8.0" description = "Python style guide checker" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["dev"] files = [ {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, @@ -1160,6 +1408,7 @@ version = "2.4.0" description = "passive checker of Python programs" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] files = [ {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, @@ -1167,17 +1416,18 @@ files = [ [[package]] name = "pygments" -version = "2.16.1" +version = "2.19.2" description = "Pygments is a syntax highlighting package written in Python." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, - {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, + {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, + {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, ] [package.extras] -plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pylint" @@ -1185,6 +1435,7 @@ version = "2.17.7" description = "python code static checker" optional = false python-versions = ">=3.7.2" +groups = ["dev"] files = [ {file = "pylint-2.17.7-py3-none-any.whl", hash = "sha256:27a8d4c7ddc8c2f8c18aa0050148f89ffc09838142193fdbe98f172781a3ff87"}, {file = "pylint-2.17.7.tar.gz", hash = "sha256:f4fcac7ae74cfe36bc8451e931d8438e4a476c20314b1101c458ad0f05191fad"}, @@ -1202,7 +1453,6 @@ mccabe = ">=0.6,<0.8" platformdirs = ">=2.2.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} tomlkit = ">=0.10.1" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] spelling = ["pyenchant (>=3.2,<4.0)"] @@ -1210,43 +1460,46 @@ testutils = ["gitpython (>3)"] [[package]] name = "pymdown-extensions" -version = "10.3.1" +version = "10.20.1" description = "Extension pack for Python Markdown." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "pymdown_extensions-10.3.1-py3-none-any.whl", hash = "sha256:8cba67beb2a1318cdaf742d09dff7c0fc4cafcc290147ade0f8fb7b71522711a"}, - {file = "pymdown_extensions-10.3.1.tar.gz", hash = "sha256:f6c79941498a458852853872e379e7bab63888361ba20992fc8b4f8a9b61735e"}, + {file = "pymdown_extensions-10.20.1-py3-none-any.whl", hash = "sha256:24af7feacbca56504b313b7b418c4f5e1317bb5fea60f03d57be7fcc40912aa0"}, + {file = "pymdown_extensions-10.20.1.tar.gz", hash = "sha256:e7e39c865727338d434b55f1dd8da51febcffcaebd6e1a0b9c836243f660740a"}, ] [package.dependencies] -markdown = ">=3.2" +markdown = ">=3.6" pyyaml = "*" [package.extras] -extra = ["pygments (>=2.12)"] +extra = ["pygments (>=2.19.1)"] [[package]] name = "pytest" -version = "8.3.5" +version = "9.0.2" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, - {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, + {file = "pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b"}, + {file = "pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11"}, ] [package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -iniconfig = "*" -packaging = "*" +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} +iniconfig = ">=1.0.1" +packaging = ">=22" pluggy = ">=1.5,<2" +pygments = ">=2.7.2" tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" @@ -1254,6 +1507,7 @@ version = "4.1.0" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.7" +groups = ["dev"] 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"}, @@ -1268,98 +1522,112 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale [[package]] name = "python-dateutil" -version = "2.8.2" +version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["dev"] files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] [package.dependencies] six = ">=1.5" -[[package]] -name = "pytz" -version = "2023.3.post1" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -files = [ - {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, - {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, -] - [[package]] name = "pyyaml" -version = "6.0.1" +version = "6.0.3" description = "YAML parser and emitter for Python" optional = false -python-versions = ">=3.6" -files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "PyYAML-6.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f"}, + {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4"}, + {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3"}, + {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6"}, + {file = "PyYAML-6.0.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369"}, + {file = "PyYAML-6.0.3-cp38-cp38-win32.whl", hash = "sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295"}, + {file = "PyYAML-6.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b"}, + {file = "pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b"}, + {file = "pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956"}, + {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8"}, + {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198"}, + {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b"}, + {file = "pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0"}, + {file = "pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69"}, + {file = "pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e"}, + {file = "pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c"}, + {file = "pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e"}, + {file = "pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824"}, + {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c"}, + {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00"}, + {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d"}, + {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a"}, + {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4"}, + {file = "pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b"}, + {file = "pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf"}, + {file = "pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196"}, + {file = "pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0"}, + {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28"}, + {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c"}, + {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc"}, + {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e"}, + {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea"}, + {file = "pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5"}, + {file = "pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b"}, + {file = "pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd"}, + {file = "pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8"}, + {file = "pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1"}, + {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c"}, + {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5"}, + {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6"}, + {file = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6"}, + {file = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be"}, + {file = "pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26"}, + {file = "pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c"}, + {file = "pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb"}, + {file = "pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac"}, + {file = "pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310"}, + {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7"}, + {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788"}, + {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5"}, + {file = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764"}, + {file = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35"}, + {file = "pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac"}, + {file = "pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3"}, + {file = "pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3"}, + {file = "pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba"}, + {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c"}, + {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702"}, + {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c"}, + {file = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065"}, + {file = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65"}, + {file = "pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9"}, + {file = "pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b"}, + {file = "pyyaml-6.0.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da"}, + {file = "pyyaml-6.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917"}, + {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9"}, + {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5"}, + {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a"}, + {file = "pyyaml-6.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926"}, + {file = "pyyaml-6.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7"}, + {file = "pyyaml-6.0.3-cp39-cp39-win32.whl", hash = "sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0"}, + {file = "pyyaml-6.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007"}, + {file = "pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f"}, ] [[package]] name = "pyyaml-env-tag" -version = "0.1" -description = "A custom YAML tag for referencing environment variables in YAML files. " +version = "1.1" +description = "A custom YAML tag for referencing environment variables in YAML files." optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, - {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, + {file = "pyyaml_env_tag-1.1-py3-none-any.whl", hash = "sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04"}, + {file = "pyyaml_env_tag-1.1.tar.gz", hash = "sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff"}, ] [package.dependencies] @@ -1371,6 +1639,7 @@ version = "1.10.0" description = "Python library to build pretty command line user prompts ⭐️" optional = false python-versions = ">=3.6,<4.0" +groups = ["dev"] files = [ {file = "questionary-1.10.0-py3-none-any.whl", hash = "sha256:fecfcc8cca110fda9d561cb83f1e97ecbb93c613ff857f655818839dac74ce90"}, {file = "questionary-1.10.0.tar.gz", hash = "sha256:600d3aefecce26d48d97eee936fdb66e4bc27f934c3ab6dd1e292c4f43946d90"}, @@ -1384,18 +1653,19 @@ docs = ["Sphinx (>=3.3,<4.0)", "sphinx-autobuild (>=2020.9.1,<2021.0.0)", "sphin [[package]] name = "requests" -version = "2.31.0" +version = "2.32.5" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, + {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, ] [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" +charset_normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.21.1,<3" @@ -1403,42 +1673,28 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] -[[package]] -name = "setuptools" -version = "68.2.2" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, - {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["dev"] files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] name = "smmap" -version = "5.0.1" +version = "5.0.2" description = "A pure Python implementation of a sliding window memory map manager" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, - {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, + {file = "smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e"}, + {file = "smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5"}, ] [[package]] @@ -1447,19 +1703,21 @@ version = "1.2.0" description = "String case converter." optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "stringcase-1.2.0.tar.gz", hash = "sha256:48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008"}, ] [[package]] name = "termcolor" -version = "2.3.0" +version = "2.5.0" description = "ANSI color formatting for output in terminal" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "termcolor-2.3.0-py3-none-any.whl", hash = "sha256:3afb05607b89aed0ffe25202399ee0867ad4d3cb4180d98aaf8eefa6a5f7d475"}, - {file = "termcolor-2.3.0.tar.gz", hash = "sha256:b5b08f68937f138fe92f6c089b99f1e2da0ae56c52b78bf7075fd95420fd9a5a"}, + {file = "termcolor-2.5.0-py3-none-any.whl", hash = "sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8"}, + {file = "termcolor-2.5.0.tar.gz", hash = "sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f"}, ] [package.extras] @@ -1467,108 +1725,177 @@ tests = ["pytest", "pytest-cov"] [[package]] name = "tomli" -version = "2.0.1" +version = "2.4.0" description = "A lil' TOML parser" optional = false -python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\"" +files = [ + {file = "tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867"}, + {file = "tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9"}, + {file = "tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95"}, + {file = "tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76"}, + {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d"}, + {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576"}, + {file = "tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a"}, + {file = "tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa"}, + {file = "tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614"}, + {file = "tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1"}, + {file = "tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8"}, + {file = "tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a"}, + {file = "tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1"}, + {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b"}, + {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51"}, + {file = "tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729"}, + {file = "tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da"}, + {file = "tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3"}, + {file = "tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0"}, + {file = "tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e"}, + {file = "tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4"}, + {file = "tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e"}, + {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c"}, + {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f"}, + {file = "tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86"}, + {file = "tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87"}, + {file = "tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132"}, + {file = "tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6"}, + {file = "tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc"}, + {file = "tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66"}, + {file = "tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d"}, + {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702"}, + {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8"}, + {file = "tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776"}, + {file = "tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475"}, + {file = "tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2"}, + {file = "tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9"}, + {file = "tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0"}, + {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df"}, + {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d"}, + {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f"}, + {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b"}, + {file = "tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087"}, + {file = "tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd"}, + {file = "tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4"}, + {file = "tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a"}, + {file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"}, ] [[package]] name = "tomlkit" -version = "0.12.2" +version = "0.14.0" description = "Style preserving TOML library" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "tomlkit-0.12.2-py3-none-any.whl", hash = "sha256:eeea7ac7563faeab0a1ed8fe12c2e5a51c61f933f2502f7e9db0241a65163ad0"}, - {file = "tomlkit-0.12.2.tar.gz", hash = "sha256:df32fab589a81f0d7dc525a4267b6d7a64ee99619cbd1eeb0fae32c1dd426977"}, + {file = "tomlkit-0.14.0-py3-none-any.whl", hash = "sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680"}, + {file = "tomlkit-0.14.0.tar.gz", hash = "sha256:cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064"}, ] [[package]] name = "typing-extensions" -version = "4.8.0" -description = "Backported and Experimental Type Hints for Python 3.8+" +version = "4.15.0" +description = "Backported and Experimental Type Hints for Python 3.9+" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, - {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, + {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, + {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, +] + +[[package]] +name = "tzdata" +version = "2025.3" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +groups = ["dev"] +markers = "sys_platform == \"win32\"" +files = [ + {file = "tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1"}, + {file = "tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7"}, ] [[package]] name = "urllib3" -version = "2.0.7" +version = "2.6.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, - {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, + {file = "urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"}, + {file = "urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] +h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] +zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "virtualenv" -version = "20.24.6" +version = "20.36.1" description = "Virtual Python Environment builder" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "virtualenv-20.24.6-py3-none-any.whl", hash = "sha256:520d056652454c5098a00c0f073611ccbea4c79089331f60bf9d7ba247bb7381"}, - {file = "virtualenv-20.24.6.tar.gz", hash = "sha256:02ece4f56fbf939dbbc33c0715159951d6bf14aaf5457b092e4548e1382455af"}, + {file = "virtualenv-20.36.1-py3-none-any.whl", hash = "sha256:575a8d6b124ef88f6f51d56d656132389f961062a9177016a50e4f507bbcc19f"}, + {file = "virtualenv-20.36.1.tar.gz", hash = "sha256:8befb5c81842c641f8ee658481e42641c68b5eab3521d8e092d18320902466ba"}, ] [package.dependencies] distlib = ">=0.3.7,<1" -filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<4" +filelock = {version = ">=3.20.1,<4", markers = "python_version >= \"3.10\""} +platformdirs = ">=3.9.1,<5" +typing-extensions = {version = ">=4.13.2", markers = "python_version < \"3.11\""} [package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] [[package]] name = "watchdog" -version = "3.0.0" +version = "6.0.0" description = "Filesystem events monitoring" optional = false -python-versions = ">=3.7" -files = [ - {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41"}, - {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397"}, - {file = "watchdog-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96"}, - {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae"}, - {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9"}, - {file = "watchdog-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7"}, - {file = "watchdog-3.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674"}, - {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f"}, - {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc"}, - {file = "watchdog-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3"}, - {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3"}, - {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0"}, - {file = "watchdog-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8"}, - {file = "watchdog-3.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100"}, - {file = "watchdog-3.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346"}, - {file = "watchdog-3.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33"}, - {file = "watchdog-3.0.0-py3-none-win32.whl", hash = "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f"}, - {file = "watchdog-3.0.0-py3-none-win_amd64.whl", hash = "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c"}, - {file = "watchdog-3.0.0-py3-none-win_ia64.whl", hash = "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759"}, - {file = "watchdog-3.0.0.tar.gz", hash = "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9"}, +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"}, + {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"}, + {file = "watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3"}, + {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c"}, + {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"}, + {file = "watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c"}, + {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948"}, + {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860"}, + {file = "watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0"}, + {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c"}, + {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134"}, + {file = "watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b"}, + {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8"}, + {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a"}, + {file = "watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c"}, + {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881"}, + {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11"}, + {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa"}, + {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2"}, + {file = "watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a"}, + {file = "watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680"}, + {file = "watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f"}, + {file = "watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282"}, ] [package.extras] @@ -1576,129 +1903,126 @@ watchmedo = ["PyYAML (>=3.10)"] [[package]] name = "wcwidth" -version = "0.2.9" +version = "0.6.0" description = "Measures the displayed width of unicode strings in a terminal" optional = false -python-versions = "*" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "wcwidth-0.2.9-py2.py3-none-any.whl", hash = "sha256:9a929bd8380f6cd9571a968a9c8f4353ca58d7cd812a4822bba831f8d685b223"}, - {file = "wcwidth-0.2.9.tar.gz", hash = "sha256:a675d1a4a2d24ef67096a04b85b02deeecd8e226f57b5e3a72dbb9ed99d27da8"}, + {file = "wcwidth-0.6.0-py3-none-any.whl", hash = "sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad"}, + {file = "wcwidth-0.6.0.tar.gz", hash = "sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159"}, ] [[package]] name = "wheel" -version = "0.45.1" -description = "A built-package format for Python" +version = "0.46.3" +description = "Command line tool for manipulating wheel files" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248"}, - {file = "wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729"}, + {file = "wheel-0.46.3-py3-none-any.whl", hash = "sha256:4b399d56c9d9338230118d705d9737a2a468ccca63d5e813e2a4fc7815d8bc4d"}, + {file = "wheel-0.46.3.tar.gz", hash = "sha256:e3e79874b07d776c40bd6033f8ddf76a7dad46a7b8aa1b2787a83083519a1803"}, ] +[package.dependencies] +packaging = ">=24.0" + [package.extras] -test = ["pytest (>=6.0.0)", "setuptools (>=65)"] +test = ["pytest (>=6.0.0)", "setuptools (>=77)"] [[package]] name = "wrapt" -version = "1.15.0" +version = "1.17.3" description = "Module for decorators, wrappers and monkey patching." optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -files = [ - {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, - {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, - {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, - {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, - {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, - {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, - {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, - {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, - {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, - {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, - {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, - {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, - {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, - {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, - {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, - {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, - {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, - {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, - {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, -] - -[[package]] -name = "zipp" -version = "3.17.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false python-versions = ">=3.8" -files = [ - {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, - {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, +groups = ["dev"] +files = [ + {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04"}, + {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2"}, + {file = "wrapt-1.17.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c"}, + {file = "wrapt-1.17.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775"}, + {file = "wrapt-1.17.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd"}, + {file = "wrapt-1.17.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05"}, + {file = "wrapt-1.17.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418"}, + {file = "wrapt-1.17.3-cp310-cp310-win32.whl", hash = "sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390"}, + {file = "wrapt-1.17.3-cp310-cp310-win_amd64.whl", hash = "sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6"}, + {file = "wrapt-1.17.3-cp310-cp310-win_arm64.whl", hash = "sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18"}, + {file = "wrapt-1.17.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7"}, + {file = "wrapt-1.17.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85"}, + {file = "wrapt-1.17.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f"}, + {file = "wrapt-1.17.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311"}, + {file = "wrapt-1.17.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1"}, + {file = "wrapt-1.17.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5"}, + {file = "wrapt-1.17.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2"}, + {file = "wrapt-1.17.3-cp311-cp311-win32.whl", hash = "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89"}, + {file = "wrapt-1.17.3-cp311-cp311-win_amd64.whl", hash = "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77"}, + {file = "wrapt-1.17.3-cp311-cp311-win_arm64.whl", hash = "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a"}, + {file = "wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0"}, + {file = "wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba"}, + {file = "wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd"}, + {file = "wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828"}, + {file = "wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9"}, + {file = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396"}, + {file = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc"}, + {file = "wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe"}, + {file = "wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c"}, + {file = "wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6"}, + {file = "wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0"}, + {file = "wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77"}, + {file = "wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7"}, + {file = "wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277"}, + {file = "wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d"}, + {file = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa"}, + {file = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050"}, + {file = "wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8"}, + {file = "wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb"}, + {file = "wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16"}, + {file = "wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39"}, + {file = "wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235"}, + {file = "wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c"}, + {file = "wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b"}, + {file = "wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa"}, + {file = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7"}, + {file = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4"}, + {file = "wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10"}, + {file = "wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6"}, + {file = "wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58"}, + {file = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a"}, + {file = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067"}, + {file = "wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454"}, + {file = "wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e"}, + {file = "wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f"}, + {file = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056"}, + {file = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804"}, + {file = "wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977"}, + {file = "wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116"}, + {file = "wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6"}, + {file = "wrapt-1.17.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:70d86fa5197b8947a2fa70260b48e400bf2ccacdcab97bb7de47e3d1e6312225"}, + {file = "wrapt-1.17.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:df7d30371a2accfe4013e90445f6388c570f103d61019b6b7c57e0265250072a"}, + {file = "wrapt-1.17.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:caea3e9c79d5f0d2c6d9ab96111601797ea5da8e6d0723f77eabb0d4068d2b2f"}, + {file = "wrapt-1.17.3-cp38-cp38-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:758895b01d546812d1f42204bd443b8c433c44d090248bf22689df673ccafe00"}, + {file = "wrapt-1.17.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02b551d101f31694fc785e58e0720ef7d9a10c4e62c1c9358ce6f63f23e30a56"}, + {file = "wrapt-1.17.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:656873859b3b50eeebe6db8b1455e99d90c26ab058db8e427046dbc35c3140a5"}, + {file = "wrapt-1.17.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a9a2203361a6e6404f80b99234fe7fb37d1fc73487b5a78dc1aa5b97201e0f22"}, + {file = "wrapt-1.17.3-cp38-cp38-win32.whl", hash = "sha256:55cbbc356c2842f39bcc553cf695932e8b30e30e797f961860afb308e6b1bb7c"}, + {file = "wrapt-1.17.3-cp38-cp38-win_amd64.whl", hash = "sha256:ad85e269fe54d506b240d2d7b9f5f2057c2aa9a2ea5b32c66f8902f768117ed2"}, + {file = "wrapt-1.17.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc"}, + {file = "wrapt-1.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9"}, + {file = "wrapt-1.17.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d"}, + {file = "wrapt-1.17.3-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a"}, + {file = "wrapt-1.17.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139"}, + {file = "wrapt-1.17.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df"}, + {file = "wrapt-1.17.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b"}, + {file = "wrapt-1.17.3-cp39-cp39-win32.whl", hash = "sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81"}, + {file = "wrapt-1.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f"}, + {file = "wrapt-1.17.3-cp39-cp39-win_arm64.whl", hash = "sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f"}, + {file = "wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22"}, + {file = "wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0"}, ] -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - [metadata] -lock-version = "2.0" -python-versions = ">=3.8,<4.0" -content-hash = "7d7668644e2e70f4afaf036ee16bdcfacd97a0a8ab1883a26b36bd51342d8dae" +lock-version = "2.1" +python-versions = ">=3.10,<4.0" +content-hash = "54954ad33999a1552d185d7bcf4cfa1db1eaa41bb52cec957906c70c8442790e" diff --git a/pyproject.toml b/pyproject.toml index cdd69ec0..d521ee48 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,9 @@ -[tool.poetry] +[project] name = "photoshop-python-api" version = "0.24.1" description = "Python API for Photoshop." -homepage = "https://github.com/loonghao/photoshop-python-api" -repository = "https://github.com/loonghao/photoshop-python-api" -documentation = "https://photoshop-python-api.readthedocs.io/en/master/" keywords = ["python-api, photoshop-python-api", "photoshop", "python"] -authors = ["longhao "] +authors = [{name = "longhao", email = "hal.long@outlook.com"}] license = "MIT" readme = "README.md" classifiers = [ @@ -14,24 +11,32 @@ classifiers = [ "License :: OSI Approved :: MIT License", "Operating System :: Microsoft :: Windows", "Operating System :: Microsoft :: Windows :: Windows 10", + "Operating System :: Microsoft :: Windows :: Windows 11", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", ] +requires-python = ">=3.10,<4.0" +[project.urls] +homepage = "https://github.com/loonghao/photoshop-python-api" +repository = "https://github.com/loonghao/photoshop-python-api" +documentation = "https://photoshop-python-api.readthedocs.io/en/master/" + +[tool.poetry] packages = [ { include = "photoshop" }, ] + [tool.poetry.build] generate-setup-file = false [tool.poetry.dependencies] -python = ">=3.8,<4.0" -wheel = "^0.45.0" -comtypes = "^1.1.11" +wheel = "^0.46.3" +comtypes = "^1.4.15" [tool.poetry.group.dev.dependencies] commitizen = "^2.17.8" @@ -39,9 +44,9 @@ pre-commit = "^2.13.0" codecov = "^2.1.11" pylint = "^2.8.2" isort = "^5.8.0" -pytest = "^8.0.0" +pytest = "^9.0.2" flake8 = "^4.0.0" -mypy = "^1.0" +mypy = "^1.19.1" coverage = "^7.0.0" mkdocs = "^1.2.2" mkdocs-git-revision-date-plugin = "^0.3.1" @@ -119,3 +124,11 @@ force_single_line = true # All project unrelated unknown imports belong to third-party. default_section = "THIRDPARTY" skip_glob = "*/docs/conf.py" + +[tool.ruff] +line-length = 120 + +[tool.ruff.lint.isort] +lines-after-imports = 2 +lines-between-types = 1 +known-first-party = ["photoshop"] \ No newline at end of file diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/manual_test/manual_test_application.py b/test/manual_test/manual_test_application.py index 26296062..b77426ab 100644 --- a/test/manual_test/manual_test_application.py +++ b/test/manual_test/manual_test_application.py @@ -1,4 +1,5 @@ """""" + # Import third-party modules import pytest @@ -6,6 +7,7 @@ from photoshop.api import Application from photoshop.api import EventID from photoshop.api import SolidColor +from photoshop.api.enumerations import FontSize class TestApplication: @@ -45,7 +47,10 @@ def test_get_background_color(self): def test_set_background_color(self, photoshop_app): self.app.backgroundColor.rgb.green = 0 - assert self.app.backgroundColor.rgb.green == photoshop_app.backgroundColor.rgb.green + assert ( + self.app.backgroundColor.rgb.green + == photoshop_app.backgroundColor.rgb.green + ) def test_build(self): assert self.app.build == "21.0 (20191018.r.37 2019/10/18: 614690fb487)" @@ -151,6 +156,7 @@ def test_get_version(self): assert self.app.version == "21.1.2" def test_windowsFileTypes(self): + assert isinstance(self.app.windowsFileTypes, tuple) assert len(self.app.windowsFileTypes) >= 100 def test_batch(self): @@ -168,9 +174,6 @@ def test_changeProgressText(self): def test_charIDToTypeID(self): assert self.app.charIDToTypeID("Type") == "1417244773" - def test_compareWithNumbers(self): - assert self.app.compareWithNumbers(20, 1) - def test_do_action(self): self.app.doAction("Vignette (selection)", "Default Actions") @@ -219,3 +222,16 @@ def test_typeIDToStringID(self): def test_updateProgress(self): assert self.app.updateProgress("Done", "total") + + def test_ui_text_font_size(self): + prefs = self.app.preferences + initial_font_size = prefs.textFontSize + try: + prefs.textFontSize = FontSize.Large + assert prefs.textFontSize == FontSize.Large + prefs.textFontSize = FontSize.Medium + assert prefs.textFontSize == FontSize.Medium + prefs.textFontSize = FontSize.Small + assert prefs.textFontSize == FontSize.Small + finally: + prefs.textFontSize = initial_font_size diff --git a/test/manual_test/manual_test_documents.py b/test/manual_test/manual_test_documents.py new file mode 100644 index 00000000..c800099f --- /dev/null +++ b/test/manual_test/manual_test_documents.py @@ -0,0 +1,29 @@ +from math import isclose + +import pytest + +from photoshop.api.application import Application + + +class TestNewDocument: + """Test various parts of the API in a new document.""" + + @pytest.fixture(autouse=True) + def setup(self): + """Setup for current test.""" + self.app = Application() + self.docs = self.app.documents + + def test_create_document(self): + doc_name = "test_document" + w = 22.3 + h = 47 + res = 55.8 + doc = self.docs.add(22.3, 47, resolution=55.8, name=doc_name) + try: + assert doc.name == doc_name + assert doc.width == int(w) + assert doc.height == h + assert isclose(doc.resolution, res, abs_tol=0.01) + finally: + doc.close() diff --git a/test/manual_test/manual_test_new_document.py b/test/manual_test/manual_test_new_document.py new file mode 100644 index 00000000..4d681018 --- /dev/null +++ b/test/manual_test/manual_test_new_document.py @@ -0,0 +1,116 @@ +from pathlib import Path +from tempfile import TemporaryDirectory + +import pytest + +from photoshop import Session +from photoshop.api._artlayer import ArtLayer +from photoshop.api._document import Document +from photoshop.api._layerSet import LayerSet +from photoshop.api.enumerations import LayerKind + + +class TestNewDocument: + """Test various parts of the API in a new document.""" + + @pytest.fixture(autouse=True) + def setup(self): + """Setup for current test.""" + self.session = Session(action="new_document", auto_close=True) + self.session.run_action() + self.app = self.session.app + self.doc = self.session.active_document + yield + self.session.close() + + def test_active_layer(self): + layer_1 = self.doc.artLayers.add() + layer_2 = self.doc.artLayers.add() + self.doc.activeLayer = layer_1 + assert layer_1.id == self.doc.activeLayer.id + self.doc.activeLayer = layer_2 + assert layer_2.id == self.doc.activeLayer.id + + def test_channel_histogram(self): + channel = self.doc.activeChannels[0] + assert isinstance(channel.histogram, tuple) + + def test_document_info_keywords(self): + doc_info = self.doc.info + assert doc_info.keywords is None + doc_info.keywords = ["foo", "bar"] + assert isinstance(doc_info.keywords, tuple) + assert doc_info.keywords == ("foo", "bar") + tuple_keywords = ("key", "word", "?") + doc_info.keywords = tuple_keywords + assert doc_info.keywords == tuple_keywords + + def test_selection(self): + self.doc.resizeImage(500, 500) + assert self.doc.width == 500 + assert self.doc.height == 500 + selection = self.doc.selection + # If the selection touches the document's borders it might not get contracted + selection.select(((10, 10), (200, 10), (200, 200), (10, 200))) + bounds = selection.bounds + assert isinstance(bounds, tuple) + assert isinstance(bounds[0], float) + selection.contract(20.5) + contracted_bounds = selection.bounds + assert bounds[0] < contracted_bounds[0] + selection.expand(10) + expanded_bounds = selection.bounds + assert expanded_bounds[0] < contracted_bounds[0] + + def test_paths(self): + with TemporaryDirectory(prefix="photoshop_python_api_") as tmpdir: + doc_path = Path(tmpdir, "test_doc.psd") + self.doc.saveAs(str(doc_path)) + assert isinstance(self.doc.saved, bool) + assert self.doc.saved + assert self.doc.fullName == doc_path + + def test_layer_kind(self): + background_layer = self.doc.artLayers[0] + assert isinstance(background_layer, ArtLayer) + layer_kind = background_layer.kind + layer_set_1 = self.doc.layerSets.add() + self.doc.activeLayer = layer_set_1 + + # This used to fail in version 0.24.1 + assert background_layer.kind == layer_kind + + layer_1 = self.doc.artLayers.add() + layer_1.kind = LayerKind.TextLayer + assert layer_1.kind == LayerKind.TextLayer + + def test_layer_iteration(self): + layer_set = self.doc.layerSets.add() + layers = list(self.doc.layers) + assert any((layer for layer in layers if isinstance(layer, LayerSet))) + assert any((layer for layer in layers if isinstance(layer, ArtLayer))) + + layer_set.artLayers.add() + layer_set.layerSets.add() + assert any((layer for layer in layer_set if isinstance(layer, LayerSet))) + assert any((layer for layer in layer_set if isinstance(layer, ArtLayer))) + + def test_layer_parent(self): + layer_set = self.doc.layerSets.add() + assert isinstance(layer_set.parent, Document) + sub_layer = layer_set.artLayers.add() + assert isinstance(sub_layer.parent, LayerSet) + + def test_layer_access(self): + for collection in (self.doc.artLayers, self.doc.layerSets): + names = ("l_1", "l_2") + layers: list[ArtLayer | LayerSet] = [] + for name in names: + layer = collection.add() + layer.name = name + layers.append(layer) + for name, layer in zip(names, layers): + assert collection[name].id == layer.id + got_layer = collection.getByName(name) + assert got_layer + assert got_layer.id == layer.id diff --git a/test/manual_test/manual_test_path_items.py b/test/manual_test/manual_test_path_items.py new file mode 100644 index 00000000..1e812b37 --- /dev/null +++ b/test/manual_test/manual_test_path_items.py @@ -0,0 +1,78 @@ +from typing import Sequence + +import pytest + +from photoshop.api.enumerations import PointKind, ShapeOperation, ToolType +from photoshop.api.path_item import PathItem +from photoshop.api.path_point_info import PathPointInfo +from photoshop.api.solid_color import SolidColor +from photoshop.api.sub_path_info import SubPathInfo +from photoshop.session import Session + + +class TestPathItems: + """Test path items.""" + + @pytest.fixture(autouse=True) + def setup(self): + self.session = Session(action="new_document", auto_close=True) + self.session.run_action() + self.app = self.session.app + self.doc = self.session.active_document + + self.point_anchors = ((0, 0.0), (10.1, 0.0), (5, 5)) + + self.path_item = self._create_path("test_path", self.point_anchors) + + yield + self.session.close() + + def _create_path( + self, name: str, point_anchors: Sequence[tuple[float, float]] + ) -> PathItem: + point_infos: list[PathPointInfo] = [ + PathPointInfo(anchor=anchor) for anchor in point_anchors + ] + + last_anchor = point_anchors[-1] + left = (last_anchor[0] + 1, last_anchor[1]) + right = (last_anchor[0], last_anchor[1] - 1) + + last_point = point_infos[-1] + last_point.kind = PointKind.SmoothPoint + last_point.leftDirection = left + last_point.rightDirection = right + + sub_path = SubPathInfo(entire_sub_path=point_infos) + + return self.doc.pathItems.add(name=name, entire_path=(sub_path,)) + + def test_path_item(self) -> None: + for sub_path in self.path_item.subPathItems: + assert ShapeOperation(sub_path.operation) + assert isinstance(sub_path.closed, bool) + for point in sub_path.pathPoints: + assert isinstance(point.anchor, tuple) + assert len(point.anchor) == 2 + assert PointKind(point.kind) + solid_color = SolidColor() + solid_color.rgb.red = 100 + solid_color.rgb.green = 100 + solid_color.rgb.blue = 100 + self.path_item.fillPath(solid_color) + self.path_item.strokePath(ToolType.Blur) + + def test_path_removal(self) -> None: + n_paths = 5 + for i in range(n_paths): + self._create_path(f"test_{i}", self.point_anchors) + + path_items = self.doc.pathItems + + path_items_len = len(path_items) + assert path_items_len >= n_paths + path_items[0].remove() + path_items["test_3"].remove() + assert len(path_items) == path_items_len - 2 + path_items.removeAll() + assert len(path_items) == 0 diff --git a/test/manual_test/manual_test_text_item.py b/test/manual_test/manual_test_text_item.py index 08f1b120..62fdf8a4 100644 --- a/test/manual_test/manual_test_text_item.py +++ b/test/manual_test/manual_test_text_item.py @@ -1,10 +1,12 @@ """""" + # Import third-party modules import pytest # Import local modules from photoshop import Session -from photoshop.api.enumerations import TextType +from photoshop.api._artlayer import ArtLayer +from photoshop.api.enumerations import Justification, TextType class TestTextItem: @@ -14,11 +16,14 @@ class TestTextItem: @pytest.fixture(autouse=True) def setup(self, psd_file): """Setup for current test.""" - self.session = Session(file_path=psd_file("textitem"), action="open", auto_close=True) + self.session = Session( + file_path=psd_file("textitem"), action="open", auto_close=True + ) self.session.run_action() doc = self.session.active_document layer = doc.activeLayer - self.text_item = layer.textItem() # -> TextItem + assert isinstance(layer, ArtLayer) + self.text_item = layer.textItem # -> TextItem yield # self.session.close() @@ -72,8 +77,8 @@ def test_justification(self): assert self.text_item.justification == 1 def test_set_justification(self): - self.text_item.justification = 2 - assert self.text_item.justification == 2 + self.text_item.justification = Justification.Center + assert self.text_item.justification == Justification.Center def test_kind(self): assert self.text_item.kind == 1 @@ -95,3 +100,6 @@ def test_size(self): def test_change_size(self): self.text_item.size = 20 assert self.text_item.size == 20.0 + + def test_width(self): + assert isinstance(self.text_item.width, float)