@5iver I wanted to start a topic to discuss the namespacing for included APIs for scripting. Currently what I have for JS is a little different to that for Python, and I wanted to ensure that we choose the best organisation for both (and potentially more) languages.
There are a few areas where I think we need to decide:
Module locations
I alluded to this in your Jython PR, but I think we need to align on the best approach here. I believe that there is nothing to discuss re: scripts (3 directories, all distinct), only modules/libs. I think that there are a few questions to be answered, and some assumptions that I have:
Assumptions:
- We want to allow 3rd party scripts to be installed, without modification.
- We want to bundle core modules with the OSGi bundle.
- We want to allow users to add to the locations being searched for modules (donāt know about overriding completely).
Questions:
- Do we want to allow users to āoverrideā scripts provided by core (or community) with their own version, without modifying core or consuming scripts?
- Where do 3rd party libs go?
My views:
- We should allow overriding, as specified above. It makes debugging much simpler for users, and they can return to the default state much more easily.
- I would suggest that 3rd party libs can go in any of the folders! This means that core or community contributions can include their own dependencies. But Iād be happy for a single folder to be the suggested place.
Module namespacing
I think that there are two main namespaces that will be provided: the āscripting APIā and the āimported host objectsā. As part of the Jython PR, these are under core
and core/jsr223/scope
I believe.
Currently in the JS code I have built, itās slightly difference (but generally easily changable). Firstly, some relevant points about how JS (CommonJS, specifically) differs from Python here:
- JS doesnāt really encourage āsubmodulesā or a hierarchy like Python (or Java). Itās possible, but awkward, prone to problems, and poorly supported by tooling.
- JS does perform top-level imports pretty much the same way, and allows either importing all symbols or a subset of those available
- A āmoduleā returned from an import/require call in JS is just an object, so āsubmodulesā can be emulated as child objects. This means that instead of
require('top/child')
you wouldrequire('top').child
- JS can request either relative:
require('./foo')
or absoluterequire('foo')
imports.
Now currently the code I have provides modules like this:
- to get API sections:
require('ohj').items
orrequire('ohj').triggers
etc. - to get host objects
require('@runtime/Defaults')
orrequire('@runtime/RuleSupport')
etc
Our approaches are obviously different. My views on how we should align:
- I donāt like my mixed import-style approach, nor my naming
- I think we should discourage (but still provide) access to the host objects, so I like your sub-namespacing. I noticed that the Python style guide suggests using leading underscores for native modules (C/C++) with an accompanying higher-level module, it feels like we have a similar situation here, so could possibly use this.
- I donāt like the ājsr223ā segment you have in the module path, itās not much help for the average user (personally, I think we should drop it entirely, how many users care which jsr proposed scripting languages in Java, or even what a jsr is?!)
- Iām torn on ācoreā. On the one hand itās already there, and it refers to ācoreā libraries. On the other hand, maybe something either OH-specific or āspecialā should be used for this namespace, or at least for the host objects namespace. Also ācoreā already exists both on PyPI and NPM.
- I also donāt like the āscopesā sub-namespace; I donāt think it describes what it is, which is a collection of objects imported from OH. Below I suggested that we use ā_hostā, but we can probably do better.
- I believe that itās ideal to be able to import specific host objects in the import statement.
If we stick with core, Iād suggest that we go with:
Python
-
import core.items
// import a piece of the API- or
import items from core
- or
-
import core._host
- or
import events from core._host
// the default scope
- or
-
import core._host.RuleSupport
- or
import automationManager from core._host.RuleSupport
- or
JS
-
require('core').items
- or
let { items } = require('core')
- or
-
require('core')._host
- or
let { RuleSupport } = require('core')._host
- or
-
require('core')._host.RuleSupport
- or
let { automationManager } = require('core')._host.RuleSupport
- or
Anyway, I wanted to start thread to get the conversation going.