Skip to content

Objects

OBJECT UTILITIES

PhotoshopHandler

Bases: Application

Wrapper for the Photoshop Application object to maintain a single instance globally, caching mechanisms, app instance refresh, etc.

Source code in src/utils/objects.py
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
class PhotoshopHandler(Application):
    """
    Wrapper for the Photoshop Application object to maintain a single instance globally,
    caching mechanisms, app instance refresh, etc.
    """
    DIMS_1200 = (3264, 4440)
    DIMS_800 = (2176, 2960)
    DIMS_600 = (1632, 2220)
    _instance = None

    def __new__(cls, version: Optional[str] = None) -> 'PhotoshopHandler':
        """Always return the same Photoshop Application instance on successive calls."""
        # Use existing Photoshop instance or create new one
        if cls._instance is None:
            try:
                cls._instance = super().__new__(cls)
            except PS_EXCEPTIONS:
                cls._instance = super(Photoshop, cls).__new__(cls)
        # Establish the version initially passed and return instance
        cls._instance._version = version
        return cls._instance

    """
    CLASS METHODS
    """

    def refresh_app(self):
        """Replace the existing Photoshop Application instance with a new one."""
        if not self.is_running():
            try:
                # Load Photoshop and default preferences
                super(PhotoshopHandler, self).__init__(version=self._version)
                self.preferences.rulerUnits = Units.Pixels
                self.preferences.typeUnits = Units.Points
            except Exception as e:
                # Photoshop is either busy or unresponsive
                return OSError(get_photoshop_error_message(e))
        return

    @classmethod
    def is_running(cls) -> bool:
        """Check if the current Photoshop Application instance is still valid."""
        with suppress(Exception):
            _ = cls._instance.version
            return True
        return False

    """
    CONVERTING CHARACTER ID
    """

    @cache
    def charIDToTypeID(self, index: str) -> int:
        """
        Caching handler for charIDToTypeID.
        @param index: ID to convert to TypeID.
        """
        return super().charIDToTypeID(index)

    @cache
    def CharIDToTypeID(self, index: str) -> int:
        """Utility definition redirecting to charIDToTypeID."""
        return self.charIDToTypeID(index)

    @cache
    def cID(self, index: str) -> int:
        """Shorthand for charIDToTypeID."""
        return self.charIDToTypeID(index)

    @cache
    def typeIDToCharID(self, index: int) -> str:
        """
        Caching handler for typeIDToCharID.
        @param index: ID to convert to CharID.
        """
        return super().typeIDToCharID(index)

    @cache
    def t2c(self, index: int) -> str:
        """Shorthand for typeIDToCharID."""
        return self.typeIDToCharID(index)

    """
    CONVERTING STRING ID
    """

    @cache
    def stringIDToTypeID(self, index: str) -> int:
        """
        Caching handler for stringIDToTypeID.
        @param index: ID to convert to TypeID.
        """
        return super().stringIDToTypeID(index)

    @cache
    def StringIDToTypeID(self, index: str) -> int:
        """Utility definition redirecting to stringIDTotypeID."""
        return self.stringIDToTypeID(index)

    @cache
    def sID(self, index: str) -> int:
        """Shorthand for stringIDToTypeID."""
        return self.stringIDToTypeID(index)

    @cache
    def typeIDToStringID(self, index: int) -> str:
        """
        Caching handler for typeIDToStringID.
        @param index: ID to convert to StringID.
        """
        return super().typeIDToStringID(index)

    @cache
    def t2s(self, index: int) -> str:
        """Shorthand for typeIDToStringID."""
        return self.typeIDToStringID(index)

    """
    EXECUTING ACTION DESCRIPTORS
    """

    def executeAction(
            self, event_id: int,
            descriptor: ActionDescriptor,
            dialogs: DialogModes = DialogModes.DisplayNoDialogs
    ) -> Any:
        """
        Middleware to allow all dialogs when an error occurs upon calling executeAction in development mode.
        @param event_id: Action descriptor event ID.
        @param descriptor: Main action descriptor tree to execute.
        @param dialogs: DialogMode which governs whether to display dialogs.
        """
        if not ENV.PS_ERROR_DIALOG:
            return super().executeAction(event_id, descriptor, dialogs)
        # Allow error dialogs within development environment
        return super().executeAction(event_id, descriptor, DialogModes.DisplayErrorDialogs)

    def ExecuteAction(
            self, event_id: int,
            descriptor: ActionDescriptor,
            dialogs: DialogModes = DialogModes.DisplayNoDialogs
    ) -> Any:
        """Utility definition rerouting to original executeAction function."""
        self.executeAction(event_id, descriptor, dialogs)

    """
    VERSION CHECKS
    """

    @cache
    def supports_target_text_replace(self) -> bool:
        """
        Checks if Photoshop version supports targeted text replacement.
        @return: True if supported.
        """
        return self.version_meets_requirement('22.0.0')

    @cache
    def supports_webp(self) -> bool:
        """
        Checks if Photoshop version supports WEBP files.
        @return: True if supported.
        """
        return self.version_meets_requirement('23.2.0')

    @cache
    def supports_generative_fill(self) -> bool:
        """
        Checks if Photoshop version supports Generative Fill.
        @return: True if supported.
        """
        return self.version_meets_requirement('24.6.0')

    def version_meets_requirement(self, value: str) -> bool:
        """
        Checks if Photoshop version meets or exceeds required value.
        @return: True if supported.
        """
        if parse(self.version) >= parse(value):
            return True
        return False

    """
    DIMENSION CHECKS
    """

    def scale_by_dpi(self, value: Union[int, float]) -> int:
        """
        Scales a value by comparing document DPI to ideal DPI.
        @param value: Integer or float value to adjust by DPI ratio.
        @return: Adjusted value as an integer.
        """
        return int((self.activeDocument.width / 3264) * value)

CharIDToTypeID(index) cached

Utility definition redirecting to charIDToTypeID.

Source code in src/utils/objects.py
93
94
95
96
@cache
def CharIDToTypeID(self, index: str) -> int:
    """Utility definition redirecting to charIDToTypeID."""
    return self.charIDToTypeID(index)

ExecuteAction(event_id, descriptor, dialogs=DialogModes.DisplayNoDialogs)

Utility definition rerouting to original executeAction function.

Source code in src/utils/objects.py
171
172
173
174
175
176
177
def ExecuteAction(
        self, event_id: int,
        descriptor: ActionDescriptor,
        dialogs: DialogModes = DialogModes.DisplayNoDialogs
) -> Any:
    """Utility definition rerouting to original executeAction function."""
    self.executeAction(event_id, descriptor, dialogs)

StringIDToTypeID(index) cached

Utility definition redirecting to stringIDTotypeID.

Source code in src/utils/objects.py
128
129
130
131
@cache
def StringIDToTypeID(self, index: str) -> int:
    """Utility definition redirecting to stringIDTotypeID."""
    return self.stringIDToTypeID(index)

__new__(version=None)

Always return the same Photoshop Application instance on successive calls.

Source code in src/utils/objects.py
44
45
46
47
48
49
50
51
52
53
54
def __new__(cls, version: Optional[str] = None) -> 'PhotoshopHandler':
    """Always return the same Photoshop Application instance on successive calls."""
    # Use existing Photoshop instance or create new one
    if cls._instance is None:
        try:
            cls._instance = super().__new__(cls)
        except PS_EXCEPTIONS:
            cls._instance = super(Photoshop, cls).__new__(cls)
    # Establish the version initially passed and return instance
    cls._instance._version = version
    return cls._instance

cID(index) cached

Shorthand for charIDToTypeID.

Source code in src/utils/objects.py
 98
 99
100
101
@cache
def cID(self, index: str) -> int:
    """Shorthand for charIDToTypeID."""
    return self.charIDToTypeID(index)

charIDToTypeID(index) cached

Caching handler for charIDToTypeID. @param index: ID to convert to TypeID.

Source code in src/utils/objects.py
85
86
87
88
89
90
91
@cache
def charIDToTypeID(self, index: str) -> int:
    """
    Caching handler for charIDToTypeID.
    @param index: ID to convert to TypeID.
    """
    return super().charIDToTypeID(index)

executeAction(event_id, descriptor, dialogs=DialogModes.DisplayNoDialogs)

Middleware to allow all dialogs when an error occurs upon calling executeAction in development mode. @param event_id: Action descriptor event ID. @param descriptor: Main action descriptor tree to execute. @param dialogs: DialogMode which governs whether to display dialogs.

Source code in src/utils/objects.py
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
def executeAction(
        self, event_id: int,
        descriptor: ActionDescriptor,
        dialogs: DialogModes = DialogModes.DisplayNoDialogs
) -> Any:
    """
    Middleware to allow all dialogs when an error occurs upon calling executeAction in development mode.
    @param event_id: Action descriptor event ID.
    @param descriptor: Main action descriptor tree to execute.
    @param dialogs: DialogMode which governs whether to display dialogs.
    """
    if not ENV.PS_ERROR_DIALOG:
        return super().executeAction(event_id, descriptor, dialogs)
    # Allow error dialogs within development environment
    return super().executeAction(event_id, descriptor, DialogModes.DisplayErrorDialogs)

is_running() classmethod

Check if the current Photoshop Application instance is still valid.

Source code in src/utils/objects.py
73
74
75
76
77
78
79
@classmethod
def is_running(cls) -> bool:
    """Check if the current Photoshop Application instance is still valid."""
    with suppress(Exception):
        _ = cls._instance.version
        return True
    return False

refresh_app()

Replace the existing Photoshop Application instance with a new one.

Source code in src/utils/objects.py
60
61
62
63
64
65
66
67
68
69
70
71
def refresh_app(self):
    """Replace the existing Photoshop Application instance with a new one."""
    if not self.is_running():
        try:
            # Load Photoshop and default preferences
            super(PhotoshopHandler, self).__init__(version=self._version)
            self.preferences.rulerUnits = Units.Pixels
            self.preferences.typeUnits = Units.Points
        except Exception as e:
            # Photoshop is either busy or unresponsive
            return OSError(get_photoshop_error_message(e))
    return

sID(index) cached

Shorthand for stringIDToTypeID.

Source code in src/utils/objects.py
133
134
135
136
@cache
def sID(self, index: str) -> int:
    """Shorthand for stringIDToTypeID."""
    return self.stringIDToTypeID(index)

scale_by_dpi(value)

Scales a value by comparing document DPI to ideal DPI. @param value: Integer or float value to adjust by DPI ratio. @return: Adjusted value as an integer.

Source code in src/utils/objects.py
220
221
222
223
224
225
226
def scale_by_dpi(self, value: Union[int, float]) -> int:
    """
    Scales a value by comparing document DPI to ideal DPI.
    @param value: Integer or float value to adjust by DPI ratio.
    @return: Adjusted value as an integer.
    """
    return int((self.activeDocument.width / 3264) * value)

stringIDToTypeID(index) cached

Caching handler for stringIDToTypeID. @param index: ID to convert to TypeID.

Source code in src/utils/objects.py
120
121
122
123
124
125
126
@cache
def stringIDToTypeID(self, index: str) -> int:
    """
    Caching handler for stringIDToTypeID.
    @param index: ID to convert to TypeID.
    """
    return super().stringIDToTypeID(index)

supports_generative_fill() cached

Checks if Photoshop version supports Generative Fill. @return: True if supported.

Source code in src/utils/objects.py
199
200
201
202
203
204
205
@cache
def supports_generative_fill(self) -> bool:
    """
    Checks if Photoshop version supports Generative Fill.
    @return: True if supported.
    """
    return self.version_meets_requirement('24.6.0')

supports_target_text_replace() cached

Checks if Photoshop version supports targeted text replacement. @return: True if supported.

Source code in src/utils/objects.py
183
184
185
186
187
188
189
@cache
def supports_target_text_replace(self) -> bool:
    """
    Checks if Photoshop version supports targeted text replacement.
    @return: True if supported.
    """
    return self.version_meets_requirement('22.0.0')

supports_webp() cached

Checks if Photoshop version supports WEBP files. @return: True if supported.

Source code in src/utils/objects.py
191
192
193
194
195
196
197
@cache
def supports_webp(self) -> bool:
    """
    Checks if Photoshop version supports WEBP files.
    @return: True if supported.
    """
    return self.version_meets_requirement('23.2.0')

t2c(index) cached

Shorthand for typeIDToCharID.

Source code in src/utils/objects.py
111
112
113
114
@cache
def t2c(self, index: int) -> str:
    """Shorthand for typeIDToCharID."""
    return self.typeIDToCharID(index)

t2s(index) cached

Shorthand for typeIDToStringID.

Source code in src/utils/objects.py
146
147
148
149
@cache
def t2s(self, index: int) -> str:
    """Shorthand for typeIDToStringID."""
    return self.typeIDToStringID(index)

typeIDToCharID(index) cached

Caching handler for typeIDToCharID. @param index: ID to convert to CharID.

Source code in src/utils/objects.py
103
104
105
106
107
108
109
@cache
def typeIDToCharID(self, index: int) -> str:
    """
    Caching handler for typeIDToCharID.
    @param index: ID to convert to CharID.
    """
    return super().typeIDToCharID(index)

typeIDToStringID(index) cached

Caching handler for typeIDToStringID. @param index: ID to convert to StringID.

Source code in src/utils/objects.py
138
139
140
141
142
143
144
@cache
def typeIDToStringID(self, index: int) -> str:
    """
    Caching handler for typeIDToStringID.
    @param index: ID to convert to StringID.
    """
    return super().typeIDToStringID(index)

version_meets_requirement(value)

Checks if Photoshop version meets or exceeds required value. @return: True if supported.

Source code in src/utils/objects.py
207
208
209
210
211
212
213
214
def version_meets_requirement(self, value: str) -> bool:
    """
    Checks if Photoshop version meets or exceeds required value.
    @return: True if supported.
    """
    if parse(self.version) >= parse(value):
        return True
    return False

Singleton

Bases: type

Maintains a single instance of any child class.

Source code in src/utils/objects.py
24
25
26
27
28
29
30
31
class Singleton(type):
    """Maintains a single instance of any child class."""
    _instances: dict = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]