[PYTHON] Generieren Sie automatisch Objektspezifikationen mit Blue Prism

Einführung

In Blue Prism sind die Teile, die die Anwendung Object tatsächlich betreiben, und die Teile, die die Geschäftslogik Process schreiben, getrennt. Dies ist ein Mechanismus zur Verbesserung der Wiederverwendbarkeit. Um die Wiederverwendung von Objekten innerhalb des Teams zu fördern, muss ein Dokument "Welche Art von Objekt ist vorhanden" erstellt und verwaltet werden. Es ist jedoch schwierig, es von Hand zu erstellen und zu verwalten, und der Inhalt des Objekts wurde aktualisiert. Es kann Probleme geben, z. B. nicht folgen zu können.

Dieser Artikel befasst sich mit der Geschichte der automatischen Generierung von Dokumentation zu solchen wichtigen Objekten (ODI: Object Design Instruction in Blue Prism Terminologie).

Es gibt einen VBO namens "Object Inventory"! Funktioniert nicht. .. ..

Ich habe ein VBO namens "Object Inventory" in Ditigal Exchange (https://digitalexchange.blueprism.com/dx/entry/3439/solution/object-inventory), aber das Trimmen von Zeichenfolgen basiert auf Englisch. Oder ich habe einen mysteriösen Excel-Fehler erhalten (`` `Ausnahme: Ausnahme von HRESULT: 0x800A03EC```) und es hat nicht funktioniert. .. ..

Es gab jedoch die folgende Beschreibung auf der Hilfeseite.

This asset is a business object that uses the output from the BP command line /getbod function to create a list of all business objects, pages, descriptions, inputs and outputs.



 Die Tatsache, dass AutomateC.exe einen Schalter namens `` `/ getbod``` hat, bedeutet, dass die Hilfe [Befehlszeilenoptionen](https://bpdocs.blueprism.com/bp-6-8/ja-jp/helpCommandLine). Es ist auch nicht in htm) geschrieben. .. ..

# Schalter namens / listprocesses und / getbod
 Wenn man sich das VBO "Objektinventar" oben ansieht, scheint es, dass der Schalter `` `/ listprocesses``` eine Liste von Prozessen und Objekten erhält und für jedes` `/ getbod``` aufruft. Wenn das Ziel "Prozess" ist, werden die Zeichenfolgen "Geschäftsobjekt konnte nicht gefunden" zurückgegeben. Es scheint also, dass sie vom Verarbeitungsziel ausgeschlossen sind.

```/getbod```Der Schalter existierte wirklich!

# Versuchen Sie, mit Python zu implementieren

 Es ist ein schlechtes Skript, aber es funktioniert. Wir hoffen auf Ihre Referenz. (Verifiziert mit Python 3.7.4)

## Bei Listenprozessen werden getbod-Prozesse in einer Textdatei gespeichert.

```python
"""
BP-Parameter für die Verbindung mit Blue Prism_USERNAME, BP_PASSWORD, BP_Legen Sie es in der Umgebungsvariablen DBCONNAME fest und führen Sie es aus.

BP_USERNAME :Nutzername
BP_PASSWORD :Passwort
BP_DBCONNAME :Verbindungsname
"""
import delegator
from pathlib import Path
import logging
import os

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

bp_username = os.environ["BP_USERNAME"]
bp_password = os.environ["BP_PASSWORD"]
bp_dbconname = os.environ["BP_DBCONNAME"]

LISTPROCESSES_CMD = '"C:\Program Files\Blue Prism Limited\Blue Prism Automate\AutomateC.exe" /user {bp_username} {bp_password} /dbconname {bp_dbconname} /listprocesses'
command = LISTPROCESSES_CMD.format(
    bp_username=bp_username, bp_password=bp_password, bp_dbconname=bp_dbconname
)
context = delegator.run(command)
object_list = context.out
object_names = object_list.splitlines()
logger.info(object_names)


GETBOD_CMD = '"C:\Program Files\Blue Prism Limited\Blue Prism Automate\AutomateC.exe" /user {bp_username} {bp_password} /dbconname {bp_dbconname} /getbod "{object_name}"'

for object_name in object_names:
    command = GETBOD_CMD.format(
        bp_username=bp_username,
        bp_password=bp_password,
        bp_dbconname=bp_dbconname,
        object_name=object_name,
    )
    context = delegator.run(command)
    description = context.out
    if (
        len(description.splitlines()) <= 1
    ):  #Prozess wird erklärt"Das Geschäftsobjekt XX wurde nicht gefunden"Es wird nur eine Zeile ausgegeben
        logger.info("{} is not a object".format(object_name))
        continue
    #Wenn der Dateiname einen Schrägstrich enthält, kann die Datei nicht erstellt werden. Ersetzen Sie sie daher.
    description_file_name = object_name.replace("/", "_") + ".txt"
    with open(Path("output_descriptions") / description_file_name, "w") as f:
        f.write(context.out)

Speichern Sie die getbod-Textdatei als Markdown

Bitte lassen Sie mich wissen, ob es eine Bibliothek gibt, die einfacher analysiert werden kann. .. ..

from typing import List, Optional
from dataclasses import dataclass, field
import re
import enum
import logging
from pathlib import Path

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG)


@dataclass
class VBOActionDescription:
    """
Eine Klasse, die Informationen zu jeder VBO-Aktion enthält
    """

    action_name: str
    description: str = ""
    pre_condition: str = ""
    post_condition: str = ""
    input_params: List[str] = field(default_factory=list)
    output_params: List[str] = field(default_factory=list)

    def as_markdown(self) -> str:
        """
Express im Markdown-Format
        """
        _md = (
            "###{action_name}\n"
            "{description}\n"
            "\n"
            "####Voraussetzungen\n"
            "{pre_condition}\n"
            "\n"
            "####Nachbedingungen\n"
            "{post_condition}\n"
            "\n"
            "####Eingabeparameter\n"
            "{input_params}\n"
            "\n"
            "####Ausgabeparameter\n"
            "{output_params}\n"
            "\n"
        )
        input_params_md = ("\n").join(
            ["* {}".format(input_param) for input_param in self.input_params]
        )
        output_params_md = ("\n").join(
            ["* {}".format(output_param) for output_param in self.output_params]
        )

        out = _md.format(
            action_name=self.action_name,
            description=self.description,
            pre_condition=self.pre_condition,
            post_condition=self.post_condition,
            input_params=input_params_md,
            output_params=output_params_md,
        )
        return out


class VBODescription:
    """
Eine Klasse, die VBO-Informationen enthält. Haben Sie eine kleine Liste von VBOActionDescription
    """

    def __init__(
        self,
        object_name: str,
        description: Optional[str] = "",
        mode: str = "",
        actions: Optional[List[VBOActionDescription]] = None,
    ):
        self.object_name = object_name
        self.description = description
        self.mode = mode
        self.actions = actions

    def as_markdown(self) -> str:
        """
Express im Markdown-Format
        """
        _md = (
            "#{object_name}\n"
            "{description}\n"
            "\n"
            "##Aktionsmodus\n"
            "{mode}\n"
            "\n"
            "##Aktion\n"
        )

        out = _md.format(
            object_name=self.object_name, description=self.description, mode=self.mode
        )
        if self.actions:
            out = out + ("\n").join([action.as_markdown() for action in self.actions])

        return out


class DescriptionOfWhat(enum.Enum):
    """
Enum wurde bereitgestellt, da beim Parsen der Beschreibung von VBO Informationen wie "Welchen Teil lesen Sie" benötigt wurden.
    """

    business_object = "Business Object"
    action = "Action"
    pre_condition = "Pre Conditiion"
    post_condition = "Post Conditiion"


def classify_line(line: str):
    """
Linien klassifizieren
    """
    line = line.strip()
    # =Geschäftsgegenstand- Utility - File Management=  <=Passen Sie die Linie wie links an
    match = re.search("^=(?P<content>[^=]*)=$", line)
    if match:
        return {"type": "object name", "content": match.groupdict()["content"]}
    #Der Ausführungsmodus dieses Geschäftsobjekts ist "Hintergrund".<=Passen Sie die Linie wie links an
    match = re.search("^Der Ausführungsmodus dieses Geschäftsobjekts ist "(?P<mode>[^」]+)"ist", line)
    if match:
        return {"type": "mode", "content": match.groupdict()["mode"]}
    # ==Append to Text File==  <=Passen Sie die Linie wie links an
    match = re.search("^==(?P<content>[^=]*)==$", line)
    if match:
        return {"type": "action name", "content": match.groupdict()["content"]}
    # ===Voraussetzungen===  <=Passen Sie die Linie wie links an
    match = re.search("^===(?P<content>[^=]*)===$", line)
    if match:
        content = match.groupdict()["content"]
        if content == "Voraussetzungen":  #Die Übersetzung auf der Seite des blauen Prismas ist seltsam. .. ..
            return {"type": "pre condition", "content": content}
        if content == "Endpunkt":  #Die Übersetzung auf der Seite des blauen Prismas ist seltsam. .. ..
            return {"type": "post condition", "content": content}
        #anders als das
        return {"type": "action attribute", "content": content}
    # *Eingang:File Path (Text) - Full path to the file to get the file size   <=Passen Sie die Linie wie links an
    match = re.search("^\*Eingang:(?P<content>.*)$", line)
    if match:
        return {"type": "input parameter", "content": match.groupdict()["content"]}
    # *Ausgabe:File Path (Text) - Full path to the file to get the file size  <=Passen Sie die Linie wie links an
    match = re.search("^\*Ausgabe:(?P<content>.*)$", line)
    if match:
        return {"type": "output parameter", "content": match.groupdict()["content"]}
    #Andere Zeilen
    return {"type": "article", "content": line}


def append_action_to_vbo_description(latest_action, vbo_description):
    actions = vbo_description.actions
    if actions:
        vbo_description.actions.append(latest_action)
    else:
        vbo_description.actions = [
            latest_action,
        ]
    return vbo_description


def convert_to_markdown(bod_description_filepath) -> str:
    """
Der Hauptteil des Prozesses, der in Markdown konvertiert werden soll
    """
    vbo_description = None
    with open(bod_description_filepath, "r", encoding="shift_jis", newline="\r\n") as f:
        previous_line_type: Optional[DescriptionOfWhat] = None  #Behalten Sie im Auge, was Sie lesen.
        latest_action = None

        for line in f:
            line_class = classify_line(line)
            if line_class["type"] == "object name":
                vbo_description = VBODescription(line_class["content"])
                previous_line_type = DescriptionOfWhat.business_object
                continue
            if line_class["type"] == "mode":
                assert vbo_description, "Der Ausführungsmodus wird nicht an der richtigen Position beschrieben"
                vbo_description.mode = line_class["content"]
                continue
            if line_class["type"] == "article":
                assert vbo_description, "Nicht im richtigen Format geschrieben"
                if previous_line_type == DescriptionOfWhat.business_object:
                    vbo_description.description += line_class["content"]
                    continue
                if previous_line_type == DescriptionOfWhat.action:
                    assert latest_action, "Nicht im richtigen Format geschrieben"
                    latest_action.description += line_class["content"]
                    continue
                if previous_line_type == DescriptionOfWhat.pre_condition:
                    assert latest_action, "Nicht im richtigen Format geschrieben"
                    latest_action.pre_condition += line_class["content"]
                    continue
                if previous_line_type == DescriptionOfWhat.post_condition:
                    assert latest_action, "Nicht im richtigen Format geschrieben"
                    latest_action.post_condition += line_class["content"]
                    continue
            if line_class["type"] == "action name":
                assert vbo_description, "Nicht im richtigen Format geschrieben"
                if latest_action:
                    vbo_description = append_action_to_vbo_description(
                        latest_action, vbo_description
                    )
                latest_action = VBOActionDescription(line_class["content"])
                previous_line_type = DescriptionOfWhat.action
                continue
            if line_class["type"] == "input parameter":
                assert vbo_description and latest_action, "Nicht im richtigen Format geschrieben"
                latest_action.input_params.append(line_class["content"])
                continue
            if line_class["type"] == "output parameter":
                assert vbo_description and latest_action, "Nicht im richtigen Format geschrieben"
                latest_action.output_params.append(line_class["content"])
                continue
            if line_class["type"] == "pre condition":
                assert vbo_description and latest_action, "Nicht im richtigen Format geschrieben"
                previous_line_type = DescriptionOfWhat.pre_condition
                continue
            if line_class["type"] == "post condition":
                assert vbo_description and latest_action, "Nicht im richtigen Format geschrieben"
                previous_line_type = DescriptionOfWhat.post_condition
                continue
            # debug
            logger.debug("line: {}".format(line.strip()))
            if latest_action:
                logger.debug("latest_action: {}".format(latest_action.as_markdown()))
        else:
            #Letzte verbleibende letzte_Aktion sammeln
            if latest_action:
                vbo_description = append_action_to_vbo_description(
                    latest_action, vbo_description
                )

    assert vbo_description, "Nicht im richtigen Format geschrieben"
    return vbo_description.as_markdown()


if __name__ == "__main__":
    descriptions_folder = Path("output_descriptions")
    for description_file in descriptions_folder.glob("*.txt"):
        with open(descriptions_folder / (description_file.stem + ".md"), "w") as md_f:
            md_f.write(convert_to_markdown(description_file))

Referenz-URL

Recommended Posts

Generieren Sie automatisch Objektspezifikationen mit Blue Prism
Generieren Sie automatisch ein Modellbeziehungsdiagramm mit Django
Anfänger generieren automatisch Dokumente mit Pytorchs LSTM
Versuchen Sie, Python-Dokumente automatisch mit Sphinx zu generieren
[Evangelion] Versuchen Sie, mit Deep Learning automatisch Asuka-ähnliche Linien zu erzeugen
Generieren Sie mit Python automatisch eine Häufigkeitsverteilungstabelle auf einmal
Messen und vergleichen Sie Temperaturen mit Raspberry Pi und generieren Sie automatisch Diagramme