Giter Site home page Giter Site logo

shotgunsoftware / tk-framework-adobe Goto Github PK

View Code? Open in Web Editor NEW
10.0 22.0 8.0 46.51 MB

Foundation Tech for all Adobe Integrations

Home Page: https://developer.shotgridsoftware.com/tk-framework-adobe/

License: Other

CSS 3.26% HTML 1.70% JavaScript 57.13% Python 35.63% Makefile 0.85% Batchfile 1.42%

tk-framework-adobe's Introduction

VFX Platform Python Build Status Code style: black Linting

tk-framework-adobe

A framework for Adobe engines

Development

How to set up your development environment

  • To setup the development environment for this project, you will need to obtain the ZXPSignCmd tool provided by Adobe.
  • Once you have logged in using your existing Adobe user account, download the CC Extensions Signing Toolkit, which will provide you with the necessary executable.
  • If you are developing on a Mac, please set all necessary variables in dev/env.mk.
  • If you are developing on Windows, please set all necessary variables in dev\env.cmd

This is what the env file should look like:

TARGET_VERSION=1.1.3 # Make sure this matches the tk-framework-adobe version you will be releasing

TKCORE_VERSION=0.19.19  # This core version is expected to exist in your bundle cache

ZXP_SIGN_TOOL=/path/to/bin/ZXPSignCmd

CERTIFICATE_FILE=/path/to/file/location/cert.p12

CERTIFICATE_PASS=<Make up your own secure password>
CERT_COUNTRY=<Two Character Country Code>
CERT_STATE=<Two Character State or Province Code>
CERT_ORG=Autodesk
CERT_CN=SGTK

Follow this link to find out where your bundle cache is located.

To install the CEP extension for testing without signing:

cd path/to/tk-adobe-framework
cd dev
make test

To sign the CEP extension

cd path/to/tk-adobe-framework
cd dev
make sign

To create a certificate for use when signing the CEP extension

cd path/to/tk-adobe-framework
cd dev
make create_certificate

Note: In the case where the configured CERTIFICATE_FILE does not exist, the create_certificate command will be automatically run as part of the sign target.

To remove the latest signed zxp file

cd path/to/tk-adobe-framework
cd dev
make clean

Notes on editing the env files (env.mk and env.cmd)

Changes to the env files (env.mk and env.cmd) will typically not be tracked in git. The information contained in these files is specific to a particular development environment, so tracking changes to that data in git is undesirable.

If you need to make changes to these files, you can use the following commands:

git update-index --no-skip-worktree dev/env.mk dev/env.cmd
git add dev\env.*
git commit -m "your message"
git update-index --skip-worktree dev/env.mk dev/env.cmd

Please be aware that these files contain potentially-sensitive information, such as a certificate password. When making changes to these files and pushing them to a git repository, be sure that you've removed any data that might be considered confidential.

tk-framework-adobe's People

Contributors

000paradox000 avatar barbara-darkshot avatar carlos-villavicencio-adsk avatar dependabot[bot] avatar eshokrgozar avatar jfboismenu avatar juanburgosautoglb avatar julien-lang avatar manneohrstrom avatar martinminsel avatar norbermv avatar pscadding avatar shaynacohen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tk-framework-adobe's Issues

Pass on ADOBE environment variables.

Summary

We should do a pass on the various environment variables to ensure they are in the right place. I am seeing a lot of stuff on the engine level that looks like it likely belongs at the framework level and in some cases it is defined in both the engine and the framework, which is bad.

The goal: Get as many of the environment variables into the framework as possible. Update the documentation to reflect the new state (wiki + sphinx, adobe fw, AE engine, PS engine).

Examples of duplicate definitions

  • It looks like the SHOTGUN_ADOBE_NETWORK_DEBUG environment is defined both in the engine and in the framework - we should refactor this to be less leaky. I think we should drop the network_debug flag and the only way to control the debug state is through the SHOTGUN_ADOBE_NETWORK_DEBUG env var, which is only accessed from the fw.
  • I am seeing a similar situation for SHOTGUN_ADOBE_PYTHON.

Well defined public interface for `tk_framework_adobe` module

Using the adobe fw results in non-standard imports:

image

Note now our other frameworks are imported like this:

shotgun_settings = sgtk.platform.import_framework("tk-framework-shotgunutils", "settings")

Whereas the adobe fw is imported like this:

adobe_bridge = sgtk.platform.import_framework(
    "tk-framework-adobe",
    "tk_framework_adobe.adobe_bridge"
)

    win_32_api = sgtk.platform.import_framework(
        "tk-framework-adobe",
        "tk_framework_adobe_utils.win_32_api"
    )

We need to get parity with other frameworks and define a strict interface for the adobe framework modules inside __init__.py - for alignment with other patterns in tk, but more importantly to ensure there is a clear public interface which will allow for refactoring in the future.

Framework interfaces should only expose the minimum public interface that we commit to officially support.

Documentation

Note how the docs for the shotgun utils are generated to look like this:

image

Currently, the docs for the adobe fw look like this:

image

As part of this work, we want them to align in structure with how the shotgun utils ones above look, e.g it should just say adobe_bridge.AdobeBridge.

Docstrings, linting and double quotes

Comments from CR:

  • Do a pass to make sure the code lints correctly (the flake8 file we are using can be found here.
  • Make sure we have docstrings with params for all methods (including tests)
  • No single quotes please!

Pass on quoting and linting

Do another pass on quoting and linting for the AE engine, the PS engine and the adobe FW:

  • Make sure we don't have any single quotes for strings.
  • Make sure that the code passes the linting rules defined by our flake8 config

Photoshop: AdobeBridge websocket communication interrupted during long, blocking operations in Photoshop

Summary

Invoking the Photoshop API with engine.adobe can cause the AdobeBridge websocket communication to be interrupted. This only seems to happen during long, blocking operations that cause a progress bar in Photoshop to appear such as saving and loading large files from network storage, or saving files with high compression settings.

Note that the original operation (File Save, File Open, etc.) does complete successfully, but because it's immediately followed up by an error that crashes the plugin, you can't do anything else afterwards.

Impact

This bug causes the SGTK plugin to fail during vital operations such as saving and loading files. It can often become a blocking issue that prevents artists from publishing work.

Traceback

Note: line numbers will be slightly off: I've inserted a lot of logging messages to my local files for debugging.

[49446 ERROR sgtk.env.project.tk-photoshopcc] Traceback (most recent call last):
  File ".../tk_multi_pythonconsole/1.3.0._build1/5322/a/ext/python/app/input_widget.py", line 246, in execute
    exec(python_code, self._locals, self._locals)
  File "python input", line 13, in <module>
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/python/tk_framework_adobe/rpc/proxy.py", line 232, in __call__
    parent=self._parent,
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/python/tk_framework_adobe/rpc/communicator.py", line 300, in rpc_call
    wrapper_class=ProxyWrapper,
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/python/tk_framework_adobe/rpc/communicator.py", line 760, in __run_rpc_command
    results = self._wait_for_response(payload["id"])
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/python/tk_framework_adobe/adobe_bridge.py", line 44, in wrapper
    result = func(*args, **kwargs)
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/python/tk_framework_adobe/adobe_bridge.py", line 440, in _wait_for_response
    return super(AdobeBridge, self)._wait_for_response(uid)
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/python/tk_framework_adobe/rpc/communicator.py", line 655, in _wait_for_response
    self.wait(single_loop=True, process_events=False)
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/python/tk_framework_adobe/rpc/communicator.py", line 523, in wait
    process_events=process_events,
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/python/tk_framework_adobe/rpc/communicator.py", line 245, in process_new_messages
    self._io._process_packets()
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/pkgs/socketIO_client_nexus/__init__.py", line 276, in _process_packets
    for engineIO_packet in self._transport.recv_packet():
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/pkgs/socketIO_client_nexus/transports.py", line 158, in recv_packet
    packet_text)
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/pkgs/socketIO_client_nexus/parsers.py", line 96, in parse_packet_text
    packet_type = int(get_character(packet_text, 0))
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/pkgs/socketIO_client_nexus/symmetries.py", line 33, in get_character
    return chr(get_byte(x, index))
  File ".../tk_framework_adobe/1.1.7/411f/a/ext/pkgs/socketIO_client_nexus/symmetries.py", line 29, in get_byte
    return indexbytes(x, index)
    
IndexError: index out of range

Video

Here is a video of me saving a PNG file with the maximum compression settings.

video.mp4

Steps to reproduce

Reproducing the error can be tricky. I can reliably reproduce the error on MacOS, but not on Windows. Furthermore, not all large files produce the error. However, once I have a file that produces the error, it is consistently reproducible with the same steps.

  1. Open a large PSD file that will take a long time to save. I have uploaded the file from the video above to Google Drive: test.psd
  2. Open the ShotGrid Python Console
  3. Use the Python API to save the file as a PNG with maximum compression settings. Example code:
from pathlib import Path


dst = Path.home() / "Desktop" / "save_test.png"  # Save file to Desktop

png_file = engine.adobe.File(dst.as_posix())
png_options = engine.adobe.PNGSaveOptions()
png_options.interlaced = False
png_options.compression = 9  # Highest compression value, most likely to cause Photoshop to hang

document = engine.adobe.get_active_document()
document.saveAs(png_file, png_options, True)

If you get an IndexError in the Python console, followed by the ShotGrid Adobe panel shutdown, you have reproduced the error successfully.

Environment

Toolkit environment:

  • tk-framework-adobe v1.1.7
  • tk-photoshopcc v1.9.4
  • tk-core v0.20.13

Python version:

  • Python 3.7.13

Photoshop version:

  • Photoshop 2022 (v23.5.4)

System information:
I have reproduced the error on both of the following systems:

  • MacBook Pro, Apple M1 Pro, macOS Monterey v12.6.3
  • MacBook Pro, Intel Core i9, macOS Ventura v13.2.1

What I've tried

I have read the ShotGrid community forum post for
Adobe engine crashing on long operations
. While this issue feels related, and indeed presents some of the same symptoms, I could not get any of the solutions to work.

My understanding is that disabling the heartbeat should be the most "forceful" way of circumventing some of these issues. I have tried saving with the heartbeat_disabled context manager, but the issue persists:

with engine.heartbeat_disabled():
    document.saveAs(png_file, png_options, True)

My investigation

(This is going to be really long, I apologize. I needed to get this all written down while it's still fresh in my head.)

The IndexError comes from the bundled pkgs.zip.

I've tried to break down the steps in the websocket communication to understand where the error is coming from, and this is my best understanding of what happens when you call, for example, document.saveAs:

  1. The Document.saveAs function is invoked on the document's FunctionWrapper
  2. An rpc call is sent over the websocket in Communicator.__run_rpc_command line 677
  3. We start waiting for a response from the rpc call in Communicator._wait_for_response line 611
  4. Packet data is received in Websocket.recv lines 292-304
    def recv(self):
        """
        Receive string data(byte array) from the server.
        return value: string(byte array) value.
        """
        opcode, data = self.recv_data()  # <-------------------------------- EMPHASIS MINE
        if six.PY3 and opcode == ABNF.OPCODE_TEXT:
            return data.decode("utf-8")
        elif opcode == ABNF.OPCODE_TEXT or opcode == ABNF.OPCODE_BINARY:
            return data
        else:
            return ''

This part is important. From the packet, we receive an opcode, and some data bundle as a byte string. In the example above that produces the IndexError, we get the following values:

opcode == 8
data == b''

Ok, let's continue...

  1. Next, that packet data is read in the socketIO-client-nexus WebsocketTransport.recv_packet lines 157-158
  2. The text from the packet data is parsed in the parse_package_text function lines 95-98
def parse_packet_text(packet_text):
    packet_type = int(get_character(packet_text, 0))  # <------------ EMPHASIS MINE
    packet_data = packet_text[1:]
    return packet_type, packet_data

This line emphasized here is why we get the IndexError. We are trying reading the first character from an empty byte string.

Alright, great. So that's one mystery solved. But why do we get an empty byte string, and what is the 8 opcode telling us? If we jump back to the websocket-client module, we can see the opcodes defined in _abnf.py lines 80-86:

    # operation code values.
    OPCODE_CONT   = 0x0
    OPCODE_TEXT   = 0x1
    OPCODE_BINARY = 0x2
    OPCODE_CLOSE  = 0x8
    OPCODE_PING   = 0x9
    OPCODE_PONG   = 0xa

The 8 opcode is a close event. Indeed if you keep tracking it down, you'll see that WebSocket.send_close (lines 362-373) is called immediately before the packet is received, which happens right before the IndexError.

If you add an except IndexError: ... block in tk-framework-adobe's Communicator.process_new_messages (lines 238-251), you can ignore the IndexError, but you immediately get another communication error, because the close signal has already been sent, and the socket communication is terminated.

And that's as far as I've been able to get. I do not know why the close signal is being sent. I don't know whether it's being deliberately called somewhere, or if it's a byproduct of some other error wrapped in a try/except clause. I dug around in the Adobe CEP plugin and couldn't find a smoking gun in there. I don't have a ton of familiarity with JavaScript, so I don't feel confident saying anything definitive one way or the other with regards to the plugin.

To circumvent the error for now, I have dialed down the compression settings that our publisher plugin uses to render PNGs. That makes the document.saveAs function complete more quickly, which doesn't produce the error. That is just a stopgap solution though. Sooner or later, I'm worried that an even more "troublesome" file will come along that we can't buy ourselves any more leeway on with the compression settings, and we'll be stuck unable to save it at all.

Any help investigating this, or suggestions on using the Python API to avoid the error, would be extremely welcome!

Rename log files to be named after engine

Looks like the log file is named after the framework rather than the engine which is currently being launched. We want the log file to be named tk-photoshopcc.log and tk-aftereffects.log depending on the DCC.

Publish issue with Photoshop

Publish failed in Photoshop CC when using if Begin File versioning is selected: (tested on Windows)
Steps:

  • Create a new project in Shotgun
  • Make sure you are using the updated after effects basic config
  • Select that project in Desktop and launch Photoshop
  • Open a file and do a publish. Make sure you select Begin File Versioning
    = Publish fails
Traceback (most recent call last):
  File "C:\Users\mathurf\AppData\Roaming\Shotgun\bundle_cache\app_store\tk-multi-publish2\v2.3.0\python\tk_multi_publish2\api\plugins\publish_plugin_instance.py", line 282, in _handle_plugin_error
    yield
  File "C:\Users\mathurf\AppData\Roaming\Shotgun\bundle_cache\app_store\tk-multi-publish2\v2.3.0\python\tk_multi_publish2\api\plugins\publish_plugin_instance.py", line 198, in run_publish
    self._hook_instance.publish(settings, item)
  File "C:\Users\mathurf\Documents\GitHub\tk-photoshopcc\hooks\tk-multi-publish2\basic\start_version_control.py", line 247, in publish
    engine.save_to_path(document, version_path)
  File "C:\Users\mathurf\Documents\GitHub\tk-photoshopcc\engine.py", line 522, in save_to_path
    save_options.quality = 12
  File "C:\Users\mathurf\Documents\GitHub\tk-framework-adobe\python\tk_adobe_basic\rpc\proxy.py", line 278, in __setattr__
    remote_names = self.data["properties"] + self.data["methods"].keys()
KeyError: 'properties'

Move photoshop logic into engine

Move some of the photoshop logic into the photoshop engine. There could be a subclassed version of the Communicator inside the engine, which implements the various photoshop specific methods.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.