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).
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)
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))
Recommended Posts