Mercurial > hg > orthanc-python
changeset 255:e75a76d11a71
updated SDK to 1.12.9 + manual implementation of SetStableStatus
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Wed, 16 Jul 2025 15:53:28 +0200 |
parents | b6a5d49c2afd |
children | 10d11de0fcd5 |
files | CodeAnalysis/CustomFunctions.json CodeAnalysis/GenerateOrthancSDK.py NEWS OrthancSDKVersion.cmake Sources/Autogenerated/orthanc.pyi Sources/Autogenerated/sdk.cpp Sources/Autogenerated/sdk.h Sources/Autogenerated/sdk_GlobalFunctions.impl.h Sources/Autogenerated/sdk_OrthancPluginCompressionType.impl.h Sources/Plugin.cpp |
diffstat | 10 files changed, 552 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/CodeAnalysis/CustomFunctions.json Wed Jul 16 10:39:24 2025 +0200 +++ b/CodeAnalysis/CustomFunctions.json Wed Jul 16 15:53:28 2025 +0200 @@ -373,5 +373,32 @@ } ], "return_sdk_type" : "void" + }, + + { + "comment" : "New in release 6.0", + "short_name" : "SetStableStatus", + "implementation" : "SetStableStatus", + "documentation" : { + "description" : [ "Change the Stable status of a resource" ], + "args" : { + "resourceId" : "The id of the resource.", + "stableStatus" : "The new stable status: 0 for Stable, 1 for Unstable." + }, + "return" : "A tuple with (The error code, An integer indicating wheter the status has changed (1) or not (0) during the execution of this command)." + }, + "args" : [ + { + "sdk_name" : "resourceId", + "sdk_type" : "const char *" + }, + { + "sdk_name" : "stableStatus", + "sdk_type" : "enumeration", + "sdk_enumeration" : "OrthancPluginStableStatus" + } + ], + "return_sdk_type" : "Tuple" } + ]
--- a/CodeAnalysis/GenerateOrthancSDK.py Wed Jul 16 10:39:24 2025 +0200 +++ b/CodeAnalysis/GenerateOrthancSDK.py Wed Jul 16 15:53:28 2025 +0200 @@ -230,6 +230,9 @@ elif f['return_sdk_type'] == 'Dictionary': # This is only used to generate the documentation file "orthanc.pyi" documentation['return_type'] = 'dict' + elif f['return_sdk_type'] == 'Tuple': + # This is only used to generate the documentation file "orthanc.pyi" + documentation['return_type'] = 'tuple' else: raise Exception('Return type not implemented: %s' % f['return_sdk_type'])
--- a/NEWS Wed Jul 16 10:39:24 2025 +0200 +++ b/NEWS Wed Jul 16 15:53:28 2025 +0200 @@ -5,6 +5,8 @@ * Added Windows builder for Python 3.13 * New methods imported from SDK 1.12.9 (TODO: sync again once released) + - AuditLog() + - SetStableStatus() Version 5.0 (2025-01-22)
--- a/OrthancSDKVersion.cmake Wed Jul 16 10:39:24 2025 +0200 +++ b/OrthancSDKVersion.cmake Wed Jul 16 15:53:28 2025 +0200 @@ -1,1 +1,1 @@ -set(ORTHANC_SDK_VERSION "1.12.6") +set(ORTHANC_SDK_VERSION "1.12.9")
--- a/Sources/Autogenerated/orthanc.pyi Wed Jul 16 10:39:24 2025 +0200 +++ b/Sources/Autogenerated/orthanc.pyi Wed Jul 16 15:53:28 2025 +0200 @@ -31,7 +31,7 @@ class ChangeType(): """ - The supported types of changes that can be signaled to the change callback. Note: this enum is not used to store changes in the DB ! + The supported types of changes that can be signaled to the change callback. Note: This enumeration is not used to store changes in the database! """ """ @@ -154,6 +154,11 @@ """ GZIP_WITH_SIZE: int = 3, + """ + No compression (new in Orthanc 1.12.8) + """ + NONE: int = 4, + class ConstraintType(): """ The constraints on the tags (main DICOM tags and identifier tags) that must be supported by the database plugins. @@ -884,6 +889,31 @@ """ UNSUPPORTED_MEDIA_TYPE: int = 3000, +class HttpAuthenticationStatus(): + """ + The status related to the authentication of a HTTP request. + """ + + """ + The authentication has been granted + """ + GRANTED: int = 0, + + """ + The authentication has failed (401 HTTP status) + """ + UNAUTHORIZED: int = 1, + + """ + The authorization has failed (403 HTTP status) + """ + FORBIDDEN: int = 2, + + """ + Redirect to another path (e.g. for login, 307 HTTP status) + """ + REDIRECT: int = 3, + class HttpMethod(): """ The various HTTP methods for a REST call. @@ -1194,6 +1224,21 @@ """ GRAYSCALE64: int = 11, +class QueueOrigin(): + """ + The supported modes to remove an element from a queue. + """ + + """ + Dequeue from the front of the queue + """ + FRONT: int = 0, + + """ + Dequeue from the back of the queue + """ + BACK: int = 1, + class ReceivedInstanceAction(): """ The action to be taken after ReceivedInstanceCallback is triggered @@ -1244,6 +1289,21 @@ """ NONE: int = 4, +class StableStatus(): + """ + The "Stable" status of a resource. + """ + + """ + The resource is stable + """ + STABLE: int = 0, + + """ + The resource is unstable + """ + UNSTABLE: int = 1, + class StorageCommitmentFailureReason(): """ The available values for the Failure Reason (0008,1197) during storage commitment. http://dicom.nema.org/medical/dicom/2019e/output/chtml/part03/sect_C.14.html#sect_C.14.1.1 @@ -1284,6 +1344,36 @@ """ DUPLICATE_TRANSACTION_UID: int = 6, +class StoreStatus(): + """ + The store status related to the adoption of a DICOM instance. + """ + + """ + The file has been stored/adopted + """ + SUCCESS: int = 0, + + """ + The file has already been stored/adopted (only if OverwriteInstances is set to false) + """ + ALREADY_STORED: int = 1, + + """ + The file could not be stored/adopted + """ + FAILURE: int = 2, + + """ + The file has been filtered out by a Lua script or a plugin + """ + FILTERED_OUT: int = 3, + + """ + The storage is full (only if MaximumStorageSize/MaximumPatientCount is set and MaximumStorageMode is Reject) + """ + STORAGE_FULL: int = 4, + class ValueRepresentation(): """ The value representations present in the DICOM standard (version 2013). @@ -1426,6 +1516,20 @@ +# Generate an audit log that might be handled by plugins that have registered an handler +def AuditLog(user_id: str, resource_type: ResourceType, resource_id: str, action: str, log_data: bytes) -> None: + """ + Generate an audit log that might be handled by plugins that have registered an handler. + + Args: + user_id (str): A string uniquely identifying the user or entity that is executing the action on the resource. + resource_type (ResourceType): The type of the resource this log relates to. + resource_id (str): The resource this log relates to. + action (str): The action that is performed on the resource. + log_data (bytes): A pointer to custom log data. + """ + ... + # This function returns the MIME type of a file by inspecting its extension def AutodetectMimeType(path: str) -> str: """ @@ -1614,6 +1718,19 @@ """ ... +# The iterator loops over the keys according to the lexicographical order +def CreateKeysValuesIterator(store_id: str) -> KeysValuesIterator: + """ + The iterator loops over the keys according to the lexicographical order. + + Args: + store_id (str): A unique identifier identifying both the plugin and the key-value store. + + Returns: + KeysValuesIterator: The newly allocated iterator, or NULL in the case of an error. The iterator must be freed by calling OrthancPluginFreeKeysValuesIterator(). + """ + ... + # This function decodes one frame of a DICOM image that is stored in a memory buffer def DecodeDicomImage(buffer: bytes, frame_index: int) -> Image: """ @@ -1628,6 +1745,15 @@ """ ... +def DeleteKeyValue(store_id: str, key: str) -> None: + """ + + Args: + store_id (str): A unique identifier identifying both the plugin and the key-value store. + key (str): The key of the value to store (note: storeId + key must be unique). + """ + ... + # This function takes as input a memory buffer containing a DICOM file, and outputs a JSON string representing the tags of this DICOM file def DicomBufferToJson(buffer: bytes, format: DicomToJsonFormat, flags: DicomToJsonFlags, max_string_length: int) -> str: """ @@ -1660,6 +1786,15 @@ """ ... +def EnqueueValue(queue_id: str, value: bytes) -> None: + """ + + Args: + queue_id (str): A unique identifier identifying both the plugin and the queue. + value (bytes): The value to store. + """ + ... + # Add JavaScript code to customize the default behavior of Orthanc Explorer def ExtendOrthancExplorer(javascript: str) -> None: """ @@ -1703,6 +1838,19 @@ """ ... +# If no custom data is associated with the attachment of interest, the target memory buffer is filled with the NULL value and a zero size +def GetAttachmentCustomData(attachment_uuid: str) -> bytes: + """ + If no custom data is associated with the attachment of interest, the target memory buffer is filled with the NULL value and a zero size. + + Args: + attachment_uuid (str): The UUID of the attachment of interest. + + Returns: + bytes: 0 if success, other value if error. + """ + ... + # Get the value of one of the command-line arguments that were used to launch Orthanc def GetCommandLineArgument(argument: int) -> str: """ @@ -2234,6 +2382,17 @@ """ ... +# This function is notably used in the "orthanc-advanced-storage" when the plugin moves an attachment +def SetAttachmentCustomData(attachment_uuid: str, custom_data: bytes) -> None: + """ + This function is notably used in the "orthanc-advanced-storage" when the plugin moves an attachment. + + Args: + attachment_uuid (str): The UUID of the attachment of interest. + custom_data (bytes): The value to store. + """ + ... + # This function gives a name to the thread that is calling this function def SetCurrentThreadName(thread_name: str) -> None: """ @@ -2309,6 +2468,16 @@ """ ... +def StoreKeyValue(store_id: str, key: str, value: bytes) -> None: + """ + + Args: + store_id (str): A unique identifier identifying both the plugin and the key-value store. + key (str): The key of the value to store (note: storeId + key must be unique). + value (bytes): The value to store. + """ + ... + # This function parses a memory buffer that contains a DICOM file, then transcodes it to the given transfer syntax def TranscodeDicomInstance(buffer: bytes, transfer_syntax: str) -> DicomInstance: """ @@ -2577,6 +2746,20 @@ """ ... +# Change the Stable status of a resource +def SetStableStatus(resource_id: str, stable_status: StableStatus) -> tuple: + """ + Change the Stable status of a resource + + Args: + resource_id (str): The id of the resource. + stable_status (StableStatus): The new stable status: 0 for Stable, 1 for Unstable. + + Returns: + tuple: A tuple with (The error code, An integer indicating wheter the status has changed (1) or not (0) during the execution of this command). + """ + ... + class DicomInstance: """ @@ -2978,6 +3161,33 @@ """ ... +class KeysValuesIterator: + """ + Key-Value store iterator + """ + ... + + + # Before using this function, the function OrthancPluginKeysValuesIteratorNext() must have been called at least once + def KeysValuesIteratorGetKey(self) -> str: + """ + Before using this function, the function OrthancPluginKeysValuesIteratorNext() must have been called at least once. + + Returns: + str: The current key, or NULL in the case of an error. + """ + ... + + # Before using this function, the function OrthancPluginKeysValuesIteratorNext() must have been called at least once + def KeysValuesIteratorGetValue(self) -> bytes: + """ + Before using this function, the function OrthancPluginKeysValuesIteratorNext() must have been called at least once. + + Returns: + bytes: The current value, or NULL in the case of an error. + """ + ... + class Peers: """ Orthanc peer @@ -3230,6 +3440,7 @@ def StorageAreaCreate(self, uuid: str, content: bytes, size: int, type: ContentType) -> None: """ This function creates a new file inside the storage area that is currently used by Orthanc. + Warning: This function will result in a "not implemented" error on versions of the Orthanc core above 1.12.6. Args: uuid (str): The identifier of the file to be created. @@ -3243,6 +3454,7 @@ def StorageAreaRead(self, uuid: str, type: ContentType) -> bytes: """ This function reads the content of a given file from the storage area that is currently used by Orthanc. + Warning: This function will result in a "not implemented" error on versions of the Orthanc core above 1.12.6. Args: uuid (str): The identifier of the file to be read. @@ -3257,6 +3469,7 @@ def StorageAreaRemove(self, uuid: str, type: ContentType) -> None: """ This function removes a given file from the storage area that is currently used by Orthanc. + Warning: This function will result in a "not implemented" error on versions of the Orthanc core above 1.12.6. Args: uuid (str): The identifier of the file to be removed.
--- a/Sources/Autogenerated/sdk.cpp Wed Jul 16 10:39:24 2025 +0200 +++ b/Sources/Autogenerated/sdk.cpp Wed Jul 16 15:53:28 2025 +0200 @@ -43,6 +43,7 @@ #include "./sdk_OrthancPluginDicomToJsonFormat.impl.h" #include "./sdk_OrthancPluginDicomWebBinaryMode.impl.h" #include "./sdk_OrthancPluginErrorCode.impl.h" +#include "./sdk_OrthancPluginHttpAuthenticationStatus.impl.h" #include "./sdk_OrthancPluginHttpMethod.impl.h" #include "./sdk_OrthancPluginIdentifierConstraint.impl.h" #include "./sdk_OrthancPluginImageFormat.impl.h" @@ -54,9 +55,12 @@ #include "./sdk_OrthancPluginLogLevel.impl.h" #include "./sdk_OrthancPluginMetricsType.impl.h" #include "./sdk_OrthancPluginPixelFormat.impl.h" +#include "./sdk_OrthancPluginQueueOrigin.impl.h" #include "./sdk_OrthancPluginReceivedInstanceAction.impl.h" #include "./sdk_OrthancPluginResourceType.impl.h" +#include "./sdk_OrthancPluginStableStatus.impl.h" #include "./sdk_OrthancPluginStorageCommitmentFailureReason.impl.h" +#include "./sdk_OrthancPluginStoreStatus.impl.h" #include "./sdk_OrthancPluginValueRepresentation.impl.h" #include "./sdk_OrthancPluginDicomInstance.impl.h" @@ -66,6 +70,7 @@ #include "./sdk_OrthancPluginFindQuery.impl.h" #include "./sdk_OrthancPluginImage.impl.h" #include "./sdk_OrthancPluginJob.impl.h" +#include "./sdk_OrthancPluginKeysValuesIterator.impl.h" #include "./sdk_OrthancPluginPeers.impl.h" #include "./sdk_OrthancPluginRestOutput.impl.h" #include "./sdk_OrthancPluginServerChunkedRequestReader.impl.h" @@ -83,6 +88,7 @@ #include "./sdk_OrthancPluginFindQuery.methods.h" #include "./sdk_OrthancPluginImage.methods.h" #include "./sdk_OrthancPluginJob.methods.h" +#include "./sdk_OrthancPluginKeysValuesIterator.methods.h" #include "./sdk_OrthancPluginPeers.methods.h" #include "./sdk_OrthancPluginRestOutput.methods.h" #include "./sdk_OrthancPluginServerChunkedRequestReader.methods.h" @@ -102,6 +108,7 @@ RegisterOrthancPluginDicomToJsonFormatEnumeration(module); RegisterOrthancPluginDicomWebBinaryModeEnumeration(module); RegisterOrthancPluginErrorCodeEnumeration(module); + RegisterOrthancPluginHttpAuthenticationStatusEnumeration(module); RegisterOrthancPluginHttpMethodEnumeration(module); RegisterOrthancPluginIdentifierConstraintEnumeration(module); RegisterOrthancPluginImageFormatEnumeration(module); @@ -113,9 +120,12 @@ RegisterOrthancPluginLogLevelEnumeration(module); RegisterOrthancPluginMetricsTypeEnumeration(module); RegisterOrthancPluginPixelFormatEnumeration(module); + RegisterOrthancPluginQueueOriginEnumeration(module); RegisterOrthancPluginReceivedInstanceActionEnumeration(module); RegisterOrthancPluginResourceTypeEnumeration(module); + RegisterOrthancPluginStableStatusEnumeration(module); RegisterOrthancPluginStorageCommitmentFailureReasonEnumeration(module); + RegisterOrthancPluginStoreStatusEnumeration(module); RegisterOrthancPluginValueRepresentationEnumeration(module); RegisterOrthancPluginDicomInstanceClass(module); @@ -125,6 +135,7 @@ RegisterOrthancPluginFindQueryClass(module); RegisterOrthancPluginImageClass(module); RegisterOrthancPluginJobClass(module); + RegisterOrthancPluginKeysValuesIteratorClass(module); RegisterOrthancPluginPeersClass(module); RegisterOrthancPluginRestOutputClass(module); RegisterOrthancPluginServerChunkedRequestReaderClass(module);
--- a/Sources/Autogenerated/sdk.h Wed Jul 16 10:39:24 2025 +0200 +++ b/Sources/Autogenerated/sdk.h Wed Jul 16 15:53:28 2025 +0200 @@ -41,6 +41,7 @@ PyTypeObject* GetOrthancPluginFindQueryType(); PyTypeObject* GetOrthancPluginImageType(); PyTypeObject* GetOrthancPluginJobType(); +PyTypeObject* GetOrthancPluginKeysValuesIteratorType(); PyTypeObject* GetOrthancPluginPeersType(); PyTypeObject* GetOrthancPluginRestOutputType(); PyTypeObject* GetOrthancPluginServerChunkedRequestReaderType(); @@ -119,6 +120,15 @@ PyObject_HEAD /* Type-specific fields go here. */ + OrthancPluginKeysValuesIterator* object_; + bool borrowed_; +} sdk_OrthancPluginKeysValuesIterator_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ OrthancPluginPeers* object_; bool borrowed_; } sdk_OrthancPluginPeers_Object;
--- a/Sources/Autogenerated/sdk_GlobalFunctions.impl.h Wed Jul 16 10:39:24 2025 +0200 +++ b/Sources/Autogenerated/sdk_GlobalFunctions.impl.h Wed Jul 16 15:53:28 2025 +0200 @@ -42,9 +42,36 @@ extern PyObject *RegisterStorageArea(PyObject* module, PyObject *args); extern PyObject *RegisterStorageCommitmentScpCallback(PyObject* module, PyObject *args); extern PyObject *RegisterWorklistCallback(PyObject* module, PyObject *args); +extern PyObject *SetStableStatus(PyObject* module, PyObject *args); // End of forward declarations +static PyObject* sdk_OrthancPluginAuditLog(PyObject* module, PyObject* args) +{ + PythonLock::LogCall("Calling Python global function: OrthancPluginAuditLog()"); + + const char* arg0 = NULL; + long int arg1 = 0; + const char* arg2 = NULL; + const char* arg3 = NULL; + Py_buffer arg4; + + if (!PyArg_ParseTuple(args, "slsss*", &arg0, &arg1, &arg2, &arg3, &arg4)) + { + PyErr_SetString(PyExc_TypeError, "Bad types for the arguments (5 arguments expected)"); + return NULL; + } + + { + PythonThreadsAllower allower; + OrthancPluginAuditLog(OrthancPlugins::GetGlobalContext(), arg0, static_cast<OrthancPluginResourceType>(arg1), arg2, arg3, arg4.buf, arg4.len); + } + PyBuffer_Release(&arg4); + + Py_INCREF(Py_None); + return Py_None; +} + static PyObject* sdk_OrthancPluginAutodetectMimeType(PyObject* module, PyObject* args) { PythonLock::LogCall("Calling Python global function: OrthancPluginAutodetectMimeType()"); @@ -449,6 +476,39 @@ } } +static PyObject* sdk_OrthancPluginCreateKeysValuesIterator(PyObject* module, PyObject* args) +{ + PythonLock::LogCall("Calling Python global function: OrthancPluginCreateKeysValuesIterator()"); + + const char* arg0 = NULL; + + if (!PyArg_ParseTuple(args, "s", &arg0)) + { + PyErr_SetString(PyExc_TypeError, "Bad types for the arguments (1 arguments expected)"); + return NULL; + } + + // This is the case of a constructor + OrthancPluginKeysValuesIterator* obj; + { + PythonThreadsAllower allower; + obj = OrthancPluginCreateKeysValuesIterator(OrthancPlugins::GetGlobalContext(), arg0); + } + + if (obj == NULL) + { + PythonLock::RaiseException(OrthancPluginErrorCode_InternalError); + return NULL; + } + else + { + PyObject *argList = Py_BuildValue("Lb", obj, false /* not borrowed */); + PyObject *python = PyObject_CallObject((PyObject *) &sdk_OrthancPluginKeysValuesIterator_Type, argList); + Py_DECREF(argList); + return python; + } +} + static PyObject* sdk_OrthancPluginDecodeDicomImage(PyObject* module, PyObject* args) { PythonLock::LogCall("Calling Python global function: OrthancPluginDecodeDicomImage()"); @@ -483,6 +543,38 @@ } } +static PyObject* sdk_OrthancPluginDeleteKeyValue(PyObject* module, PyObject* args) +{ + PythonLock::LogCall("Calling Python global function: OrthancPluginDeleteKeyValue()"); + + const char* arg0 = NULL; + const char* arg1 = NULL; + + if (!PyArg_ParseTuple(args, "ss", &arg0, &arg1)) + { + PyErr_SetString(PyExc_TypeError, "Bad types for the arguments (2 arguments expected)"); + return NULL; + } + + OrthancPluginErrorCode code; + { + PythonThreadsAllower allower; + code = OrthancPluginDeleteKeyValue(OrthancPlugins::GetGlobalContext(), arg0, arg1); + } + + + if (code == OrthancPluginErrorCode_Success) + { + Py_INCREF(Py_None); + return Py_None; + } + else + { + PythonLock::RaiseException(code); + return NULL; + } +} + static PyObject* sdk_OrthancPluginDicomBufferToJson(PyObject* module, PyObject* args) { PythonLock::LogCall("Calling Python global function: OrthancPluginDicomBufferToJson()"); @@ -547,6 +639,38 @@ } } +static PyObject* sdk_OrthancPluginEnqueueValue(PyObject* module, PyObject* args) +{ + PythonLock::LogCall("Calling Python global function: OrthancPluginEnqueueValue()"); + + const char* arg0 = NULL; + Py_buffer arg1; + + if (!PyArg_ParseTuple(args, "ss*", &arg0, &arg1)) + { + PyErr_SetString(PyExc_TypeError, "Bad types for the arguments (2 arguments expected)"); + return NULL; + } + + OrthancPluginErrorCode code; + { + PythonThreadsAllower allower; + code = OrthancPluginEnqueueValue(OrthancPlugins::GetGlobalContext(), arg0, arg1.buf, arg1.len); + } + PyBuffer_Release(&arg1); + + if (code == OrthancPluginErrorCode_Success) + { + Py_INCREF(Py_None); + return Py_None; + } + else + { + PythonLock::RaiseException(code); + return NULL; + } +} + static PyObject* sdk_OrthancPluginExtendOrthancExplorer(PyObject* module, PyObject* args) { PythonLock::LogCall("Calling Python global function: OrthancPluginExtendOrthancExplorer()"); @@ -638,6 +762,36 @@ } } +static PyObject* sdk_OrthancPluginGetAttachmentCustomData(PyObject* module, PyObject* args) +{ + PythonLock::LogCall("Calling Python global function: OrthancPluginGetAttachmentCustomData()"); + + const char* arg0 = NULL; + + if (!PyArg_ParseTuple(args, "s", &arg0)) + { + PyErr_SetString(PyExc_TypeError, "Bad types for the arguments (1 arguments expected)"); + return NULL; + } + + OrthancPlugins::MemoryBuffer buffer; + OrthancPluginErrorCode code; + { + PythonThreadsAllower allower; + code = OrthancPluginGetAttachmentCustomData(OrthancPlugins::GetGlobalContext(), *buffer, arg0); + } + + if (code == OrthancPluginErrorCode_Success) + { + return PyBytes_FromStringAndSize(buffer.GetData(), buffer.GetSize()); + } + else + { + PythonLock::RaiseException(code); + return NULL; + } +} + static PyObject* sdk_OrthancPluginGetCommandLineArgument(PyObject* module, PyObject* args) { PythonLock::LogCall("Calling Python global function: OrthancPluginGetCommandLineArgument()"); @@ -1809,6 +1963,38 @@ } } +static PyObject* sdk_OrthancPluginSetAttachmentCustomData(PyObject* module, PyObject* args) +{ + PythonLock::LogCall("Calling Python global function: OrthancPluginSetAttachmentCustomData()"); + + const char* arg0 = NULL; + Py_buffer arg1; + + if (!PyArg_ParseTuple(args, "ss*", &arg0, &arg1)) + { + PyErr_SetString(PyExc_TypeError, "Bad types for the arguments (2 arguments expected)"); + return NULL; + } + + OrthancPluginErrorCode code; + { + PythonThreadsAllower allower; + code = OrthancPluginSetAttachmentCustomData(OrthancPlugins::GetGlobalContext(), arg0, arg1.buf, arg1.len); + } + PyBuffer_Release(&arg1); + + if (code == OrthancPluginErrorCode_Success) + { + Py_INCREF(Py_None); + return Py_None; + } + else + { + PythonLock::RaiseException(code); + return NULL; + } +} + static PyObject* sdk_OrthancPluginSetCurrentThreadName(PyObject* module, PyObject* args) { PythonLock::LogCall("Calling Python global function: OrthancPluginSetCurrentThreadName()"); @@ -1986,6 +2172,39 @@ return Py_None; } +static PyObject* sdk_OrthancPluginStoreKeyValue(PyObject* module, PyObject* args) +{ + PythonLock::LogCall("Calling Python global function: OrthancPluginStoreKeyValue()"); + + const char* arg0 = NULL; + const char* arg1 = NULL; + Py_buffer arg2; + + if (!PyArg_ParseTuple(args, "sss*", &arg0, &arg1, &arg2)) + { + PyErr_SetString(PyExc_TypeError, "Bad types for the arguments (3 arguments expected)"); + return NULL; + } + + OrthancPluginErrorCode code; + { + PythonThreadsAllower allower; + code = OrthancPluginStoreKeyValue(OrthancPlugins::GetGlobalContext(), arg0, arg1, arg2.buf, arg2.len); + } + PyBuffer_Release(&arg2); + + if (code == OrthancPluginErrorCode_Success) + { + Py_INCREF(Py_None); + return Py_None; + } + else + { + PythonLock::RaiseException(code); + return NULL; + } +} + static PyObject* sdk_OrthancPluginTranscodeDicomInstance(PyObject* module, PyObject* args) { PythonLock::LogCall("Calling Python global function: OrthancPluginTranscodeDicomInstance()"); @@ -2089,6 +2308,8 @@ static PyMethodDef ORTHANC_SDK_FUNCTIONS[] = { + { "AuditLog", sdk_OrthancPluginAuditLog, METH_VARARGS, + "Generated from C function OrthancPluginAuditLog()" }, { "AutodetectMimeType", sdk_OrthancPluginAutodetectMimeType, METH_VARARGS, "Generated from C function OrthancPluginAutodetectMimeType()" }, { "BufferCompression", sdk_OrthancPluginBufferCompression, METH_VARARGS, @@ -2115,12 +2336,18 @@ "Generated from C function OrthancPluginCreateFindMatcher()" }, { "CreateImage", sdk_OrthancPluginCreateImage, METH_VARARGS, "Generated from C function OrthancPluginCreateImage()" }, + { "CreateKeysValuesIterator", sdk_OrthancPluginCreateKeysValuesIterator, METH_VARARGS, + "Generated from C function OrthancPluginCreateKeysValuesIterator()" }, { "DecodeDicomImage", sdk_OrthancPluginDecodeDicomImage, METH_VARARGS, "Generated from C function OrthancPluginDecodeDicomImage()" }, + { "DeleteKeyValue", sdk_OrthancPluginDeleteKeyValue, METH_VARARGS, + "Generated from C function OrthancPluginDeleteKeyValue()" }, { "DicomBufferToJson", sdk_OrthancPluginDicomBufferToJson, METH_VARARGS, "Generated from C function OrthancPluginDicomBufferToJson()" }, { "DicomInstanceToJson", sdk_OrthancPluginDicomInstanceToJson, METH_VARARGS, "Generated from C function OrthancPluginDicomInstanceToJson()" }, + { "EnqueueValue", sdk_OrthancPluginEnqueueValue, METH_VARARGS, + "Generated from C function OrthancPluginEnqueueValue()" }, { "ExtendOrthancExplorer", sdk_OrthancPluginExtendOrthancExplorer, METH_VARARGS, "Generated from C function OrthancPluginExtendOrthancExplorer()" }, { "ExtendOrthancExplorer2", sdk_OrthancPluginExtendOrthancExplorer2, METH_VARARGS, @@ -2129,6 +2356,8 @@ "Generated from C function OrthancPluginGenerateRestApiAuthorizationToken()" }, { "GenerateUuid", sdk_OrthancPluginGenerateUuid, METH_VARARGS, "Generated from C function OrthancPluginGenerateUuid()" }, + { "GetAttachmentCustomData", sdk_OrthancPluginGetAttachmentCustomData, METH_VARARGS, + "Generated from C function OrthancPluginGetAttachmentCustomData()" }, { "GetCommandLineArgument", sdk_OrthancPluginGetCommandLineArgument, METH_VARARGS, "Generated from C function OrthancPluginGetCommandLineArgument()" }, { "GetCommandLineArgumentsCount", sdk_OrthancPluginGetCommandLineArgumentsCount, METH_VARARGS, @@ -2213,6 +2442,8 @@ "Generated from C function OrthancPluginRestApiPut()" }, { "RestApiPutAfterPlugins", sdk_OrthancPluginRestApiPutAfterPlugins, METH_VARARGS, "Generated from C function OrthancPluginRestApiPutAfterPlugins()" }, + { "SetAttachmentCustomData", sdk_OrthancPluginSetAttachmentCustomData, METH_VARARGS, + "Generated from C function OrthancPluginSetAttachmentCustomData()" }, { "SetCurrentThreadName", sdk_OrthancPluginSetCurrentThreadName, METH_VARARGS, "Generated from C function OrthancPluginSetCurrentThreadName()" }, { "SetDescription", sdk_OrthancPluginSetDescription, METH_VARARGS, @@ -2227,6 +2458,8 @@ "Generated from C function OrthancPluginSetRootUri()" }, { "SetRootUri2", sdk_OrthancPluginSetRootUri2, METH_VARARGS, "Generated from C function OrthancPluginSetRootUri2()" }, + { "StoreKeyValue", sdk_OrthancPluginStoreKeyValue, METH_VARARGS, + "Generated from C function OrthancPluginStoreKeyValue()" }, { "TranscodeDicomInstance", sdk_OrthancPluginTranscodeDicomInstance, METH_VARARGS, "Generated from C function OrthancPluginTranscodeDicomInstance()" }, { "UncompressImage", sdk_OrthancPluginUncompressImage, METH_VARARGS, @@ -2261,6 +2494,8 @@ "Implemented in C++ function RegisterStorageCommitmentScpCallback()" }, { "RegisterWorklistCallback", RegisterWorklistCallback, METH_VARARGS, "Implemented in C++ function RegisterWorklistCallback()" }, + { "SetStableStatus", SetStableStatus, METH_VARARGS, + "Implemented in C++ function SetStableStatus()" }, { NULL, NULL } };
--- a/Sources/Autogenerated/sdk_OrthancPluginCompressionType.impl.h Wed Jul 16 10:39:24 2025 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginCompressionType.impl.h Wed Jul 16 15:53:28 2025 +0200 @@ -97,6 +97,12 @@ Py_DECREF(tmp); } + { + PyObject* tmp = PyLong_FromLong(4); + PyDict_SetItemString(sdk_OrthancPluginCompressionType_Type.tp_dict, "NONE", tmp); + Py_DECREF(tmp); + } + Py_INCREF(&sdk_OrthancPluginCompressionType_Type); if (PyModule_AddObject(module, "CompressionType", (PyObject *)&sdk_OrthancPluginCompressionType_Type) < 0)
--- a/Sources/Plugin.cpp Wed Jul 16 10:39:24 2025 +0200 +++ b/Sources/Plugin.cpp Wed Jul 16 15:53:28 2025 +0200 @@ -286,6 +286,49 @@ } } +PyObject* SetStableStatus(PyObject* module, PyObject* args) +{ + const char* resourceId = NULL; + long int stableStatus = 0; + + if (!PyArg_ParseTuple(args, "sl", &resourceId, &stableStatus)) + { + PyErr_SetString(PyExc_TypeError, "Please provide a string containing the resourceId and a integer with 0 for stable and 1 for unstable"); + return NULL; + } + else + { + OrthancPluginErrorCode code; + int32_t statusHasChanged; + + { + PythonThreadsAllower allower; + code = OrthancPluginSetStableStatus(OrthancPlugins::GetGlobalContext(), &statusHasChanged, resourceId, static_cast<OrthancPluginStableStatus>(stableStatus)); + } + + if (code == OrthancPluginErrorCode_Success) + { + /** + * "PyGILState_Ensure()" can be invoked several times from the + * same thread, so no problem in creating a PythonLock even if + * the GIL is already locked. + **/ + PythonLock lock; + + PythonObject tuple(lock, PyTuple_New(2)); + PyTuple_SetItem(tuple.GetPyObject(), 0, PyLong_FromUnsignedLong(static_cast<unsigned long>(code))); + PyTuple_SetItem(tuple.GetPyObject(), 1, PyLong_FromLong(static_cast<long>(statusHasChanged))); + + return tuple.Release(); + } + else + { + std::string message = "Failed to change stable status of resource: " + std::string(resourceId); + PyErr_SetString(PyExc_TypeError, message.c_str()); + return NULL; + } + } +} static bool pythonEnabled_ = false;