Article Sylvain Guilbaud · Oct 19, 2023 6m read

Cet article a été écrit en réponse à un message de la communauté qui demandait si Python pouvait créer des messages HL7 de manière dynamique.

Conditions préalables et configuration

Utilisez un espace de noms compatible avec l'intégration.
Remarque : l'espace de noms USER n'est pas activé pour l'interopérabilité par défaut.
Si nécessaire, créez un nouvel espace de noms interopérable afin d'explorer les fonctionnalités.

# Passage à
ZN "[Espace de nom pour l'interopérabilité]"

# Lancement d'un shell interactif Python :
Exécuter $SYSTEM.Python.Shell()

Début du script

#Chargement des dépendances

import datetime as dt
import uuid

# L'heure actuelle du cache est exprimée au format AAAAMMJJHHMMss.
hl7_datetime_now=dt.datetime.now().strftime('%Y%m%d%H%M%S')

# Création d'un message HL7
hl7=iris.cls("EnsLib.HL7.Message")._New()

# Définition du type de document
# 2.5.1:ORU_R01 - Envoi non sollicité d'un message d'observation
hl7.PokeDocType("2.5.1:ORU_R01")

Les structures de ces messages sont accessibles à partir du portail de gestion

 

Création du MSH (segment d'en-tête de message)

// Segment MSH
hl7.SetValueAt('OutApp','MSH:SendingApplication')
hl7.SetValueAt('OutFac','MSH:SendingFacility')
hl7.SetValueAt('InApp','MSH:ReceivingApplication')
hl7.SetValueAt('InFac','MSH:ReceivingFacility')
hl7.SetValueAt(hl7_datetime_now,'MSH:DateTimeOfMessage')
hl7.SetValueAt('ORU','MSH:MessageType.MessageCode')
hl7.SetValueAt('R01','MSH:MessageType.TriggerEvent')
hl7.SetValueAt('ORU_R01','MSH:MessageType.MessageStructure')
hl7.SetValueAt(str(uuid.uuid4()),'MSH:MessageControlID')
hl7.SetValueAt('2.5.1','MSH:ProcessingID')

Fonction d'échappement et d'annulation ("Escape" ou "Unescape")

Les documents HL7 sont structurés en segments
Chaque segment est divisé en Éléments par un délimiteur ("|") et en Éléments répétitifs ("~").
Un élément comporte un délimiteur "^" et un sous-délimiteur "&".
Lorsque le délimiteur apparaît en tant que contenu textuel, il est échappé par "" et d'autres caractères qui remplacent les délimiteurs.
Le caractère "&" est souvent problématique, car il peut apparaître fréquemment dans les messages et entraîner une troncature lors de la lecture par le système de réception.
Un segment HL7 dispose d'une méthode intégrée pour échapper le contenu en fonction des délimiteurs choisis pour un message.
Un modèle commun est d'obtenir une référence au premier segment

# Exécution de cette ligne; la variable "msh" sera utilisée ultérieurement.
> msh=hl7.GetSegmentAt(1)

Ensuite, on peut appeler Escape (échappement) par exemple avec la chaîne brute de Python :

> msh.Escape(r"a&b~c^d")
'a\\T\\b\\R\\c\\S\\d'

Le segment peut également être utilisé pour annuler la fonction Unescape, par exemple :

> msh.Unescape('a\\T\\b\\R\\c\\S\\d')
'a&b~c^d'

Ainsi, lors de la définition d'un contenu qui devrait comporter des caractères de délimitation, ces caractères peuvent être échappés pour le message

hl7.SetValueAt(msh.Escape(r"a&b~c^d"),'MSH:ReceivingFacility')

Lors de la récupération du contenu, il est possible d'annuler l'echappement

msh.Unescape(hl7.GetValueAt('MSH:ReceivingFacility'))

Pour cet exemple, il suffit de rétablir la valeur précédente de msh.

hl7.SetValueAt('InFac','MSH:ReceivingFacility')

Pour la revérification du segment existant :

> hl7.GetValueAt('MSH')
'MSH|^~\\&|OutApp|OutFac|InApp|InFac|20230610100040||ORU^R01^ORU_R01|2dfab415-51aa-4c75-a7e7-a63aedfb53cc|2.5.1'

Segment démographique (PID)

# Préfixe du chemin virtuel pour l'identifiant PID
seg='PIDgrpgrp(1).PIDgrp.PID:'
hl7.SetValueAt('1',seg+'SetIDPID')
hl7.SetValueAt('12345',seg+'PatientIdentifierList(1).IDNumber')
hl7.SetValueAt('MRN',seg+'PatientIdentifierList(1).AssigningAuthority')
hl7.SetValueAt('MR',seg+'PatientIdentifierList(1).IdentifierTypeCode')
hl7.SetValueAt(msh.Escape('Redfield'), seg+'PatientName(1).FamilyName')
hl7.SetValueAt(msh.Escape('Claire') ,seg+'PatientName(1).GivenName')
hl7.SetValueAt('19640101',seg+'DateTimeofBirth')
hl7.SetValueAt('F',seg+'AdministrativeSex')
hl7.SetValueAt(msh.Escape('Umbrella Corporation') ,seg+'PatientAddress.StreetAddress')
hl7.SetValueAt(msh.Escape('Umbrella Drive') ,seg+'PatientAddress.OtherDesignation')
hl7.SetValueAt(msh.Escape('Raccoon City') ,seg+'PatientAddress.City')
hl7.SetValueAt(msh.Escape('MO') ,seg+'PatientAddress.StateorProvince')
hl7.SetValueAt(msh.Escape('63117') ,seg+'PatientAddress.ZiporPostalCode')

Revérification du contenu du segment PID

> hl7.GetValueAt(seg[0:-1])
'PID|1||12345^^^MRN^MR||Redfield^Claire||19640101|F|||Umbrella Corporation^Umbrella Drive^Raccoon City^MO^63117'

Segment de contrôle d'ordre

seg='PIDgrpgrp(1).ORCgrp(1).ORC:'
hl7.SetValueAt('RE',seg+'OrderControl')
hl7.SetValueAt('10003681',seg+'PlacerOrderNumber')
hl7.SetValueAt('99001725',seg+'FillerOrderNumber')
hl7.SetValueAt('AG104',seg+'OrderingProvider')
hl7.SetValueAt('L43',seg+'EnterersLocation')

Revérification du contenu des segments ORC (segments de contrôle d'ordre)

> hl7.GetValueAt(seg[0:-1])
'ORC|RE|10003681|99001725|||||||||AG104|L43'

 

Demande d'observation

seg='PIDgrpgrp(1).ORCgrp(1).OBR:'
hl7.SetValueAt('1',seg+'SetIDOBR')
hl7.SetValueAt('10003681',seg+'PlacerOrderNumber')
hl7.SetValueAt('99001725',seg+'FillerOrderNumber')
hl7.SetValueAt('20210428100729',seg+'ResultsRptStatusChngDateTime')
hl7.SetValueAt('F',seg+'ResultStatus')
hl7.SetValueAt('U',seg+'QuantityTiming.Priority')

 

Observation OBX/Résultat

seg='PIDgrpgrp(1).ORCgrp(1).OBXgrp(1).OBX:'
hl7.SetValueAt('1',seg+'SetIDOBX')
hl7.SetValueAt('TX',seg+'ValueType')
hl7.SetValueAt('V8132',seg+'ObservationIdentifier.Identifier')
hl7.SetValueAt(msh.Escape('G-Virus') , seg+'ObservationIdentifier.Identifier')
hl7.SetValueAt(msh.Escape('17.8 log10') ,seg+'ObservationValue')
hl7.SetValueAt(msh.Escape('RNA copies/mL') ,seg+'Units')
hl7.SetValueAt('F',seg+'ObservationResultStatus')
hl7.SetValueAt('20210428100729',seg+'DateTimeoftheObservation')
hl7.SetValueAt('AG001',seg+'ResponsibleObserver.IDNumber')
hl7.SetValueAt('Birkin',seg+'ResponsibleObserver.FamilyName')
hl7.SetValueAt('William',seg+'ResponsibleObserver.GivenName')
hl7.SetValueAt('AG001',seg+'ResponsibleObserver.IDNumber')
hl7.SetValueAt('UXL43',seg+'EquipmentInstanceIdentifier')

 

NTE - Remarques et commentaires

seg='PIDgrpgrp(1).ORCgrp(1).OBXgrp(1).NTE(1):'
hl7.SetValueAt('1',seg+'SetIDNTE')
hl7.SetValueAt(msh.Escape('Expected late onset Hyphema. Contain but do not approach.') ,seg+'Comment')

 

Affichage du message complet sur le terminal

> print(hl7.OutputToString())

MSH|^~\&|OutApp|OutFac|InApp|InFac|20230610141201||ORU^R01^ORU_R01|2dfab415-51aa-4c75-a7e7-a63aedfb53cc|2.5.1
PID|1||12345^^^MRN^MR||Redfield^Claire||19640101|F|||Umbrella Corporation^Umbrella Drive^Raccoon City^MO^63117
ORC|RE|10003681|99001725|||||||||AG104|L43
OBR|1|10003681|99001725|||||||||||||||||||20210428100729|||F||^^^^^U
OBX|1|TX|G-Virus||17.8 log10|RNA copies/mL|||||F|||20210428100729||AG001^Birkin^William||UXL43
NTE|1||Expected late onset Hyphema. Contain but do not approach.

Pièges

Si le contenu d'un élément comporte une valeur telle que "8@%SYS.Python", il est probable que la valeur "string" ou la propriété "string" ait été demandée à la place.

Par exemple, uuid a été enveloppé par "str" dans la structure de MSH.

0
1 122
Article Sylvain Guilbaud · Oct 2, 2023 13m read

Pour le prochain Concours Python, j'aimerais faire une petite démo, sur la création d'une simple application REST en Python, qui utilisera IRIS comme base de données. Et utiliser les outils suivants

  • Le cadre FastAPI, très performant, facile à apprendre, rapide à coder, prêt pour la production.
  • SQLAlchemy est la boîte à outils SQL et le Mapping objet-relationnel de Python qui donne aux développeurs en Python toute la puissance et la flexibilité de SQL.
  • Alembic est un outil léger de migration de base de données à utiliser avec le SQLAlchemy Database Toolkit pour Python.
  • Uvicorn est une implémentation de serveur web ASGI pour Python.

Préparation de l'environnement

En supposant que Python soit déjà installé, au moins en version 3.7., il faut créer un dossier de projet, et y créer un fichier requirements.txt avec le contenu suivant

fastapi==0.101.1
alembic==1.11.1
uvicorn==0.22.0
sqlalchemy==2.0.20
sqlalchemy-iris==0.10.5

 Je vous conseille d'utiliser l'environnement virtuel en python, nous allons créer un nouvel environnement et l'activer.

python -m venv env && source env/bin/activate

Et maintenant, nous pouvons installer nos dépendances

pip install -r requirements.txt

Démarrage rapide

Créons l'Api REST la plus simple avec FastAPI. Pour ce faire, créons app/main.py

from fastapi import FastAPI

app = FastAPI(
    title='TODO Application',
    version='1.0.0',
)

@app.get("/ping")asyncdefpong():return {"ping": "pong!"}

Pour l'instant, il suffit de démarrer notre application, et elle devrait déjà fonctionner. Pour démarrer le serveur, nous allons utiliser uvicorn

$ uvicorn app.main:app         
INFO:     Processus de serveur lancé [94936]
INFO:     En attente du lancement de l'application.
INFO:     Application startup compléte.
INFO:     Uvicorn fonctionne sur http://127.0.0.1:8000 ( Appuyez sur CTRL+C pour quitter)

Et nous pouvons soumettre une requête de ping.

$ curl http://localhost:8000/ping
{"ping":"pong!"}

FastAPI propose une interface utilisateur permettant de tester l'API.

Environnement Dockerisé

Pour ajouter IRIS à notre application, nous allons utiliser des conteneurs. L'image d'IRIS sera utilisée telle quelle, mais il nous faut construire une image Docker pour l'application python. Et nous aurons besoin de Dockerfile

FROM python:3.11-slim-buster

WORKDIR /usr/src/app
RUN --mount=type=bind,src=.,dst=. \
    pip install --upgrade pip && \
    pip install -r requirements.txt
COPY . .
ENTRYPOINT [ "/usr/src/app/entrypoint.sh" ]

Pour lancer l'application à l'intérieur du conteneur, il faut un simple entrypoint.sh.

#!/bin/sh
# Exécution des migrations SQL, pour mettre à jour le schéma de la base de données
alembic upgrade head

# Lancement de l'application Python
uvicorn app.main:app \
      --workers 1 \
      --host 0.0.0.0 \
      --port 8000 "$@"

N'oubliez pas d'ajouter un drapeau d'exécution

chmod +x entrypoint.sh

Et combinez avec IRIS dans docker-compose.yml

version:"3"services:  iris:    image:intersystemsdc/iris-community    ports:      -1972    environment:      -IRISUSERNAME=demo      -IRISPASSWORD=demo    healthcheck:      test:/irisHealth.sh      interval:5s  app:    build:.    ports:      -8000:8000    environment:      -DATABASE_URL=iris://demo:demo@iris:1972/USER    volumes:      -./:/usr/src/app    depends_on:      iris:        condition:service_healthy    command:      ---reload

Construisons-le

docker-compose build

Le premier modèle de données

Maintenant, déclarons l'accès à notre base de données IRIS à l'application, en ajoutant le fichier app/db.py, qui configurera SQLAlchemy pour accéder à notre base de données définie à travers l'URL passée par docker-compose.yml. Ce fichier contient également quelques gestionnaires que nous utiliserons plus tard dans l'application.

import os

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import DeclarativeMeta, declarative_base
from sqlalchemy.orm import sessionmaker

DATABASE_URL = os.environ.get("DATABASE_URL")
ifnot DATABASE_URL:
    DATABASE_URL = "iris://demo:demo@localhost:1972/USER"
engine = create_engine(DATABASE_URL, echo=True, future=True)

Base: DeclarativeMeta = declarative_base()

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)


definit_db():
    engine.connect()


defget_session():
    session = SessionLocal()
    yield session

Et nous sommes prêts à définir le premier et unique modèle de notre application. Nous créons et éditons le fichier app/models.py, il utilisera SQLAlchemy pour définir le modèle, nommé Todo, à trois colonnes, id, title, et description.

from sqlalchemy import Column, Integer, String, Text
from app.db import Base


classTodo(Base):
    __tablename__ = 'todo'
    id = Column(Integer, primary_key=True, index=True)
    title = Column(String(200), index=True, nullable=False)
    description = Column(Text, nullable=False)

Préparation de la migration SQL

Dans ce monde changeant, nous savons que notre application sera améliorée à l'avenir, que la structure de nos tableaux n'est pas définitive, que nous pouvons ajouter des tableaux, des colonnes, des index, etc. Dans ce cas, le meilleur scénario consiste à utiliser des outils de migration SQL, qui permettent de mettre à jour la structure actuelle de la base de données en fonction de la version de notre application, et grâce à ces outils, il est également possible de la rétrograder, au cas où quelque chose ne fonctionnerait pas. Bien que dans ce projet nous utilisions Python et SQLAlchemy, l'auteur de SQLAlchemy propose son outil nommé Alembic, et nous allons l'utiliser ici.

We need to start IRIS and container with our application, at this moment we need bash, to be able to run commands

$ docker-compose run --entrypoint bash app
[+] Creating 2/0
 ✔ Réseau  fastapi-iris-demo_default   Crée                                                                                                                                                        0.0s 
 ✔ Conteneur fastapi-iris-demo-iris-1  Crée                                                                                                                                                        0.0s 
[+] Exécution 1/1
 ✔ Conteneur fastapi-iris-demo-iris-1  Lancé                                                                                                                                                        0.1s 
root@7bf903cd2721:/usr/src/app# 

Exécution de la commande alembic init app/migrations

root@7bf903cd2721:/usr/src/app# alembic init app/migrations
  Création du répertoire '/usr/src/app/app/migrations' ...  exécuté
  Création du répertoire '/usr/src/app/app/migrations/versions' ...  exécuté
  Génération de /usr/src/app/app/migrations/README ...  exécuté
  Génération de /usr/src/app/app/migrations/script.py.mako ...  exécuté
  Génération de /usr/src/app/app/migrations/env.py ...  exécuté
  Génération de /usr/src/app/alembic.ini ...  exécuté
  Veuillez modifier les paramètres de configuration/connexion/logging dans '/usr/src/app/alembic.ini' avant de continuer.
root@7bf903cd2721:/usr/src/app#

Cette configuration alembic a été préalablement configurée, et nous devons la corriger pour qu'elle corresponde aux besoins de notre application. Pour ce faire, il faut éditer le fichier app/migrations/env.py. Ce n'est que le début du fichier, qui doit être mis à jour, en se concentrant sur la mise à jour de sqlalchemy.url et target_metadata. Ce qui se trouve en dessous reste inchangé

import os
import urllib.parse
from logging.config import fileConfig

from sqlalchemy import engine_from_config
from sqlalchemy import pool

from alembic import context

# il s'agit de l'objet Alembic Config, qui permet# d'accéder aux valeurs du fichier .ini utilisé.
config = context.config

DATABASE_URL = os.environ.get("DATABASE_URL")

decoded_uri = urllib.parse.unquote(DATABASE_URL)
config.set_main_option("sqlalchemy.url", decoded_uri)

# Interprétation du fichier de configuration pour l'enregistrement Python.# Cette ligne met en place les enregistreurs de façon basique.if config.config_file_name isnotNone:
    fileConfig(config.config_file_name)

# ajoutez ici l'objet MetaData de votre modèle# pour la prise en charge de l'autogénérationfrom app.models import Base
target_metadata = Base.metadata
# target_metadata = non applicable

Nous avons déjà un modèle, maintenant il faut créer une migration, avec la commande alembic revision --autogenerate (alembic revision ---autogénérer).

root@7bf903cd2721:/usr/src/app# alembic revision --autogenerate
INFO  [alembic.runtime.migration] Contexte impl IRISImpl.
INFO  [alembic.runtime.migration] Cela suppose un DDL non transactionnel.
INFO  [alembic.autogenerate.compare] Détection du tableau "todo" ajouté
INFO  [alembic.autogenerate.compare] Détection d'un index ajouté 'ix_todo_id' sur '['id']'
INFO  [alembic.autogenerate.compare] Détection d'un index ajouté 'ix_todo_title' sur '['title']'
  Generating /usr/src/app/app/migrations/versions/1e4d3b4d51ca_.py ... exécuté
root@7bf903cd2721:/usr/src/app# 
 
Let's see generated migration

Maintenant il faut appliquer ceci à la base de données, avec la commande alembic upgrade head, où "head" est un mot-clé pour mettre à jour vers la dernière version.

root@7bf903cd2721:/usr/src/app# alembic upgrade head
INFO  [alembic.runtime.migration] Contexte impl IRISImpl.
INFO  [alembic.runtime.migration] Cela suppose un DDL non transactionnel.
INFO  [alembic.runtime.migration] Exécution de la mise à jour -> 1e4d3b4d51ca, message vide
 
Rétrogradation
Si, au cours de la mise à jour de l'application, nous découvrons que nous devons revenir en arrière, nous pouvons rétrograder la base de données, par exemple la dernière révision sera head-1.
<pre>root@7bf903cd2721:/usr/src/app# alembic downgrade head-1

INFO  [alembic.runtime.migration] Contexte impl IRISImpl. INFO  [alembic.runtime.migration] Cela suppose un DDL non transactionnel. INFO  [alembic.runtime.migration] Exécution de la rétrogradation 1e4d3b4d51ca -> , message vide

<p>
  et pour rétrograder complètement vers un état vide, utilisez le mot-clé <strong>base</strong>
</p>

Vérifiez l'état actuel à tout moment, ce qui vous donnera des informations sur les migrations manquantes.

root@7bf903cd2721:/usr/src/app# alembic check
INFO  [alembic.runtime.migration] Contexte impl IRISImpl.
INFO  [alembic.runtime.migration] Cela suppose un DDL non transactionnel.
Aucune nouvelle opération de mise à jour détectée.

Accessibilité des données

Donc, nous pouvons maintenant retourner au REST, et il nous faut le faire fonctionner, quitter le conteneur actuel et lancer le service d'application comme d'habitude maintenant, uvicorn a un drapeau --reload, donc, il vérifiera les changements dans les fichiers python et redémarrera lorsque nous les changerons.

$ docker-compose up app
[+] Running 2/0
 ✔ Conteneur fastapi-iris-demo-iris-1 Lancé                                                                                                                                                        0.0s 
 ✔ Conteneur fastapi-iris-demo-app-1   Crée                                                                                                                                                       0.0s 
Attaching to fastapi-iris-demo-app-1, fastapi-iris-demo-iris-1
fastapi-iris-demo-app-1   | INFO  [alembic.runtime.migration] Contexte impl IRISImpl.
fastapi-iris-demo-app-1   | INFO  [alembic.runtime.migration] Cela suppose un DDL non transactionnel.
fastapi-iris-demo-app-1   | INFO:     Surveillance des modifications apportées aux répertoires : ['/usr/src/app']
fastapi-iris-demo-app-1   | INFO:     Uvicorn lancé sur http://0.0.0.0:8000 (Appuyez sur CTRL+C pour quitter)
fastapi-iris-demo-app-1   | INFO:     Lancement du processus de rechargement [8] à l'aide de StatReload
fastapi-iris-demo-app-1   | INFO:     Lancement du processus de serveur [10]
fastapi-iris-demo-app-1   | INFO:     En attente du démarrage de l'application.
fastapi-iris-demo-app-1   | INFO:     Démarrage de l'application achevé.

FastAPI utilise le projet pydantic, pour déclarer le schéma de données, et nous en avons besoin aussi, créons app/schemas.py, les mêmes colonnes que dans models.py mais sous une forme simple en Python

from pydantic import BaseModel


classTodoCreate(BaseModel):
    title: str
    description: str


classTodo(TodoCreate):
    id: int

    classConfig:
        from_attributes = True

Déclaration des opérations crud dans app/crud.py, où nous travaillons avec la base de données en utilisant l'ORM de SQLAlchemy.

from sqlalchemy.orm import Session
from . import models, schemas


defget_todos(db: Session, skip: int = 0, limit: int = 100):return db.query(models.Todo).offset(skip).limit(limit).all()


defcreate_todo(db: Session, todo: schemas.TodoCreate):
    db_todo = models.Todo(**todo.dict())
    db.add(db_todo)
    db.commit()
    db.refresh(db_todo)
    return db_todo

Pour finir, nous pouvons mettre à jour notre app/main.py, et ajouter des itinéraires pour lire et créer des todos.

from fastapi import FastAPI, Depends
from .db import init_db, get_session
from . import crud, schemas

app = FastAPI(
    title='TODO Application',
    version='1.0.0',
)


@app.on_event("startup")defon_startup():
    init_db()


@app.get("/ping")asyncdefpong():return {"ping": "pong!"}


@app.get("/todo", response_model=list[schemas.Todo])asyncdefread_todos(skip: int = 0, limit: int = 100, session=Depends(get_session)):
    todos = crud.get_todos(session, skip=skip, limit=limit)
    return todos


@app.post("/todo", response_model=schemas.Todo)asyncdefcreate_todo(todo: schemas.TodoCreate, session=Depends(get_session)):return crud.create_todo(db=session, todo=todo)

La page de documentation "docs" a été mise à jour en conséquence, et nous pouvons maintenant jouer avec.

 
Essayez !
Ajouter une nouvelle todo
<p>
  <img src="/sites/default/files/inline/images/images/image(6813).png" />
</p>

<p>
  Et vérifiez ce que nous avons ici
</p>

<p>
  <img src="/sites/default/files/inline/images/images/image(6814).png" />
</p>

Vérifions-le dans IRIS

─$ docker-compose exec iris irissqlcli iris+emb:///
Serveur:  IRIS pour UNIX (Ubuntu Server LTS pour les conteneurs "ARM64 Containers") 2023.2 (Build 227U) Mon Jul 31 2023 17:43:25 EDT
Version: 0.5.4
[SQL]irisowner@/usr/irissys/:USER> .tables
+-------------------------+
| TABLE_NAME              |
+-------------------------+
| SQLUser.alembic_version |
| SQLUser.todo            |
+-------------------------+
Temps: 0.043s
[SQL]irisowner@/usr/irissys/:USER> select * from todo
+----+-------+---------------------+
| id | titre | description         |
+----+-------+---------------------+
| 1  | démo  | cela marche vraiment |
+----+-------+---------------------+
1 rang dans le jeu
Temps: 0.004s
[SQL]irisowner@/usr/irissys/:USER> select * from alembic_version
+--------------+
| version_num  |
+--------------+
| 1e4d3b4d51ca |
+--------------+
1 rang dans le jeu
Temps: 0.045s
[SQL]irisowner@/usr/irissys/:USER>

 

J'espère que vous avez apprécié la facilité d'utilisation de Python et de FastAPI pour la création de REST. Le code source de ce projet est disponible sur github https://github.com/caretdev/fastapi-iris-demo

0
0 126
Article Sylvain Guilbaud · Sept 20, 2023 1m read

La méthode InstallFoundation est manquante (IRIS 2023.2+)

IRIS 2023.2 est récemment sorti. Cette version a supprimé cette méthode InstallFoundation de cette classe HS.HC.Util.Installer. Il s’agissait d’une méthode privée et elle n’était pas documentée. Mais il a été largement utilisé par la communauté pour installer le serveur FHIR.

Donc si vous rencontrez cette erreur :

<METHOD DOES NOT EXIST> *InstallFoundation,HS.HC.Util.Installer

Pendant que vous créez une démo sur votre propre serveur FHIR, vous pouvez le corriger en remplaçant cette ligne :

  do ##class(HS.HC.Util.Installer).InstallFoundation(namespace)

par

  Do ##class(HS.Util.Installer.Foundation).Install(namespace)
0
0 53
Article Sylvain Guilbaud · Sept 14, 2023 8m read

Aperçu

La documentation en ligne contient une référence expliquant comment définir et utiliser les requêtes de classes.

La personnalisation des procédures stockées en ObjectScript s'est avérée utile pour accéder au stockage NoSQL et à la messagerie externe via l'intégration, afin de présenter la sortie sous forme de tableau.

Par exemple : une application qui utilise déjà 90 % d'interaction SQL depuis un frontal peut alors également étendre cet accès aux 10 % restants des fonctionnalités requises de la plate-forme, via le même accès SQL.

0
0 106
Annonce Sylvain Guilbaud · Sept 13, 2023

L'équipe InterSystems se rend ce week-end au plus grand hackathon du MIT, où nous présenterons un défi technologique pour les hackers.
Nous proposons aux hackers d'utiliser IntegratedML ou InterSystems Supply Chain Orchestrator dans leurs projets afin de concourir pour des prix vraiment sympas !

Si vous êtes à Boston et que vous êtes intéressé pour devenir un mentor InterSystems lors de l'événement, envoyez-moi un message.

 

2
0 77
Discussion Sylvain Guilbaud · Sept 12, 2023

Je gère mes collections d'avis sur OpenExchange depuis maintenant plus de 3 ans.
J'ai expliqué le principe que j'applique dans un article précédent.

Ces avis constituent la première étape du contrôle de qualité chez OEX.

Mon credo personnel
Mon attente de l'OEX (exprimée à l'extrême) est de le voir plutôt comme
une collection de bijoux, qu'un simple marché aux puces.

Je lance cette discussion encouragé par @Evgeny Shvarov dans son commentaire recent 

4
1 81
Discussion Sylvain Guilbaud · Sept 12, 2023

Je reçois généralement des plaintes de nos clients concernant l'actualisation automatique des pages Web BPL et DTL. C'est un problème courant parmi les utilisateurs débutants, mais pour les développeurs expérimentés aussi, ils oublient d'enregistrer les modifications régulièrement et automatiquement la page Web est rechargée, perdant tout le travail effectué.

0
0 46
Discussion Sylvain Guilbaud · Sept 11, 2023

Actuellement, les privilèges SQL (SELECT, INSERT, UPDATE, DELETE) sont gérés au niveau des tables, ce qui peut s'avérer très fastidieux lorsque vous devez administrer de nombreux rôles dans une organisation et les synchroniser avec des modèles de données en constante évolution.
En gérant les privilèges au niveau des schémas, cela permettra d'accorder des privilèges SELECT et d'autres privilèges DML à *tous* ou *plusieurs schémas* à un rôle|utilisateur, corrigeant ainsi le besoin de synchroniser manuellement les nouvelles tables|vues avec les rôles.

4
0 90
Article Sylvain Guilbaud · Sept 6, 2023 3m read

pour démonter/monter une base de données, utilisez les méthodes Dismount() et Mount() dans la classe SYS.Database disponible dans l'espace de noms %SYS.
NB : l'ID de la base de données est le nom du chemin absolu de son répertoire.

Vous trouverez quelques exemples de démontage/montage et de méthodes contrôlant si une base de données est montée (Mounted=1) ou non (Mounted=0), ou affichant rapidement tous les attributs d'une base de données (via zwrite)

0
0 121
Article Sylvain Guilbaud · Sept 6, 2023 10m read

Salut la communauté

Dans cet article, nous allons apprendre les sujets ci-dessous répertoriés ci-dessous :

  1. Qu'est-ce que Docker ?
  2. Certains des avantages de Docker
  3. Comment fonctionne Docker ?
  4. Image Docker
  5. Conteneur Docker
  6. Dépôt d'images Docker
  7. Dépôt d'images Docker d'InterSystems
  8. Installation de Docker
  9. Commandes de base de Docker
  10. Exécution de l'édition communautaire IRIS à l'aide de Docker
  11. Interface graphique du bureau Docker

Alors commençons.


1. Qu’est-ce que Docker ?

0
0 273
Article Sylvain Guilbaud · Sept 6, 2023 9m read

Salut la communauté,


Dans mon article précédent, nous avons appris les sujets répertoriés ci-dessous :

  1. Qu’est-ce que Docker ?
  2. Certains des avantages de Docker
  3. Comment fonctionne Docker ?
  4. Image Docker
  5. Conteneur Docker
  6. Dépôt d'images Docker
  7. Dépôt d'images Docker d'InterSystems
  8. Installation de Docker
  9. Commandes de base de Docker
  10. Exécution de l'édition communautaire IRIS à l'aide de Docker
  11. Interface graphique du bureau Docker

Dans cet article, nous aborderons les sujets suivants

  1. Utilisation du fichier Docker Compose (un fichier YAML)
  2. Utilisation du fichier Docker (utilisé pour créer une image Docker)
  3. Utilisation du volume Docker

Alors commençons.

0
0 781
Discussion Sylvain Guilbaud · Sept 4, 2023

Je travaille avec des clients qui envisagent de migrer de Caché vers IRIS et je souhaite résumer les avantages d'aller vers IRIS. Je pense à ceux-ci:

  1. IntegratedML - AutoML - Agile machine learning
  2. IAM - InterSystems API Manager
  3. Interopérabilité
  4. Advanced Reports (JReport)
  5. Cloud Manager/Docker et support DevOps
  6. ZPM - Package manager
  7. Native API - Node.js, Python, Java and .NET interoperability
  8. Licence basée sur le cœur x licence basée sur l'utilisateur
  9. Support InterSystems et nouvelles fonctionnalités
  10. Fonctionnalités de gestion et de surveillance améliorées
3
0 90
Article Sylvain Guilbaud · Sept 4, 2023 6m read

Lorsque nous démarrons le développement avec IRIS, nous disposons d'un kit de distribution ou, dans le cas de Docker, nous extrayons l'image Docker, puis nous devons souvent l'initialiser et configurer l'environnement de développement. Nous devrons peut-être créer des bases de données, des espaces de noms, activer/désactiver certains services, créer des ressources. Nous devons souvent importer du code et des données dans l'instance IRIS et exécuter du code personnalisé pour lancer la solution.

Il existe de nombreux modèles sur Open Exchange dans lesquels nous suggérons comment initialiser REST, l'interopérabilité, l'analytics, le développement Fullstack et bien d'autres modèles utilisant ObjectScript. Mais qu'en est-il si nous souhaitons utiliser uniquement Python pour configurer l'environnement de développement d'un projet Embedded Python avec IRIS ?

De fait, la récente sortie de Embedded Python template est devenu le passe-partout du pur Python qui pourrait être un point de départ pour les développeurs qui créent des projets Python sans avoir besoin d'utiliser et d'apprendre ObjectScript. Cet article explique comment ce modèle pourrait être utilisé pour initialiser IRIS. C'est parti!

0
0 80
Article Sylvain Guilbaud · Août 31, 2023 7m read

Description du cas

Imaginons que vous soyez un développeur Python ou que vous disposiez d'une équipe bien formée et spécialisée en Python, mais que le délai dont vous disposez pour analyser certaines données dans IRIS est serré. Bien entendu, InterSystems propose de nombreux outils pour toutes sortes d’analyses et de traitements. Cependant, dans le scénario donné, il est préférable de faire le travail en utilisant les bons vieux Pandas et de laisser l'IRIS pour une autre fois.

0
0 125
Question Sylvain Guilbaud · Août 28, 2023

Je recherche dans DBeaver un moyen efficace permettant de filtrer les tables systèmes (ex: appartenant à un schéma commençant par "%").

En utilisant un utilisateur possédant le rôle %All, DBeaver nous affiche une longue liste de schémas systèmes, qui nous oblige à descendre la liste avant d'accéder aux tables utilisateurs.

En créant un utilisateur dans IRIS avec des droits restreints permet de réduire cette liste, mais on perd l'intérêt du rôle %All.

3
0 446
Article Sylvain Guilbaud · Août 25, 2023 1m read

Rubrique FAQ InterSystems

Vous pouvez voir l'espace disponible libre pour la base de données à l'aide du bouton radio « Vue de l'espace libre » dans le portail de gestion : Exploitation du système > Bases de données.

Et il peut être obtenu par programmation par la requête FreeSpace de la classe système SYS.Database.

0
0 70