Article Eduard Lebedyuk · Apr 23, 2019 1m read

This series of articles would cover Python Gateway for InterSystems Data Platforms. Execute Python code and more from InterSystems IRIS. This project brings you the power of Python right into your InterSystems IRIS environment:

  • Execute arbitrary Python code
  • Seamlessly transfer data from InterSystems IRIS into Python
  • Build intelligent Interoperability business processes with Python Interoperability Adapter
  • Save, examine, modify and restore Python context from InterSystems IRIS

Other articles

The plan for the series so far (subject to change).

2
1 1399
Question Eduard Lebedyuk · Apr 15, 2019

I managed to use CacheGlobalOrder to iterate over global and return the next subscript:

int GetGlobalStr(char *global, int subscript, CACHE_EXSTRP result)
{
    int push = CACHEPUSHGLOBAL(strlen(global), global);
    int pushS = CACHEPUSHINT(subscript);
    
    // narg Number of subscript expressions pushed onto the argument stack.
    int narg = 1;

    // Direction for the $Order is 1 for forward, -1 for reverse.
    int dir = 1;
    // Indicates whether the data value, if there is one, should be returned.
1
0 523
Question Eduard Lebedyuk · Apr 15, 2019

I'm using callin to get global values.

Here's a simple function to get string value from global and return it:

int GetGlobalStr(char *global, CACHE_EXSTRP result)
{
    int push = CACHEPUSHGLOBAL(strlen(global), global);

    // narg Number of subscript expressions pushed onto the argument stack.
    int narg = 0;

    // flag - Indicates behavior when global reference is undefined:
    // 0 — returns CACHE_ERUNDEF
    // 1 — returns CACHE_SUCCESS but the return value is an empty string.
11
0 887
Article Eduard Lebedyuk · Apr 12, 2019 1m read

This series of articles would cover Python Gateway for InterSystems Data Platforms. Leverage modern AI/ML tools and execute Python code and more from InterSystems IRIS. This project brings you the power of Python right into your InterSystems IRIS environment:

  • Execute arbitrary Python code
  • Seamlessly transfer data from InterSystems IRIS into Python
  • Build intelligent Interoperability business processes with Python Interoperability Adapter
  • Save, examine, modify and restore Python context from InterSystems IRIS

Index

The plan for the series so far (subject to change).

11
9 3180
Article Eduard Lebedyuk · Apr 8, 2019 4m read

The titular question was quite relevant and often discussed some thirty years ago. The thought went: “Sure, there are industries where computers are the norm, but in my industry we got just fine so far, the benefits are questionable, problems innumerable and unsolved. Can we continue as before or should we embrace this new technology?”

Today, everyone asks the same question but about Machine Learning and Artificial Intelligence. The doubts are the same – lack of expertise, lack of known path, perceived irrelevancy to the industry.

Yet, as before, the correct, even the only possible answer is a resounding yes. Read on to find out why.

1
1 458
Question Eduard Lebedyuk · Mar 2, 2019

I have one abstract class and several subclasses. All share one data/id global.

How can I get concrete class name from id (without opening the object)?

What I have so far:

write $p($lg(^DATAGLOBAL(<id>),1),"~",*-1)

It does the job, but is there a more official way?

3
0 342
Question Eduard Lebedyuk · Feb 28, 2019

I'm connecting to a remote device using TCP. It has a binary protocol.

set host = ""
set port = ""
set io = $io
set device = "|TCP|7000"

set timeout = 2
open device:(host:port:"M")
use device:(/IOT="RAW")
read string:timeout

use io
zzdump string

The problem is when reading from it, I get a 0A (also known as 10 or \n or linefeed) byte, which terminates the read.

Expected output:

0000: 42 00 7B 0A 11

But I get this output:

0000: 42 00 7B

How can I fix that?

Some additional info:

  • read completes in 0.1 seconds despite 2 seconds timeout.
  • $zb contains the value of 0D
1
0 323
Question Eduard Lebedyuk · Feb 28, 2019

Here's a simple indirection snippet. It fails with <UNDEFINED> error and I'm not sure why.

ClassMethod ind()
{
  kill info

  set active = 1
  set reactive = 2

  for i="active","reactive" {
    set info(i)= @i
  }

  zw info

  break
}

I'm getting this exception: <UNDEFINED>zind+5^test.Client.1 *active

6
0 616
Question Eduard Lebedyuk · Feb 21, 2019

I have a date in this format: "YYYY-MM-DD HH:MM:SS+HHMM" how can I convert it to UTC?

write $zdth("2018-02-01 00:00:00+0600",3,5)
>64680,0
write $zdt("64680,0",3,5)
>2018-02-01T00:00:00+03:00

As you see, timezone is lost. Docs for $zdth in timeopt (5) state: Specify time in the form "hh:mm:ss+/-hh:mm" (24-hour clock). The time is specified as local time. The following optional suffix may be supplied, but is ignored: a plus (+) or minus (–) suffix followed by the offset of local time from Coordinated Universal Time (UTC)

2
0 2144
Question Eduard Lebedyuk · Feb 21, 2019

SetIdentityInsert call controls the ability of the user to specify a value for the IDENTITY property when saving a new object, a value for the IDENTITY column or an explicit ROWID value in an SQL INSERT. If IDENTITY_INSERT is false and the user specifies an explicit IDENTITY or ROWID value when saving a new object or inserting a new ROW then an error condition is reported.

Setting takes effect immediately and lasts for the duration of the process or until SetIdentityInsert is called again.

My question is how can I change this setting system-wide?

2
0 430
Question Eduard Lebedyuk · Feb 18, 2019

I have a business process.

if it has an error it dies, or if a have a catch all/fault handler the execution flow goes there.

However, I want another behavior.

If any error occurs I want the process to "Pause" (and alert me), so I can figure out what went wrong and resume from the last request.

Here's an example of how it could work:

  1. If an error is caught, call BO
  2. BO defers response
  3. BO sends alert
  4. Fix BP
  5. Manually resolve deferred response

I'm not set on the exact  pause/resume mechanic but I hope it makes the general idea of what I want clear enough. Ideas?

4
0 428
Question Eduard Lebedyuk · Feb 4, 2019

I want to consume external websocket api, URL looks like this:

wss://site.com/ws/v2/?&token=<token>

Checked with external tool (Simple WebSocket Client) that websocket works and I can consume the data.
In Cache the relevant functionality is offered by %IO.Socket class.

set sock = ##class(%IO.Socket).%New()
set sock.SSLConfig = "MyEmptySSLConfig"
set sock.TranslationTable="UTF8"
do sock.Open("site.com/ws/v2/?&token=<token>","443", 10,.sc)

However I get this error:

ERROR #7109: Timed out after 10 seconds trying to open stream '|TCP|443|42881' [zOpen+41^%IO.Socket.
17
0 1635
Question Eduard Lebedyuk · Jan 26, 2019

Today in docs I found this example using NULL:

 WRITE $LISTVALID($LB(NULL)),!

simplified

zzdump $LB(NULL)

and NULL can be case-insensitive:

zzdump $LB(null)

seems the same as just:

zzdump $LB()

But if null variable is defined then list would contain value from variable. Case sensitive in that situation.

Does anyone have any Idea what is this? Is NULL used anywhere besides as a list element?

5
0 446
Article Eduard Lebedyuk · Jan 23, 2019 3m read

Recently I needed a classmethod that returns annotation value based on a name of a activity.

As doing it at runtime seemed inefficient, I wrote compile-time utility that iterates over all business process activities and generates relevant code.

This code could be used in a variety of situations when you need to iterate over business process activities, just add it as a secondary superclass to your BPL processes.

2
1 510
Question Eduard Lebedyuk · Jan 17, 2019

I have a persistent class.

I want to store one of the properties there as a stream or a string depending on a size.

99% of values would be strings (less than $$$MaxStringLength characters) so I don't want to store everything as streams.

What do you think of this approach?

What's the best architecture to implement in this situation?

4
0 750
Question Eduard Lebedyuk · Dec 27, 2018

I have an in-memory list of items and I want to check which items match my pattern string.

Pattern string is a comma-separated list of items and special symbols like '*' and maybe '?'.

There's something similar in $system.OBJ.Compile, it accepts patterns: "*.data.*,Sample.*" -  and it would compile 'Sample' package and all 'data' packages.

For example:

set list=$lb("abc", "c", "aaa", "bbb")
set result = ..match(list, "a*,*b")
zw result
result=$lb("abc","aaa","bbb")
7
0 908
Question Eduard Lebedyuk · Dec 16, 2018

I have a simple callout library:

#define ZF_DLL
#include 
#include 
#undef ERROR

int GetRandom(double* random) {
   // Py_Initialize();
   // Py_Finalize();
   *random = 1.0;
   return ZF_SUCCESS;
}

int main(int argc, char **argv)
{
   printf("Random: ");
   double random=0;
   GetRandom(&random);
   printf("%lf", random);
   return 0;
}

ZFBEGIN
    ZFENTRY("GetRandom","D",GetRandom)
ZFEND

I compile this code as a shared library and it works fine with:

set path = "library.dll"
write $ZF(-3, path, "GetRandom")

It also compiles and works as an executable.

4
0 619
Question Eduard Lebedyuk · Dec 2, 2018

I'm using this code to read a file, line by line.
Most lines are shorter than 32767 symbols, but some are longer. No line is longer than $$$MaxStringLength and long strings are enabled.
Is there a param to Open/Read command I can pass to increase Read limit?
My code:

set filename = pFile
open filename:("R")
for  {
    use filename read x
    quit:$ZEOF=-1
    set ^dbg($i(^dbg)) = $lb($e(x,1,10), $e(x,*-10,*), $l(x))
}
close filename

I've checked reclen parameter but it did not seem to help
 

3
0 353
Article Eduard Lebedyuk · Nov 26, 2018 2m read

In this article, I would show how you can upload and download files from InterSystems products via http.

The questions about working with files over http arise fairly often on community and I'm usually linking to my FileServer project which demonstrates file upload/download but I'd like to talk a bit more on how we can serve and receive files from InterSystems products.

3
5 3118