From 0f1d464fa67276921ec9474ff458d8f249e7425d Mon Sep 17 00:00:00 2001 From: Paul Griffith Date: Thu, 29 Sep 2022 16:20:32 -0700 Subject: [PATCH 1/5] Add system.project extensions to all scopes --- client/build.gradle.kts | 4 ++ .../org/imdc/extensions/client/ClientHook.kt | 10 +++-- .../client/ClientProjectExtensions.kt | 13 +++++++ .../client/ClientProjectExtensions.properties | 2 + common/build.gradle.kts | 4 ++ .../common/UtilitiesExtensions.java | 1 + .../extensions/common/ExtensionDocProvider.kt | 25 +++++++++++++ .../extensions/common/ProjectExtensions.kt | 7 ++++ designer/build.gradle.kts | 4 ++ .../imdc/extensions/designer/DesignerHook.kt | 10 +++-- .../designer/DesignerProjectExtensions.kt | 37 +++++++++++++++++++ .../DesignerProjectExtensions.properties | 6 +++ gateway/build.gradle.kts | 4 ++ .../imdc/extensions/gateway/GatewayHook.kt | 10 +++-- .../gateway/GatewayProjectExtensions.kt | 22 +++++++++++ .../GatewayProjectExtensions.properties | 3 ++ gradle/libs.versions.toml | 8 +--- 17 files changed, 155 insertions(+), 15 deletions(-) create mode 100644 client/src/main/kotlin/org/imdc/extensions/client/ClientProjectExtensions.kt create mode 100644 client/src/main/resources/org/imdc/extensions/client/ClientProjectExtensions.properties create mode 100644 common/src/main/kotlin/org/imdc/extensions/common/ExtensionDocProvider.kt create mode 100644 common/src/main/kotlin/org/imdc/extensions/common/ProjectExtensions.kt create mode 100644 designer/src/main/kotlin/org/imdc/extensions/designer/DesignerProjectExtensions.kt create mode 100644 designer/src/main/resources/org/imdc/extensions/designer/DesignerProjectExtensions.properties create mode 100644 gateway/src/main/kotlin/org/imdc/extensions/gateway/GatewayProjectExtensions.kt create mode 100644 gateway/src/resources/org/imdc/extensions/gateway/GatewayProjectExtensions.properties diff --git a/client/build.gradle.kts b/client/build.gradle.kts index faeb344..7577b92 100644 --- a/client/build.gradle.kts +++ b/client/build.gradle.kts @@ -9,6 +9,10 @@ java { } } +kotlin { + jvmToolchain(libs.versions.java.map(String::toInt).get()) +} + dependencies { compileOnly(libs.bundles.client) compileOnly(projects.common) diff --git a/client/src/main/kotlin/org/imdc/extensions/client/ClientHook.kt b/client/src/main/kotlin/org/imdc/extensions/client/ClientHook.kt index e1a1c12..24bc3f6 100644 --- a/client/src/main/kotlin/org/imdc/extensions/client/ClientHook.kt +++ b/client/src/main/kotlin/org/imdc/extensions/client/ClientHook.kt @@ -4,9 +4,9 @@ import com.inductiveautomation.ignition.client.model.ClientContext import com.inductiveautomation.ignition.common.BundleUtil import com.inductiveautomation.ignition.common.licensing.LicenseState import com.inductiveautomation.ignition.common.script.ScriptManager -import com.inductiveautomation.ignition.common.script.hints.PropertiesFileDocProvider import com.inductiveautomation.vision.api.client.AbstractClientModuleHook import org.imdc.extensions.common.DatasetExtensions +import org.imdc.extensions.common.ExtensionDocProvider import org.imdc.extensions.common.UtilitiesExtensions import org.imdc.extensions.common.addPropertyBundle @@ -20,11 +20,15 @@ class ClientHook : AbstractClientModuleHook() { BundleUtil.get().apply { addPropertyBundle() addPropertyBundle() + addPropertyBundle() } } override fun initializeScriptManager(manager: ScriptManager) { - manager.addScriptModule("system.dataset", DatasetExtensions, PropertiesFileDocProvider()) - manager.addScriptModule("system.util", UtilitiesExtensions(context), PropertiesFileDocProvider()) + manager.apply { + addScriptModule("system.dataset", DatasetExtensions, ExtensionDocProvider) + addScriptModule("system.util", UtilitiesExtensions(context), ExtensionDocProvider) + addScriptModule("system.project", ClientProjectExtensions(context), ExtensionDocProvider) + } } } diff --git a/client/src/main/kotlin/org/imdc/extensions/client/ClientProjectExtensions.kt b/client/src/main/kotlin/org/imdc/extensions/client/ClientProjectExtensions.kt new file mode 100644 index 0000000..828b638 --- /dev/null +++ b/client/src/main/kotlin/org/imdc/extensions/client/ClientProjectExtensions.kt @@ -0,0 +1,13 @@ +package org.imdc.extensions.client + +import com.inductiveautomation.ignition.client.model.ClientContext +import com.inductiveautomation.ignition.common.project.Project +import com.inductiveautomation.ignition.common.script.hints.ScriptFunction +import org.imdc.extensions.common.ProjectExtensions + +class ClientProjectExtensions(private val context: ClientContext) : ProjectExtensions { + @ScriptFunction(docBundlePrefix = "ClientProjectExtensions") + override fun getProject(): Project { + return requireNotNull(context.project) + } +} diff --git a/client/src/main/resources/org/imdc/extensions/client/ClientProjectExtensions.properties b/client/src/main/resources/org/imdc/extensions/client/ClientProjectExtensions.properties new file mode 100644 index 0000000..776f5d2 --- /dev/null +++ b/client/src/main/resources/org/imdc/extensions/client/ClientProjectExtensions.properties @@ -0,0 +1,2 @@ +getProject.desc=Retrieves the current project. +getProject.returns=The current project as a RuntimeProject instance. diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 86ffa82..a925654 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -9,6 +9,10 @@ java { } } +kotlin { + jvmToolchain(libs.versions.java.map(String::toInt).get()) +} + dependencies { compileOnly(libs.ignition.common) testImplementation(libs.ignition.common) diff --git a/common/src/main/java/org/imdc/extensions/common/UtilitiesExtensions.java b/common/src/main/java/org/imdc/extensions/common/UtilitiesExtensions.java index 104c3c0..51d35cd 100644 --- a/common/src/main/java/org/imdc/extensions/common/UtilitiesExtensions.java +++ b/common/src/main/java/org/imdc/extensions/common/UtilitiesExtensions.java @@ -22,6 +22,7 @@ public UtilitiesExtensions(CommonContext context) { } @ScriptFunction(docBundlePrefix = "UtilitiesExtensions") + @UnsafeExtension public CommonContext getContext() { return context; } diff --git a/common/src/main/kotlin/org/imdc/extensions/common/ExtensionDocProvider.kt b/common/src/main/kotlin/org/imdc/extensions/common/ExtensionDocProvider.kt new file mode 100644 index 0000000..163ebf0 --- /dev/null +++ b/common/src/main/kotlin/org/imdc/extensions/common/ExtensionDocProvider.kt @@ -0,0 +1,25 @@ +package org.imdc.extensions.common + +import com.inductiveautomation.ignition.common.script.hints.PropertiesFileDocProvider +import com.inductiveautomation.ignition.common.script.hints.ScriptFunctionDocProvider +import java.lang.reflect.Method + +private val propertiesFileDocProvider = PropertiesFileDocProvider() + +object ExtensionDocProvider : ScriptFunctionDocProvider by propertiesFileDocProvider { + override fun getMethodDescription(path: String, method: Method): String? { + val methodDescription: String? = propertiesFileDocProvider.getMethodDescription(path, method) + return if (method.isAnnotationPresent(UnsafeExtension::class.java)) { + """ + + THIS IS AN UNOFFICIAL IGNITION EXTENSION. IT MAY RELY ON OR EXPOSE UNDOCUMENTED OR DANGEROUS FUNCTIONALITY. USE AT YOUR OWN RISK. +
+ ${methodDescription.orEmpty()} + """.trimIndent() + } else { + methodDescription + } + } +} + +annotation class UnsafeExtension diff --git a/common/src/main/kotlin/org/imdc/extensions/common/ProjectExtensions.kt b/common/src/main/kotlin/org/imdc/extensions/common/ProjectExtensions.kt new file mode 100644 index 0000000..d229648 --- /dev/null +++ b/common/src/main/kotlin/org/imdc/extensions/common/ProjectExtensions.kt @@ -0,0 +1,7 @@ +package org.imdc.extensions.common + +import com.inductiveautomation.ignition.common.project.Project + +interface ProjectExtensions { + fun getProject(): Project +} diff --git a/designer/build.gradle.kts b/designer/build.gradle.kts index 4ca7178..fab5670 100644 --- a/designer/build.gradle.kts +++ b/designer/build.gradle.kts @@ -9,6 +9,10 @@ java { } } +kotlin { + jvmToolchain(libs.versions.java.map(String::toInt).get()) +} + dependencies { compileOnly(libs.bundles.designer) compileOnly(projects.common) diff --git a/designer/src/main/kotlin/org/imdc/extensions/designer/DesignerHook.kt b/designer/src/main/kotlin/org/imdc/extensions/designer/DesignerHook.kt index 52a0c2e..a4e58e1 100644 --- a/designer/src/main/kotlin/org/imdc/extensions/designer/DesignerHook.kt +++ b/designer/src/main/kotlin/org/imdc/extensions/designer/DesignerHook.kt @@ -3,10 +3,10 @@ package org.imdc.extensions.designer import com.inductiveautomation.ignition.common.BundleUtil import com.inductiveautomation.ignition.common.licensing.LicenseState import com.inductiveautomation.ignition.common.script.ScriptManager -import com.inductiveautomation.ignition.common.script.hints.PropertiesFileDocProvider import com.inductiveautomation.ignition.designer.model.AbstractDesignerModuleHook import com.inductiveautomation.ignition.designer.model.DesignerContext import org.imdc.extensions.common.DatasetExtensions +import org.imdc.extensions.common.ExtensionDocProvider import org.imdc.extensions.common.UtilitiesExtensions import org.imdc.extensions.common.addPropertyBundle @@ -20,11 +20,15 @@ class DesignerHook : AbstractDesignerModuleHook() { BundleUtil.get().apply { addPropertyBundle() addPropertyBundle() + addPropertyBundle() } } override fun initializeScriptManager(manager: ScriptManager) { - manager.addScriptModule("system.dataset", DatasetExtensions, PropertiesFileDocProvider()) - manager.addScriptModule("system.util", UtilitiesExtensions(context), PropertiesFileDocProvider()) + manager.apply { + addScriptModule("system.dataset", DatasetExtensions, ExtensionDocProvider) + addScriptModule("system.util", UtilitiesExtensions(context), ExtensionDocProvider) + addScriptModule("system.project", DesignerProjectExtensions(context), ExtensionDocProvider) + } } } diff --git a/designer/src/main/kotlin/org/imdc/extensions/designer/DesignerProjectExtensions.kt b/designer/src/main/kotlin/org/imdc/extensions/designer/DesignerProjectExtensions.kt new file mode 100644 index 0000000..de35985 --- /dev/null +++ b/designer/src/main/kotlin/org/imdc/extensions/designer/DesignerProjectExtensions.kt @@ -0,0 +1,37 @@ +package org.imdc.extensions.designer + +import com.inductiveautomation.ignition.common.script.hints.ScriptFunction +import com.inductiveautomation.ignition.designer.IgnitionDesigner +import com.inductiveautomation.ignition.designer.model.DesignerContext +import com.inductiveautomation.ignition.designer.project.DesignableProject +import org.apache.commons.lang3.reflect.MethodUtils +import org.imdc.extensions.common.ProjectExtensions +import org.imdc.extensions.common.UnsafeExtension + +class DesignerProjectExtensions(private val context: DesignerContext) : ProjectExtensions { + @ScriptFunction(docBundlePrefix = "DesignerProjectExtensions") + override fun getProject(): DesignableProject { + return requireNotNull(context.project) + } + + @ScriptFunction(docBundlePrefix = "DesignerProjectExtensions") + @UnsafeExtension + fun save() { + MethodUtils.invokeMethod( + context.frame, + true, // forceAccess + "handleSave", + false, // saveAs + null, // newName + false, // commitOnly + false, // skipReopen + false, // showDialog + ) + } + + @ScriptFunction(docBundlePrefix = "DesignerProjectExtensions") + @UnsafeExtension + fun update() { + (context.frame as IgnitionDesigner).updateProject() + } +} diff --git a/designer/src/main/resources/org/imdc/extensions/designer/DesignerProjectExtensions.properties b/designer/src/main/resources/org/imdc/extensions/designer/DesignerProjectExtensions.properties new file mode 100644 index 0000000..c5ac1cc --- /dev/null +++ b/designer/src/main/resources/org/imdc/extensions/designer/DesignerProjectExtensions.properties @@ -0,0 +1,6 @@ +getProject.desc=Retrieves the current project. +getProject.returns=The current project as a DesignableProject instance. +update.desc=Pulls in external changes made to this project from the gateway. +update.returns=None +save.desc=Programmatically invokes the save action. +save.returns=None diff --git a/gateway/build.gradle.kts b/gateway/build.gradle.kts index d91e1ed..623b626 100644 --- a/gateway/build.gradle.kts +++ b/gateway/build.gradle.kts @@ -9,6 +9,10 @@ java { } } +kotlin { + jvmToolchain(libs.versions.java.map(String::toInt).get()) +} + dependencies { compileOnly(libs.bundles.gateway) compileOnly(projects.common) diff --git a/gateway/src/main/kotlin/org/imdc/extensions/gateway/GatewayHook.kt b/gateway/src/main/kotlin/org/imdc/extensions/gateway/GatewayHook.kt index d5e3af1..b4bc735 100644 --- a/gateway/src/main/kotlin/org/imdc/extensions/gateway/GatewayHook.kt +++ b/gateway/src/main/kotlin/org/imdc/extensions/gateway/GatewayHook.kt @@ -3,10 +3,10 @@ package org.imdc.extensions.gateway import com.inductiveautomation.ignition.common.BundleUtil import com.inductiveautomation.ignition.common.licensing.LicenseState import com.inductiveautomation.ignition.common.script.ScriptManager -import com.inductiveautomation.ignition.common.script.hints.PropertiesFileDocProvider import com.inductiveautomation.ignition.gateway.model.AbstractGatewayModuleHook import com.inductiveautomation.ignition.gateway.model.GatewayContext import org.imdc.extensions.common.DatasetExtensions +import org.imdc.extensions.common.ExtensionDocProvider import org.imdc.extensions.common.UtilitiesExtensions import org.imdc.extensions.common.addPropertyBundle @@ -20,6 +20,7 @@ class GatewayHook : AbstractGatewayModuleHook() { BundleUtil.get().apply { addPropertyBundle() addPropertyBundle() + addPropertyBundle() } } @@ -27,8 +28,11 @@ class GatewayHook : AbstractGatewayModuleHook() { override fun shutdown() {} override fun initializeScriptManager(manager: ScriptManager) { - manager.addScriptModule("system.dataset", DatasetExtensions, PropertiesFileDocProvider()) - manager.addScriptModule("system.util", UtilitiesExtensions(context), PropertiesFileDocProvider()) + manager.apply { + addScriptModule("system.dataset", DatasetExtensions, ExtensionDocProvider) + addScriptModule("system.util", UtilitiesExtensions(context), ExtensionDocProvider) + addScriptModule("system.project", GatewayProjectExtensions(context), ExtensionDocProvider) + } } override fun isFreeModule(): Boolean = true diff --git a/gateway/src/main/kotlin/org/imdc/extensions/gateway/GatewayProjectExtensions.kt b/gateway/src/main/kotlin/org/imdc/extensions/gateway/GatewayProjectExtensions.kt new file mode 100644 index 0000000..4dbb01c --- /dev/null +++ b/gateway/src/main/kotlin/org/imdc/extensions/gateway/GatewayProjectExtensions.kt @@ -0,0 +1,22 @@ +package org.imdc.extensions.gateway + +import com.inductiveautomation.ignition.common.project.RuntimeProject +import com.inductiveautomation.ignition.common.script.ScriptContext +import com.inductiveautomation.ignition.common.script.hints.ScriptFunction +import com.inductiveautomation.ignition.gateway.model.GatewayContext +import org.imdc.extensions.common.ProjectExtensions +import org.python.core.Py + +class GatewayProjectExtensions(private val context: GatewayContext) : ProjectExtensions { + @ScriptFunction(docBundlePrefix = "GatewayProjectExtensions") + override fun getProject(): RuntimeProject { + val defaultProject = ScriptContext.defaultProject() ?: throw Py.EnvironmentError("No context project populated") + return getProject(defaultProject) + ?: throw Py.ValueError("Unable to find a default project with name $defaultProject") + } + + @ScriptFunction(docBundlePrefix = "GatewayProjectExtensions") + fun getProject(project: String): RuntimeProject? { + return context.projectManager.getProject(project).orElse(null) + } +} diff --git a/gateway/src/resources/org/imdc/extensions/gateway/GatewayProjectExtensions.properties b/gateway/src/resources/org/imdc/extensions/gateway/GatewayProjectExtensions.properties new file mode 100644 index 0000000..fc1b241 --- /dev/null +++ b/gateway/src/resources/org/imdc/extensions/gateway/GatewayProjectExtensions.properties @@ -0,0 +1,3 @@ +getProject.desc=Retrieves a project by name, or the default project. +getProject.param.project=The name of the project to retrieve. +getProject.returns=The current project as a RuntimeProject instance. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8c0a292..8a820dd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,13 +1,9 @@ [versions] java = "11" -kotlin = "1.7.10" +kotlin = "1.7.20" kotest = "5.4.1" ignition = "8.1.0" -#coroutines = "1.6.3" -#serialization = "1.3.3" -#ktor = "2.0.3" - [plugins] kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } #serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } @@ -48,4 +44,4 @@ kotest = [ "kotest-data", "kotest-junit", "kotest-property", -] \ No newline at end of file +] From 0f55f15c3588a556ecdb1358ff09f3d1ac1f292a Mon Sep 17 00:00:00 2001 From: Paul Griffith Date: Fri, 30 Sep 2022 09:01:29 -0700 Subject: [PATCH 2/5] Tweak warning generation a bit --- .../extensions/common/ExtensionDocProvider.kt | 31 ++++++++++++------- .../org/imdc/extensions/common/Utilities.kt | 11 +++++-- .../designer/DesignerProjectExtensions.kt | 1 + 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/common/src/main/kotlin/org/imdc/extensions/common/ExtensionDocProvider.kt b/common/src/main/kotlin/org/imdc/extensions/common/ExtensionDocProvider.kt index 163ebf0..cc0ccfc 100644 --- a/common/src/main/kotlin/org/imdc/extensions/common/ExtensionDocProvider.kt +++ b/common/src/main/kotlin/org/imdc/extensions/common/ExtensionDocProvider.kt @@ -6,20 +6,29 @@ import java.lang.reflect.Method private val propertiesFileDocProvider = PropertiesFileDocProvider() +private val WARNING = """ + THIS IS AN UNOFFICIAL IGNITION EXTENSION. + IT MAY RELY ON OR EXPOSE UNDOCUMENTED OR DANGEROUS FUNCTIONALITY. + USE AT YOUR OWN RISK. +""".trimIndent() + object ExtensionDocProvider : ScriptFunctionDocProvider by propertiesFileDocProvider { - override fun getMethodDescription(path: String, method: Method): String? { + override fun getMethodDescription(path: String, method: Method): String { val methodDescription: String? = propertiesFileDocProvider.getMethodDescription(path, method) - return if (method.isAnnotationPresent(UnsafeExtension::class.java)) { - """ - - THIS IS AN UNOFFICIAL IGNITION EXTENSION. IT MAY RELY ON OR EXPOSE UNDOCUMENTED OR DANGEROUS FUNCTIONALITY. USE AT YOUR OWN RISK. -
- ${methodDescription.orEmpty()} - """.trimIndent() - } else { - methodDescription + val unsafeAnnotation = method.getAnnotation() + + return buildString { + if (unsafeAnnotation != null) { + append("") + append(WARNING) + if (unsafeAnnotation.note.isNotEmpty()) { + append("
").append(unsafeAnnotation.note) + } + append("

") + } + append(methodDescription.orEmpty()) } } } -annotation class UnsafeExtension +annotation class UnsafeExtension(val note: String = "") diff --git a/common/src/main/kotlin/org/imdc/extensions/common/Utilities.kt b/common/src/main/kotlin/org/imdc/extensions/common/Utilities.kt index d4bde98..8939632 100644 --- a/common/src/main/kotlin/org/imdc/extensions/common/Utilities.kt +++ b/common/src/main/kotlin/org/imdc/extensions/common/Utilities.kt @@ -4,19 +4,20 @@ import com.inductiveautomation.ignition.common.BundleUtil import com.inductiveautomation.ignition.common.Dataset import org.python.core.Py import org.python.core.PyObject +import java.lang.reflect.Method class PyObjectAppendable(target: PyObject) : Appendable { private val writeMethod = target.__getattr__("write") - override fun append(csq: CharSequence) = this.apply { + override fun append(csq: CharSequence): Appendable = this.apply { writeMethod.__call__(Py.newStringOrUnicode(csq.toString())) } - override fun append(csq: CharSequence, start: Int, end: Int) = this.apply { + override fun append(csq: CharSequence, start: Int, end: Int): Appendable = this.apply { append(csq.subSequence(start, end)) } - override fun append(c: Char) = this.apply { + override fun append(c: Char): Appendable = this.apply { append(c.toString()) } } @@ -48,3 +49,7 @@ inline fun BundleUtil.addPropertyBundle() { T::class.java.name.replace('.', '/'), ) } + +inline fun Method.getAnnotation(): T? { + return getAnnotation(T::class.java) +} diff --git a/designer/src/main/kotlin/org/imdc/extensions/designer/DesignerProjectExtensions.kt b/designer/src/main/kotlin/org/imdc/extensions/designer/DesignerProjectExtensions.kt index de35985..df22708 100644 --- a/designer/src/main/kotlin/org/imdc/extensions/designer/DesignerProjectExtensions.kt +++ b/designer/src/main/kotlin/org/imdc/extensions/designer/DesignerProjectExtensions.kt @@ -10,6 +10,7 @@ import org.imdc.extensions.common.UnsafeExtension class DesignerProjectExtensions(private val context: DesignerContext) : ProjectExtensions { @ScriptFunction(docBundlePrefix = "DesignerProjectExtensions") + @UnsafeExtension override fun getProject(): DesignableProject { return requireNotNull(context.project) } From 49a4e35d40fe5aa2f2b950b9a17c96b6c46c7127 Mon Sep 17 00:00:00 2001 From: Paul Griffith Date: Fri, 30 Sep 2022 10:28:08 -0700 Subject: [PATCH 3/5] Fix documentation --- .../org/imdc/extensions/common/ExtensionDocProvider.kt | 2 +- .../imdc}/extensions/common/DatasetExtensions.properties | 0 .../extensions/common/UtilitiesExtensions.properties | 0 .../imdc/extensions/gateway/GatewayProjectExtensions.kt | 8 +++++--- .../gateway/GatewayProjectExtensions.properties | 3 +++ .../gateway/GatewayProjectExtensions.properties | 3 --- 6 files changed, 9 insertions(+), 7 deletions(-) rename common/src/main/resources/{io/github/paulgriffith => org/imdc}/extensions/common/DatasetExtensions.properties (100%) rename common/src/main/resources/{io/github/paulgriffith => org/imdc}/extensions/common/UtilitiesExtensions.properties (100%) create mode 100644 gateway/src/main/resources/org/imdc/extensions/gateway/GatewayProjectExtensions.properties delete mode 100644 gateway/src/resources/org/imdc/extensions/gateway/GatewayProjectExtensions.properties diff --git a/common/src/main/kotlin/org/imdc/extensions/common/ExtensionDocProvider.kt b/common/src/main/kotlin/org/imdc/extensions/common/ExtensionDocProvider.kt index cc0ccfc..85bcb02 100644 --- a/common/src/main/kotlin/org/imdc/extensions/common/ExtensionDocProvider.kt +++ b/common/src/main/kotlin/org/imdc/extensions/common/ExtensionDocProvider.kt @@ -24,7 +24,7 @@ object ExtensionDocProvider : ScriptFunctionDocProvider by propertiesFileDocProv if (unsafeAnnotation.note.isNotEmpty()) { append("
").append(unsafeAnnotation.note) } - append("
") + append("

") } append(methodDescription.orEmpty()) } diff --git a/common/src/main/resources/io/github/paulgriffith/extensions/common/DatasetExtensions.properties b/common/src/main/resources/org/imdc/extensions/common/DatasetExtensions.properties similarity index 100% rename from common/src/main/resources/io/github/paulgriffith/extensions/common/DatasetExtensions.properties rename to common/src/main/resources/org/imdc/extensions/common/DatasetExtensions.properties diff --git a/common/src/main/resources/io/github/paulgriffith/extensions/common/UtilitiesExtensions.properties b/common/src/main/resources/org/imdc/extensions/common/UtilitiesExtensions.properties similarity index 100% rename from common/src/main/resources/io/github/paulgriffith/extensions/common/UtilitiesExtensions.properties rename to common/src/main/resources/org/imdc/extensions/common/UtilitiesExtensions.properties diff --git a/gateway/src/main/kotlin/org/imdc/extensions/gateway/GatewayProjectExtensions.kt b/gateway/src/main/kotlin/org/imdc/extensions/gateway/GatewayProjectExtensions.kt index 4dbb01c..69950a2 100644 --- a/gateway/src/main/kotlin/org/imdc/extensions/gateway/GatewayProjectExtensions.kt +++ b/gateway/src/main/kotlin/org/imdc/extensions/gateway/GatewayProjectExtensions.kt @@ -2,6 +2,7 @@ package org.imdc.extensions.gateway import com.inductiveautomation.ignition.common.project.RuntimeProject import com.inductiveautomation.ignition.common.script.ScriptContext +import com.inductiveautomation.ignition.common.script.hints.ScriptArg import com.inductiveautomation.ignition.common.script.hints.ScriptFunction import com.inductiveautomation.ignition.gateway.model.GatewayContext import org.imdc.extensions.common.ProjectExtensions @@ -11,12 +12,13 @@ class GatewayProjectExtensions(private val context: GatewayContext) : ProjectExt @ScriptFunction(docBundlePrefix = "GatewayProjectExtensions") override fun getProject(): RuntimeProject { val defaultProject = ScriptContext.defaultProject() ?: throw Py.EnvironmentError("No context project populated") - return getProject(defaultProject) - ?: throw Py.ValueError("Unable to find a default project with name $defaultProject") + return requireNotNull(getProject(defaultProject)) { "No such project $defaultProject" } } @ScriptFunction(docBundlePrefix = "GatewayProjectExtensions") - fun getProject(project: String): RuntimeProject? { + fun getProject( + @ScriptArg("project", optional = true) project: String, + ): RuntimeProject? { return context.projectManager.getProject(project).orElse(null) } } diff --git a/gateway/src/main/resources/org/imdc/extensions/gateway/GatewayProjectExtensions.properties b/gateway/src/main/resources/org/imdc/extensions/gateway/GatewayProjectExtensions.properties new file mode 100644 index 0000000..4be8f31 --- /dev/null +++ b/gateway/src/main/resources/org/imdc/extensions/gateway/GatewayProjectExtensions.properties @@ -0,0 +1,3 @@ +getProject.desc=Retrieves a project by name, or None. +getProject.param.project=The name of the project to retrieve. Defaults to the current project, if known. +getProject.returns=The specified project as a RuntimeProject instance. diff --git a/gateway/src/resources/org/imdc/extensions/gateway/GatewayProjectExtensions.properties b/gateway/src/resources/org/imdc/extensions/gateway/GatewayProjectExtensions.properties deleted file mode 100644 index fc1b241..0000000 --- a/gateway/src/resources/org/imdc/extensions/gateway/GatewayProjectExtensions.properties +++ /dev/null @@ -1,3 +0,0 @@ -getProject.desc=Retrieves a project by name, or the default project. -getProject.param.project=The name of the project to retrieve. -getProject.returns=The current project as a RuntimeProject instance. From b621d9c902e2c7f0f49b12e19d61303d7c185f8d Mon Sep 17 00:00:00 2001 From: Paul Griffith Date: Fri, 30 Sep 2022 10:28:44 -0700 Subject: [PATCH 4/5] Add test facility via docker compose --- README.md | 18 +++++++++++++----- build.gradle.kts | 4 ++++ docker-compose.yml | 20 ++++++++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 docker-compose.yml diff --git a/README.md b/README.md index 12df72f..dbb67b9 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,26 @@ # Ignition Extensions A (hopefully) community driven Ignition module project to house utilities that are often useful, but just too niche (or -have enough footguns) to go into Ignition itself. +potentially risky) to go into Ignition itself. # Usage -Simply download the .modl file from the [latest release](https://github.com/IgnitionModuleDevelopmentCommunity/ignition-extensions/releases) and install it to your gateway. +Simply download the .modl file from +the [latest release](https://github.com/IgnitionModuleDevelopmentCommunity/ignition-extensions/releases) and install it +to your gateway. + +# Contribution + +Contributions are welcome. This project is polyglot and set up for both Kotlin and Java. There are example utilities +written in both Kotlin and Java to extend from. Ideas for new features should start as issues for broader discussion. # Building This project uses Gradle, and the Gradle Module Plugin. Use `./gradlew build` to assemble artifacts, and `./gradlew zipModule` to build an unsigned module file for installation into a development gateway. -# Contribution +# Testing -Contributions are welcome. This project is polyglot and set up for both Kotlin and Java. There are example utilities -written in both Kotlin and Java to extend from. Ideas for new features should start as issues for broader discussion. +The easiest way to test is a local Docker installation. Simple run `docker compose up` in the root of this repository to +stand up a local development gateway. Use `./gradlew deployModl` to install the locally built module on that test +gateway. diff --git a/build.gradle.kts b/build.gradle.kts index 5f48818..f28130f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -38,3 +38,7 @@ ignitionModule { skipModlSigning.set(!findProperty("signModule").toString().toBoolean()) } + +tasks.deployModl { + hostGateway.set("http://localhost:18088") +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..911d51b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +services: + gateway: + image: inductiveautomation/ignition:8.1.20 + ports: + - 18088:8088 + environment: + GATEWAY_ADMIN_PASSWORD: password + IGNITION_EDITION: standard + ACCEPT_IGNITION_EULA: "Y" + volumes: + - gateway-data:/usr/local/bin/ignition/data + command: > + -n Ignition-module-dev + -d + -- + -Dignition.allowunsignedmodules=true + -Dia.developer.moduleupload=true + +volumes: + gateway-data: From 22eed804d3ef76befa79e315b70e3924ea7a8806 Mon Sep 17 00:00:00 2001 From: Paul Griffith Date: Fri, 30 Sep 2022 10:28:55 -0700 Subject: [PATCH 5/5] Optimize release build action --- .github/workflows/main-build.yml | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/.github/workflows/main-build.yml b/.github/workflows/main-build.yml index 9696415..064c27b 100644 --- a/.github/workflows/main-build.yml +++ b/.github/workflows/main-build.yml @@ -2,7 +2,7 @@ name: Publish new version upon tag commit on: push: tags: - - '*' + - '[0-9].[0-9].[0-9]' jobs: build: runs-on: ubuntu-latest @@ -29,24 +29,9 @@ jobs: --keystoreFile=keystore.pfx --keystorePassword="${{ secrets.KEYSTORE_PASSWORD }}" --certAlias=ignition-extensions - - name: Upload signed module - uses: actions/upload-artifact@v3 - with: - name: signed - path: build/Ignition-Extensions.modl - release: - runs-on: ubuntu-latest - needs: [build] - steps: - - uses: actions/checkout@v2 - - name: Download signed module - uses: actions/download-artifact@v3 - with: - name: signed - path: artifacts - name: Create release uses: marvinpinto/action-automatic-releases@latest with: repo_token: ${{ secrets.GITHUB_TOKEN }} prerelease: false - files: artifacts/* + files: build/Ignition-Extensions.modl