Artigo
· Jun. 21 7min de leitura

Sobre a ideia de Usar a Sintaxe de Definição de Classe Python para criar classes IRIS

Introdução

Não muito tempo atrás, eu me deparei com a ideia de Usar a Sintaxe de Definição de Classe Python para criar classes IRIS no Portal de Ideias do InterSystems. Ela atraiu minha atenção porque integrar o máximo de sintaxes possíveis dá visibilidade aos produtos InterSystems para programadores de muitas linguagens.

O autor dessa ideia apontou a possibilidade de criar classes usando a sintaxe Python, em adição às já disponíveis no IRIS. Esse conceito me inspirou a escrever esse artigo, explorando as possibilidades de acessar o poder total da InterSystems utilizando apenas Python.

Vale à pena mencionar que um dos precursores de todo esse poder é a capacidade multi-modelo do IRIS. Ela permite que você acesse o mesmo dado por meio de globais (uma estrutura de armazenamento multidimensional). As globais são a estrutura de base para todos os outros modelos. Da mesma maneira, você pode acessar o mesmo dado por meio de objetos. No escopo desse artigo, acessar por objeto significa usar adaptadores JSON ou XML para conectar IRIS e Python. Além disso, também pode acessar o dado por SQL usando conexões JDBC ou ODBC. Por fim, você também pode empregar uma DocDB (Document database) que também opera com sintaxe JSON para receber o mesmo resultado.

 

Criar uma base de dados IRIS desde uma classe Python usando SQL

Para começar, devemos discutir o ponto principal da ideia: usar a sintaxe de definição de classe do Python para criar uma classe IRIS. É possível chegar nisso, mas a complexidade dessa implementação depende totalmente na sofisticação das relações definidas na sua classe. Você pode clicar aqui para olhar meus estudos dessa solução. Não hesite em me contatar se quiser discutir esse tema melhor!

Se você só precisa das propriedades de uma classe definida em Python, a maneira mais fácil será utilizar a função mapper() do SQLAlchemy para criar sua classe.

Para isso, você vai precisar das importações a seguir:
 

from sqlalchemy import create_engine, MetaData
from sqlalchemy.schema import Table, Column
from sqlalchemy.orm import mapper

Claro, você deve começar definindo sua máquina e então criando sua tabela. Você também pode definir uma coluna de chave primária para sua classe se ela já não tem.

engine = create_engine("iris://" + user + ":" + password + "@" + host + ":" + port + "/" + namespace)
metadata = MetaData()
table = Table(class_name, metadata, Column('id', Integer,  primary_key = True))

Adicionalmente, para cada propriedade na sua classe, lembre-se de adicionar uma Column() na sua tabela com o nome, tipo SQL, vindo de sqlalchemy.sql.sqltypes e opcionalmente um valor default. Talvez você queira checar esse link com um dicionário de Python para SQL para simplificar sua tarefa.

Finalmente, você deve chamar o mapper com a sua classe e a tabela como argumentos, e criá-las com sua máquina.

mapper(my_class, table)
metadata.create_all(engine)

Se você ainda assim desejar criar métodos, pode acessar seu recém criado arquivo .cls, definir um método com sintaxe ObjectScript e definir sua linguagem como Python.

Contudo você ainda pode evitar essa única linha de ObjectScript ao criar sua classe. A melhor maneira de fazê-lo é usar o InterSystems Native SDK para Python para conectar o Python ao Iris e utilizá-lo para acessar classes %Dictionary. Essas classes te ajudam a construir seu arquivo .cls. Você vai precisar de um schema, um nome para sua classe, nomes e tipos das suas propriedades e implementações de métodos para concluir essa tarefa.

Se você tem uma classe definida em Python, pode acessar essa informação facilmente. Defina o schema como quiser e acesse o nome da classe em uma linha de código, como mostrado abaixo:

class_name = your_class.__class__.__name__

A seguir, a função embutida dir() te dará todos os atributos em uma classe. Você pode usar o método callable() para checar se é uma propriedade ou um método. Finalmente, você pode importar o módulo inspect e utilizar suas funções getsource() e getfullargspec() para acessar cada pedacinho de informação dos seus métodos.

implementation = i.getsource(function) # esse pega o código escrito como uma string
inspection = i.getfullargspec(function) 
defaults = inspection.defaults
annotation = inspection.annotations
arguments = inspection[0]

Tenha em mente que o primeiro argumento numa função de classe do Python pode ser "self". Nesse caso, será refletida no ObjectScript como Method. Caso contrário, será um ClassMethod.

Com esses elementos, você pode abrir sua classe e modificá-la com as classes %Dictionary.

new_class = irispy.classMethodObject("%Dictionary.ClassDefinition", "%Open", class_name)
new_method = irispy.classMethodObject("%Dictionary.MethodDefinition", "%New", class_name + ":" + method_name)
new_method.set("Language", "python")
new_method.get("Implementation").invoke("Write", implementation)
new_method.set("ClassMethod", isClassMethod)
new_method.set("FormalSpec", formal_spec)
new_class.get("Methods").invoke("Insert", new_method)

No código escrito acima, o objeto irispy foi gerado conectando a instância IRIS com o método createIRIS() do módulo. Você pode descobrir mais detalhes sobre como estabelecer essa conexão na documentação ou em alguns dos meus artigos anteriores. Contudo, nesse momento tudo o que você precisa saber sobre isso está no código abaixo:

import iris

# Abre uma conexão com o servidor
args = {'hostname':'127.0.0.1', 'port':52773,
    'namespace':'USER', 'username':'_SYSTEM', 'password':'SYS'
}
conn = iris.connect(**args)
# Cria um objeto IRIS
irispy = iris.createIRIS(conn)

Você pode criar sua formal_spec com a anotação da inspeção.

Por fim, invoque %Save nessa definição.

sc = new_class.invoke("%Save")

 

Criar uma base de dados IRIS de uma classe Python usando DocDB

Primeiro, você deve habilitar sua instância para receber esse tipo de requisição REST. Para isso, vá em Administração do Sistema > Segurança > Serviços, selecione %Service_DocDB, escolha "Serviço habilitado" e clique em Salvar. A seguir, seu sistema pode necessitar que você instale o módulo de requisições do Python com o comando pip install requests.

Se você não está familiarizado com APIs REST com Python, você ainda poderá acompanhar esse tutorial, já que tudo o que será usado aqui é bastante intuitivo.

Vamos precisar apenas enviar algumas URLs para a %Api.DocDB.v1, que é uma opção embutida do IRIS. Apenas importe o requests no seu ambiente Python e escreva uma URL com o padrão demonstrado abaixo:

url = http://HOST:PORT/api/docdb/v1/NAMESPACE/db/DBNAME?type=cls

Então, envie uma requisição POST para essa URL comrequest.post(url). Pronto! Agora você já pode ver uma classe chamada CLASSNAME no schema padrão ISC_DM, no namespace selecionado.

Após criar uma classe, você pode adicionar propriedades a ela mandando mais requisições POST com uma URL do seguinte tipo:

http://HOST:PORT/api/docdb/v1/NAMESPACE/prop/DBNAME/PROPERTYNAME?type=%String&path=PROPERTYPATH

Você pode perceber o caminho da propriedade como o caminho que você usaria para obter o valor nela definido, caso estivesse num objeto dinâmico construído de um JSON. Por exemplo, imagine que você pode representar um objeto como no bloco de código abaixo.

{
    "person": {
        "name":"heloisa tambara",
        "country":"brazil"
    }
}

 Nesse caso, o caminho para a propriedade nome seria person.name.

Finalmente, você pode começar a popular essa tabela com um outro padrão de URL:

http://HOST:PORT/api/docdb/v1/NAMESPACE/doc/DBNAME/ID

Se quiser criar um novo documento, uses o método POST e deixe o campo ID vazio. Por outro lado, para substituir um documento existente, use o método PUT e especifique o ID que deseja modificar.

Escreva o corpo da sua requisição de acordo com os caminhos de propriedades empregados. Por exemplo, se você criou algumas propriedades com os caminhos "person.name", "person.location.country", "person.location.state", "person.location.city", você pode adicionar um documento enviado o JSON abaixo no corpo da sua requisição.

{
    "person": {
        "name":"Heloisa Tambara",
        "location": {
            "country":"Brasil",
            "state":"Pernambuco",
            "city":"Recife"
        }
    }
}

Essa seção foi designada para te dar apenas um gostinho da capacidade do DocDB. Na documentação que você pode acessar clicando aqui, você pode descobrir todos os métodos disponíveis em mais detalhes.

Indo mais a fundo: usar interoperabilidade IRIS sem ObjectScript

Para a maioria das implementações, você pode praticamente abolir o uso de classes COS. Suponha que você está procurando por uma produção completa construída apenas com Python. Nesse caso, você pode experimentar o PEX (Production EXtension framework) e limitar o uso de arquivos .cls para a classe da produção apenas. A melhor prática para usar PEX é utilizar a aplicação do Guillaume Rongier (interoperability-embedded-python), que reduz as diferenças entre a arquitetura InterSystems para interoperabilidade e o Python. Se você nõ está familiarizado com essa estrutura ainda, vale a pena dar uma olhada no curso de 30 minutos dedicado à Arquitetura de Integração.

Se esse é seu objetivo, eu recomendo que você leia o artigo Full Python IRIS production: DataTransformation of a CSV to a FHIR server de Lucas Enard. Aa página do GitHub relacionada à aplicação OpenExchange descrita no texto mostra um ótimo exemplo de como atingir um desenvolvimento quase 100% Python.

 

Sempre tem mais...

Como você pode ver, há muitas maneiras de criar, manipular e popular classes em IRIS. Você já conhecia todas essas descritas acima? Qual você gostaria de ler mais a respeito? Que outras maneiras você conhece que eu ainda não descrevi? Por favor, compartilhe nos comentários o que você pensa!

Discussão (0)1
Entre ou crie uma conta para continuar