Aiviro Modules

Email

Note

It’s required to install email from Optional dependencies section.

Note

In case you’ll be using Outlook OAuth2.0 authorization, you need to create & configure new application with the Microsoft identity platform. By the following steps:
2. (Optional) In case of using Public(Delegated) Authorization option, you have to enable Allow public client flows in Authentication section
3. Add credentials, we currently support only Client’s Secret
4. Add corresponding permissions for Mail, in section API Permissions.

We require Mail.ReadWrite and Mail.Send permissions for both Authorization options (Delegated and Application). In case of using shared mailbox (only for Delegated option), also Mail.ReadWrite.Shared and Mail.Send.Shared is required.

Important, as Application permissions allow a user to access any mailbox, Administrators can configure application access policy to limit app access to specific mailboxes and not to all the mailboxes in the organization.

class aiviro.modules.email.EmailClient(username: str = '', password: str = '')

Email client which uses IMAP and SMTP protocols to communicate with server.

Parameters
  • username – Username for both services

  • password – Password for both services

Example

>>> from aiviro.modules.email import EmailClient
>>> from datetime import datetime
>>> client = EmailClient("<EMAIL_ADDRESS>", "<EMAIL_PASSWORD>")
>>> # To receive emails you need to add imap server.
>>> client.setup_imap_basic_auth("<IMAP_SERVER>")
>>> # Go through all messages
>>> for email in client.inbox.all():
...     print(email.sender.full, email.subject, email.datetime)
...     email.set_seen(True)
>>> # Go through unseen messages
>>> for email in client.inbox.query(seen=False):
...     print(email.sender.full, email.subject, email.datetime)
...     print("Has attachments:", len(email.file_attachments) != 0)
...
...     # Download all attachments to this mail
...     for attachment in email.file_attachments:
...         with open(attachment.filename, "wb") as f:
...             f.write(attachment.content)
>>> # To send messages you need to connect to SMTP.
>>> client.setup_smtp_basic_auth("<SMTP_SERVER>")
>>> # Basic sending of message
>>> client.send_mail(
...     "recipient@foo.bar",
...     "Hello from Python",
...     "This message was sent by Aiviro",
... )
setup_imap_basic_auth(server: str, username: str, password: str, port: int = 993, starttls: bool = False) aiviro.modules.email.client.email.EmailClient

Setups the IMAP connection with a basic username-password authorization for future use.

Parameters
  • server – server IP or hostname

  • port – port on which the IMAP service runs

  • username – username to this server

  • password – password to this server

  • starttls – set True if connection should be use starttls

setup_smtp_basic_auth(server: str, username: str, password: str, port: Optional[int] = None, starttls: bool = True, sender_name: Optional[str] = None, email_address: Optional[str] = None) aiviro.modules.email.client.email.EmailClient

Setups the SMTP connection with a basic username-password authorization for future use.

Parameters
  • server – server IP or hostname

  • username – username to this server

  • password – password to this server

  • port – port on which the SMTP service runs

  • starttls – set True if connection should be use starttls

  • sender_name – set name of the sender. Is shown on sent emails

  • email_address – Send emails as this email address. Set this if you need to send emails from a shared or alias email address you have access to via username.

setup_imap_outlook_oauth2_public(username: str, client_id: str, authority_url: str, shared_username: Optional[str] = None) aiviro.modules.email.client.email.EmailClient

Setups the Graph-API connection (functionality as IMAP protocol) with an OAuth2.0 authorization.

Note

This authorization type requires manual action, during the set-up process, to allow the app to access user’s data. By default, Mail.ReadWrite scope/permission is necessary.

Parameters
  • username – Username to outlook server

  • client_id – Application (client) id of the registered App in Azure Portal

  • authority_url – OAuth 2.0 authorization endpoint, it contains Directory (tenant) ID

  • shared_username – Specify this argument if you want to access a shared mailbox of different user

setup_imap_outlook_oauth2_confidential(username: str, client_id: str, authority_url: str, secret: str) aiviro.modules.email.client.email.EmailClient

Setups the Graph-API connection (functionality as IMAP protocol) with an OAuth2.0 authorization.

Note

This authorization type doesn’t require manual action, during the set-up process, but the permissions require an Admin consent in Azure Portal. By default, Mail.ReadWrite scope/permission is necessary.

Parameters
  • username – Username to outlook server

  • client_id – Application (client) id of the registered App in Azure Portal

  • authority_url – OAuth 2.0 authorization endpoint, it contains Directory (tenant) ID

  • secret – A secret string that the application uses to prove its identity when requesting a token. Also, can be referred to as application password

setup_smtp_outlook_oauth2_public(username: str, client_id: str, authority_url: str, sender_name: Optional[str] = None, email_address: Optional[str] = None)

Setups the Graph-API connection (functionality as SMTP protocol) with an OAuth2.0 authorization.

Note

This authorization type requires manual action, during the set-up process, to allow the app to access user’s data. By default, Mail.Send scope/permission is necessary.

Parameters
  • username – Username to outlook server

  • client_id – Application (client) id of the registered App in Azure Portal

  • authority_url – OAuth 2.0 authorization endpoint, it contains Directory (tenant) ID

  • sender_name – set name of the sender. Is shown on sent emails

  • email_address – Send emails as this email address. Set this if you need to send emails from a shared or alias email address you have access to via username.

setup_smtp_outlook_oauth2_confidential(username: str, client_id: str, authority_url: str, secret: str, sender_name: Optional[str] = None, email_address: Optional[str] = None)

Setups the Graph-API connection (functionality as SMTP protocol) with an OAuth2.0 authorization.

Note

This authorization type doesn’t require manual action, during the set-up process, but the permissions require an Admin consent in Azure Portal. By default, Mail.Send scope/permission is necessary.

Parameters
  • username – Username to outlook server

  • client_id – Application (client) id of the registered App in Azure Portal

  • authority_url – OAuth 2.0 authorization endpoint, it contains Directory (tenant) ID

  • secret – A secret string that the application uses to prove its identity when requesting a token. Also, can be referred to as application password

  • sender_name – set name of the sender. Is shown on sent emails

  • email_address – Send emails as this email address. Set this if you need to send emails from a shared or alias email address you have access to via username.

property root: aiviro.modules.email.client.imap.IMAPPath

Root folder on server

property inbox: aiviro.modules.email.client.imap.IMAPPath

Inbox folder on server

list_folders_raw() List[IMAPFolder]

Lists folders on the IMAP mailbox

Returns

List of folders and paths

get_current_folder() str

Get current folder

Returns

Current folder path

set_current_folder(path: EMAIL_PATH_TYPE)

Sets current folder

Parameters

path – Sets this path as current folder path

folder_exists(path: EMAIL_PATH_TYPE) bool

Checks if this folder exists on server

Parameters

path – Folder path to check

Returns

True if folder exists, False otherwise.

create_folder(path: EMAIL_PATH_TYPE)

Create folder on server

Parameters

path – Folder path to create

all(folder: EMAIL_PATH_TYPE = None, limit: int = None) Iterator[IMAPMessage]

Returns all emails

Parameters
  • folder – Folder from which to extract message. If not set, currently set folder is used

  • limit – Limits the number of emails which to get. Default None = No Limit

Returns

Emails in supplied folder

Example

>>> from aiviro.modules.email import EmailClient
>>> from datetime import datetime
>>> client = EmailClient("<EMAIL_ADDRESS>", "<EMAIL_PASSWORD>")
>>> # To receive emails you need to add imap server.
>>> client.setup_imap_basic_auth("<IMAP_SERVER>")
>>> # Go through all messages
>>> for email in client.all():
...     print(email.sender.full, email.subject, email.datetime)
...     email.set_seen(True)
query(seen: bool = None, subject: str = None, sender: str = None, recipient: str = None, text: str = None, cc: str = None, bcc: str = None, date: datetime.date = None, date_from: datetime.date = None, date_to: datetime.date = None, folder: EMAIL_PATH_TYPE = None, limit: int = None) IMAPQuery

Returns all emails following set constraints

Parameters
  • seen – True = seen emails, False = unseen emails, None = all emails. Default None

  • subject – Emails containing this subject. Default None

  • sender – Emails from this sender. Default None

  • recipient – Emails to this recipient. Default None

  • text – Emails containing this text. Default None

  • cc – CC field containing this recipient. Default None

  • bcc – BCC field containing this recipient. Default None

  • date – Email received on this date. Default None

  • date_from – Emails received after this date. Default None

  • date_to – Emails received before this date. Default None

  • folder – Folder which to search. Default is Inbox

  • limit – Limits the number of emails which to get. Default None = No Limit

Returns

Emails in supplied folder

Example

>>> from aiviro.modules.email import EmailClient
>>> from datetime import datetime
>>> client = EmailClient("<EMAIL_ADDRESS>", "<EMAIL_PASSWORD>")
>>> # To receive emails you need to add imap server.
>>> client.setup_imap_basic_auth("<IMAP_SERVER>")
>>> # Go through all unseen messages
>>> for email in client.query(seen=False):
...     print(email.sender.full, email.subject, email.datetime)
...     email.set_seen(True)
execute_query(query: IMAPQuery) Iterator[IMAPMessage]

Executes the query

Parameters

query – Query to execute

copy_mail(ref: EMAIL_ID_TYPE, path: EMAIL_PATH_TYPE, working_folder: Optional[EMAIL_PATH_TYPE] = None)

Copies email to a new folder

Parameters
  • ref – UUID of the email.

  • path – Path to new location of the email.

  • working_folder – Folder which contains email with specified UUID

move_mail(ref: EMAIL_ID_TYPE, path: EMAIL_PATH_TYPE, working_folder: Optional[EMAIL_PATH_TYPE] = None)

Moves email to a new folder

Parameters
  • ref – UUID of the email.

  • path – Path to new location of the email.

  • working_folder – Folder which contains email with specified UUID

mail_set_seen(ref: EMAIL_ID_TYPE, seen: bool, working_folder: Optional[EMAIL_PATH_TYPE] = None)

Sets the email as seen or unseen

Parameters
  • ref – UUID of the email.

  • seen – Set seen flag to either True or False

  • working_folder – Folder which contains email with specified UUID

mail_delete(ref: EMAIL_ID_TYPE, working_folder: Optional[EMAIL_PATH_TYPE] = None)

Delete the mail from server

Parameters
  • ref – UUID of the email.

  • working_folder – Folder which contains email with specified UUID

send_mail(recipients: ADDR_TYPE, subject: str, message: str, attachments: Sequence[Union[str, pathlib.Path]] = None, cc: ADDR_TYPE = None, bcc: ADDR_TYPE = None, reply_msg: IMAPMessage = None, sender_email: str = None, message_as_html: bool = False)

Sends email via SMTP server

Parameters
  • recipients – One or more recipients in format email or (fullname, email)

  • subject – Subject of the message

  • message – Contents of the message

  • attachments – List of paths to attach to the email.

  • cc – Carbon copy recipients, same format as recipients.

  • bcc – Blind carbon copy recipients, same format as recipients.

  • reply_msg – If this message is a reply to email use this attribute to include the reference.

  • sender_email – Send emails as this email address. Set this if you need to send emails from a shared or alias email address.

  • message_as_html – If True, content of the ‘messsage’ argument is sent as html

Example

>>> from aiviro.modules.email import EmailClient
>>> from datetime import datetime
>>> client = EmailClient("<EMAIL_ADDRESS>", "<EMAIL_PASSWORD>")
>>> # To send messages you need to connect to SMTP.
>>> client.setup_smtp_basic_auth("<SMTP_SERVER>")
>>> # Basic sending of message
>>> client.send_mail(
...     "recipient@foo.bar",
...     "Hello from Python",
...     "This message was sent by Aiviro",
... )

Email Notifier

class aiviro.modules.email.notifier.EmailNotifier(client: EmailClient, report_title: str)

Email notifier which provides an interface to create standardized reports for Aiviro scripts. It creates report in html, markdown and plain-text format.

Parameters
  • clientEmailClient object with configured SMTP server credentials

  • report_title – Title of the report

Example

>>> from aiviro.modules.email import EmailClient
>>> from aiviro.modules.email.notifier import EmailNotifier, Msg, Item, Style
>>>
>>> client = EmailClient("<EMAIL_ADDRESS>", "<EMAIL_PASSWORD>")
>>> client.setup_smtp_basic_auth("<SMTP_SERVER>")
...
>>> en = EmailNotifier(client, "Spracovaní Faktúr")
>>> en.default_block.item_style = Style(bold=True)
>>> en.successful(Item("Faktura", "Milburg 21893918.pdf"))
>>> en.successful(Item("Objednavka", "300220178"))
>>> en.unable_to_process(
...     Item("e-mail", "SecureNetwork.cz: Potvrzení o přijetí platby")
... ).add_sub_msg("Neobsahuje přilohu")
>>> en.unable_to_process(
...     Item("e-mail", "faktura FV-11/2022")
... ).add_sub_msg("Obsahuje neznámu přílohu")
>>> en.warning(
...     Item("položka", "107236").item("Faktura", "R22E09315").item("Objednávka", "301210221")
... ).add_sub_msg(Msg("nebyla nalezena v 'Převod s výběrem a potvrdzením'"))
>>> en.error("Extrakce emailu")
>>> en.error(Item("faktura", "Emmen 503031100.PDF").item("parser", "EmmennParser"))
...
>>> blk = en.create_block("Druhy Blok")
>>> blk.item_style = Style(italic=True)
>>> blk.unable_to_process(
...     Item("E-mail", 'Melder Electronics, a.s.')
... ).add_sub_msg("Neobsahuje přílohu s PDF")
>>> blk.unable_to_process(
...     Item("Objednavka", "123-30XDSF03").text("jiz existuje ve 'Expedicni prikazy'")
... )
>>> blk.warning(Msg("Výber maximálního-menšího množství (20)").item("polozka", "7811248"))
>>> blk.error(
...     Item("Faktura", '123-3498129').text("nelze spracovat")
... ).add_sub_msg(Item("Firma", "Sewer s.r.o.").text("nebyla nalezena v konfiguračním souboru"))
>>> en.send_report(["email@domain.com", "email2@domain.com"])
_images/email-report.png

Example of e-mail report.

report_plain_text() str

Returns plain-text report

report_markdown() str

Returns markdown report

report_html() str

Returns html report

send_report(recipients: Optional[ADDR_TYPE], logging_info: bool = True, prefect_artifact: bool = True, email_subject: str = None, email_attachments: List[str] = None)

Method generates and sends the report.

Parameters
  • recipients – E-mail recipients of the html report

  • logging_info – If True, plain-text report is logged in INFO level

  • prefect_artifact – If True, Prefect artifact with markdown report is created

  • email_subject – Subject of them e-mail, if None report_title is used as subject

  • email_attachments – List of paths to attach to the email

property blocks: List[aiviro.modules.email.notifier.common.NotificationBlock]

Returns list of non-empty blocks. It can be used to see if report containes any messages.

Example

>>> en = EmailNotifier("<client>", "Invoice Processing")
>>> if en.blocks:
>>>     en.send_report("robot.aiviro@aiviro.com", email_subject="Robot Report")
property default_block: aiviro.modules.email.notifier.common.NotificationBlock

Returns default NotificationBlock

Example

>>> # set default item_style for the block
>>> from aiviro.modules.email.notifier import EmailNotifier, Style
>>> en = EmailNotifier("<client>", "Title")
>>> en.default_block.item_style = Style(bold=True)
property last_block: aiviro.modules.email.notifier.common.NotificationBlock

Returns last created NotificationBlock

get_block(block_id: str) aiviro.modules.email.notifier.common.NotificationBlock

Method to get NotificationBlock

Parameters

block_id – Identification of the notification block

create_block(title: str, block_id: Optional[str] = None, sort_notifications: bool = False, style: Style = None) aiviro.modules.email.notifier.common.NotificationBlock

Creates new block/section in the report.

Parameters
  • title – Title of the block

  • block_id – Identifier of the block, if not set ‘title’ is used as identifier

  • sort_notifications – If True notification messages will be sorted in the block

  • style – Style to automatically format Item messages.

custom(title: str, text: MSG_TYPE, m_type: aiviro.modules.email.notifier.common.NotificationType = NotificationType.INFO) Notification

Method creates custom notification message in default block.

Parameters
  • title – Title of the message

  • text – Additional text of the message

  • m_type – Type of the notification, see NotificationType for options

Returns

Notification object, to add additional messages

Example

>>> from aiviro.modules.email.notifier import EmailNotifier, NotificationType
>>> en = EmailNotifier("<client>", "title")
>>> en.custom("Custom", "message text", NotificationType.INFO).add_sub_msg("Sub message")
"Custom - message text
    - Sub message"
successful(msg: MSG_TYPE) Notification

Method creates ‘successful’ (green) notification message in default block.

Parameters

msg – Standardized message object

Returns

Notification object, to add additional messages

Example

>>> from aiviro.modules.email.notifier import EmailNotifier, Item
>>> en = EmailNotifier("<client>", "title")
>>> en.successful(Item("faktúra", "310-231234"))
"Úspěšně zpracováno - Faktúra '310-231234'"
unable_to_process(msg: MSG_TYPE) Notification

Method creates ‘unable to process’ (blue) notification message in default block.

Parameters

msg – Standardized message object

Returns

Notification object, to add additional messages

Example

>>> from aiviro.modules.email.notifier import EmailNotifier, Item
>>> en = EmailNotifier("<client>", "title")
>>> en.unable_to_process(
...     Item("e-mail", "Invoice no.331343")
... ).add_sub_msg("Neznámi formát e-mailu")
"Nelze zpracovat - E-mail 'Invoice no.331343'
    - Neznámi formát e-mailu"
warning(msg: MSG_TYPE) Notification

Method creates ‘warning’ (yellow) notification message in default block.

Parameters

msg – Standardized message object

Returns

Notification object, to add additional messages

Example

>>> from aiviro.modules.email.notifier import EmailNotifier, Msg
>>> en = EmailNotifier("<client>", "title")
>>> en.warning(
...     Msg("Byl spracovany maximálni počet položek")
... ).add_sub_msg("spracovano 20/20")
"Upozornení - Byl spracovany maximálni počet položek
    - spracovano 20/20"
error(msg: MSG_TYPE) Notification

Method creates ‘error’ (red) notification message in default block.

Parameters

msg – Standardized message object

Returns

Notification object, to add additional messages

Example

>>> from aiviro.modules.email.notifier import EmailNotifier, Item
>>> en = EmailNotifier("<client>", "title")
>>> en.error(
...     Item("Objednávka", "RE-102-3539").text("neobsahuje požadované položky")
... ).add_sub_msg("položka DP-34101")
"Chyba - Objednávka 'RE-102-3539' neobsahuje požadované položky
    - položka DP-34101"
class aiviro.modules.email.notifier.Notification(title: str, message: aiviro.modules.email.notifier.message.Msg, m_type: aiviro.modules.email.notifier.common.NotificationType, item_style: Optional[aiviro.modules.email.notifier.message.Style] = None)

Notification object representing one message (possibly with sub messages) for NotificationBlock.

add_sub_msg(text: MSG_TYPE) Notification

Adds sub message into the notification

property notification_type: aiviro.modules.email.notifier.common.NotificationType

Type of the notification, one of NotificationType options.

Getter

Returns notification type

Setter

Sets type of the notification

Example

>>> from aiviro.modules.email.notifier import EmailNotifier, NotificationType, Item
>>> en = EmailNotifier("<client>", "title")
>>> msg = en.successful(Item("invoice", "600-123456"))
>>> # some code
>>> # change the successful message into error
>>> msg.notification_type = NotificationType.ERROR
class aiviro.modules.email.notifier.NotificationBlock(title: str, sort_notifications: bool = False)

Block/section of the section, containing corresponding notifications.

Parameters
  • title – Title of the section

  • sort_notifications – If True notification messages will be sorted

property item_style: Optional[aiviro.modules.email.notifier.message.Style]

Default style setting using which Item text is automatically formated.

Getter

Returns style object

Setter

Sets style for item texts

Example

>>> from aiviro.modules.email.notifier import EmailNotifier, NotificationType, Item, Style
>>> en = EmailNotifier("<client>", "title")
>>> blk = en.create_block("New Block", "nb")
>>> blk.item_style = Style(bold=True)
>>> blk.successful(Item("invoice", "600-123456").item("email", "title of email"))
"Úspěšně zpracováno - **Invoice** '600-123456', **Email** 'title of email'"
custom(title: str, text: MSG_TYPE, m_type: aiviro.modules.email.notifier.common.NotificationType = NotificationType.INFO) aiviro.modules.email.notifier.common.Notification

Method creates custom notification message.

Parameters
  • title – Title of the message

  • text – Additional text of the message

  • m_type – Type of the notification, see NotificationType for options

Returns

Notification object, to add additional messages

Example

>>> from aiviro.modules.email.notifier import EmailNotifier, NotificationType
>>> en = EmailNotifier("<client>", "title")
>>> blk = en.create_block("supplier-1", "s1")
>>> blk.custom("Custom", "message text", NotificationType.INFO).add_sub_msg("Sub message")
"Custom - message text
    - Sub message"
successful(msg: MSG_TYPE) aiviro.modules.email.notifier.common.Notification

Method creates ‘successful’ (green) notification message.

Parameters

msg – Standardized message object

Returns

Notification object, to add additional messages

Example

>>> from aiviro.modules.email.notifier import EmailNotifier, Item
>>> en = EmailNotifier("<client>", "title")
>>> blk = en.create_block("supplier-1", "s1")
>>> blk.successful(Item("faktúra", "310-231234"))
"Úspěšně zpracováno - Faktúra '310-231234'"
unable_to_process(msg: MSG_TYPE) aiviro.modules.email.notifier.common.Notification

Method creates ‘unable to process’ (blue) notification message.

Parameters

msg – Standardized message object

Returns

Notification object, to add additional messages

Example

>>> from aiviro.modules.email.notifier import EmailNotifier, Item
>>> en = EmailNotifier("<client>", "title")
>>> blk = en.create_block("supplier-1", "s1")
>>> blk.unable_to_process(
...     Item("e-mail", "Invoice no.331343")
... ).add_sub_msg("Neznámi formát e-mailu")
"Nelze zpracovat - E-mail 'Invoice no.331343'
    - Neznámi formát e-mailu"
warning(msg: MSG_TYPE) aiviro.modules.email.notifier.common.Notification

Method creates ‘warning’ (yellow) notification message.

Parameters

msg – Standardized message object

Returns

Notification object, to add additional messages

Example

>>> from aiviro.modules.email.notifier import EmailNotifier, Msg
>>> en = EmailNotifier("<client>", "title")
>>> blk = en.create_block("supplier-1", "s1")
>>> blk.warning(
...     Msg("Byl spracovany maximálni počet položek")
... ).add_sub_msg("spracovano 20/20")
"Upozornení - Byl spracovany maximálni počet položek
    - spracovano 20/20"
error(msg: MSG_TYPE) aiviro.modules.email.notifier.common.Notification

Method creates ‘error’ (red) notification message.

Parameters

msg – Standardized message object

Returns

Notification object, to add additional messages

Example

>>> from aiviro.modules.email.notifier import EmailNotifier, Item
>>> en = EmailNotifier("<client>", "title")
>>> blk = en.create_block("supplier-1", "s1")
>>> blk.error(
...     Item("Objednávka", "RE-102-3539").text("neobsahuje požadované položky")
... ).add_sub_msg("položka DP-34101")
"Chyba - Objednávka 'RE-102-3539' neobsahuje požadované položky
    - položka DP-34101"
class aiviro.modules.email.notifier.NotificationType(value)

Default types for notification messages.

SUCCESS = 10

Green colored message

INFO = 20

Blue colored message

WARNING = 30

Yellow colored message

ERROR = 40

Red colored message

class aiviro.modules.email.notifier.Msg(text: str = '', style: Optional[aiviro.modules.email.notifier.message.Style] = None)

Main object to create a standardized message for e-mail notifications, see EmailNotifier.

Parameters
  • text – Initial text of the message

  • style – Style to format text

Example

>>> from aiviro.modules.email.notifier import Msg
>>> m = Msg("Text at the beginning")
>>> m.message
"Text at the beginning"
>>> m = Msg("")
...     .item("Item", 'DP123-1').text("unable to process")
...     .item("Invoice", "300220178").text("has invalid format")
>>> m.message
"Item 'DP123-1' unable to process, Invoice '300220178' has invalid format"
item(name: str, value: str, style: Optional[aiviro.modules.email.notifier.message.Style] = None) aiviro.modules.email.notifier.message.Msg

Method to add custom item with its value.

Parameters
  • name – Name of the item, text is capitalized

  • value – String value of the item, text is formatted between two ‘

  • style – Style to format ‘name’ text, ‘value’ is not formatted

Example

>>> m = Msg("Some text").item('invoice', '310-12345').item('file', 'R234_12345.pdf')
>>> m.message
"Some text, Invoice '310-12345', File 'R234_12345.pdf'"
>>> m = Msg("Some text").item("Item", 'DP123-1', Style(bold=True))
>>> m.message
"Some text, **Item** 'DP123-1'"
text(text: str, style: Optional[aiviro.modules.email.notifier.message.Style] = None) aiviro.modules.email.notifier.message.Msg

Method to add additional text to the message.

Parameters
  • text – Text added to the final message, “space” is added in front of it

  • style – Style to format text

Example

>>> m = Msg("Some text").text("additional text")
>>> m.message
"Some text addtitional text"
>>> m = Msg("Bold text", Style(bold=True))
>>> m.message
"**Bold text**"
class aiviro.modules.email.notifier.Item(name: str, value: str, style: Optional[aiviro.modules.email.notifier.message.Style] = None)

Object to create a standardized message for e-mail notifications, see EmailNotifier. Can be used instead of Msg, when initial text is not required.

Parameters
  • name – Name of the item, text is capitalized

  • value – String value of the item, text is formatted between two ‘

Example

>>> from aiviro.modules.email.notifier import Item
>>> m = Item("Item", "DP123-1")
>>> m.message
"Item 'DP123-1'"
>>> m = Item("Item", 'DP123-1').text("unable to process")
...     .item("Invoice", "300220178").text("has invalid format")
>>> m.message
"Item 'DP123-1' unable to process, Invoice '300220178' has invalid format"
>>> m = Item("Item", 'DP123-1', Style(bold=True)).text("unable to process")
>>> m.message
"**Item** 'DP123-1' unable to process"

Email Extractor

class aiviro.modules.email.extractor.EmailExtractor(client: EmailClient, source_dir: EMAIL_DIR_TYPE, processed_dir: EMAIL_DIR_TYPE, unprocessed_dir: EMAIL_DIR_TYPE = None, attachment_conditions: List[aiviro.modules.email.extractor.conditions.BaseCondition] = None, max_valid_emails: int = 0)

Email extractor provides a standardized way to extract emails and their attachments, based on the provided configuration.

Parameters
  • clientEmailClient object with configured IMAP server credentials

  • source_dir – Email directory from which emails are extracted

  • processed_dir – Email directory into which valid or processed emails can be moved, see EmailExtractor.move_to_processed()

  • unprocessed_dir – Email directory into which invalid emails are automatically moved, if set to None, emails are not automatically moved, see EmailExtractor.move_to_unprocessed()

  • attachment_conditions – Conditions for separating valid/invalid emails, based on their attachments

  • max_valid_emails – Maximum number of valid emails to extract, if set to 0, all valid emails are extracted

Example

>>> from aiviro.modules.email import EmailClient
>>> from aiviro.modules.email.extractor import (
...     EmailExtractor,
...     HasAttachmentsCondition,
...     FileExtensionCondition
... )
>>> client = EmailClient("<EMAIL_ADDRESS>", "<EMAIL_PASSWORD>")
>>> client.setup_imap_basic_auth("<SMTP_SERVER>")
>>> e_extractor = EmailExtractor(
...     client,
...     "INBOX",
...     "INBOX/Processed",
...     "INBOX/Manual",
...     [HasAttachmentsCondition(), FileExtensionCondition("pdf")],
...     15
... )
>>> for email, attachments in e_extractor.extract_all():
...     # process email & attachments
>>> # extract exactly one valid email
>>> email, attachments = e_extractor.extract_one()
move_to_processed(email: IMAPMessage)

Moves email into processed email directory, see processed_dir argument in EmailExtractor.

Parameters

email – Email to move

move_to_unprocessed(email: IMAPMessage)

Moves email into unprocessed email directory, see unprocessed_dir argument in EmailExtractor.

Parameters

email – Email to move

property email_query: Optional[IMAPQuery]

The custom query for extracting emails, set it if you want emails from a specific recipient, with certain subjects, or others. See query() for possible options.

Warning

By setting this option, you override source_dir argument from EmailExtractor

Example

>>> from aiviro.modules.email import EmailClient
>>> from aiviro.modules.email.extractor import EmailExtractor
>>> client = EmailClient("<EMAIL_ADDRESS>", "<EMAIL_PASSWORD>")
>>> client.setup_imap_basic_auth("<SMTP_SERVER>")
>>> e_extractor = EmailExtractor(
...     client,
...     "INBOX",
...     "INBOX/Processed",
...     "INBOX/Manual",
... )
>>> e_extractor.email_query = client.query(seen=False)
>>> for email, attachments in e_extractor.extract_all():
...     # process email & attachments
extract_all(auto_move: bool = True) Generator[EXTRACT_TYPE, None, None]

Extracts all valid emails, based on provided configuration.

Parameters

auto_move – if True, it automatically moves invalid emails into unprocessed folder

extract_one(auto_move: bool = True) EXTRACT_TYPE

Extracts one valid email, based on provided configuration.

Parameters

auto_move – if True, it automatically moves invalid emails into unprocessed folder

Raises

NoEmailToExtract – If no valid email can be extracted

class aiviro.modules.email.extractor.BaseCallbackStrategy

Base class to inherit from for creating custom callback-strategy. Callback strategies can be added to attachment-conditions, they are called in case the condition is not satisfied. The callback logic is implemented in the __call__ method.

Example

>>> from aiviro.modules.email.extractor import (
...     EmailExtractor,
...     HasAttachmentsCondition,
...     InvalidEmailNotificationCallback
... )
>>> e_extractor = EmailExtractor(
...     "<client-object>",
...     "INBOX",
...     "INBOX/Processed",
...     "INBOX/Manual",
...     [
...         FileExtensionCondition(
...             "pdf",
...             InvalidEmailNotificationCallback("<email-notifier>", "do not contain PDF attachment")
...         )
...     ],
... )
class aiviro.modules.email.extractor.InvalidEmailNotificationCallback(email_notifier: EmailNotifier, message: str)

Strategy creates unable_to_process() report-message, containing information about invalid email and custom message.

Parameters
  • email_notifier – Standardized email-notifier, see EmailNotifier

  • message – Custom text added at the end of the report-message

class aiviro.modules.email.extractor.BaseCondition(callback: Optional[aiviro.modules.email.extractor.conditions.BaseCallbackStrategy])

Base class provides an interface to create a custom attachment validator. The validation logic must be implemented in the __call__ method.

Parameters

callback – Callback that is called, in case the attachments are not valid, see BaseCallbackStrategy, InvalidEmailNotificationCallback

class aiviro.modules.email.extractor.OrCondition(*conditions: aiviro.modules.email.extractor.conditions.BaseCondition, callback: Optional[aiviro.modules.email.extractor.conditions.BaseCallbackStrategy] = None)

Validates if at least one input condition is satisfied.

Parameters

conditions – Conditions to check

class aiviro.modules.email.extractor.HasAttachmentsCondition(do_not_contain: bool = False, callback: Optional[aiviro.modules.email.extractor.conditions.BaseCallbackStrategy] = None)

Validates if there’s at least one attachment, or none, based on the do_not_contain argument.

Parameters

do_not_contain – Reverse the logic of the condition

class aiviro.modules.email.extractor.FileExtensionCondition(file_extension: str, callback: Optional[aiviro.modules.email.extractor.conditions.BaseCallbackStrategy] = None)

Validates if at least one attachment has specified file-extension.

Parameters

file_extension – Extension to check

class aiviro.modules.email.extractor.FilenameCondition(regex: str, callback: Optional[aiviro.modules.email.extractor.conditions.BaseCallbackStrategy] = None)

Validates if at least one attachment’s filename satisfies provided regex.

Parameters

regex – Regex used for filename validation

class aiviro.modules.email.extractor.ReplaceFilenameCondition(from_char: List[str], to_char: List[str])

Renames attachments filename.

Parameters
  • from_char – List of characters to replace

  • to_char – List of characters to use for the replacement

class aiviro.modules.email.extractor.EmailSubjectCondition(regex: str, callback: Optional[aiviro.modules.email.extractor.conditions.BaseCallbackStrategy] = None)

Validates if email’s subject satisfies provided regex.

Parameters

regex – Regex used for validation

class aiviro.modules.email.extractor.EmailDatetimeCondition(delta_time: datetime.timedelta, timezone: Optional[str] = None, callback: Optional[aiviro.modules.email.extractor.conditions.BaseCallbackStrategy] = None)

Validates if email is younger than specified datetime.

Parameters
  • delta_time – The amount of time for which email is still valid

  • timezone – Pytz timezone for calculating current time, if not set timezone from aiviro-configuration is used

exception aiviro.modules.email.extractor.NoEmailToExtract

Parsers

The first step of working with Parsers is to implement all the parsers you need based on one of three provided base classes: PDFBaseParser, EmailBaseParser and FileBaseParser.

The second step is to create an instance of ParserHandler, which automatically loads all the parsers based on provided input arguments.

And finally, to parse our input data, we can call parse() method, which will select the correct parser and parse the input data based on provided Parsing Strategy. See parameter parse_strategy in ParserHandler.

class aiviro.modules.parser.PDFBaseParser(supplier_name: Optional[str] = None)

Base class to inherit from for creating PDF Parser.

Example

>>> import aiviro
>>> from typing import Any
>>> from dataclasses import dataclass
>>> from aiviro.modules.pdf import PDFRobot
>>> from aiviro.modules.parser import PDFBaseParser, ParserInvalidCheck
>>>
>>> @dataclass
... class DataOut:
...     something: int
...
>>> class SupplierParser(PDFBaseParser[DataOut]):
...     def __init__(self):
...         super().__init__("supplier name")
...
...     def parse(self, r: PDFRobot) -> DataOut:
...         if not r.get(aiviro.And(
...             aiviro.Text("Invoice"),
...             aiviro.Text("Supplier Name")
...         )):
...             raise ParserInvalidCheck
...
...         # additional code
...         return DataOut(42)
class aiviro.modules.parser.EmailBaseParser(supplier_name: Optional[str] = None)

Base class to inherit from for creating Email Parser.

Example

>>> import aiviro
>>> from typing import Any
>>> from aiviro.modules.email import IMAPMessage
>>> from aiviro.modules.parser import EmailBaseParser, ParserInvalidCheck
>>>
>>> class SupplierParser(EmailBaseParser[str]):
...     def __init__(self):
...         super().__init__("supplier name")
...
...     def parse(self, email: IMAPMessage) -> str:
...         if email.subject.find("Supplier name") == -1:
...             raise ParserInvalidCheck
...
...         # additional code
...         return email.subject
class aiviro.modules.parser.FileBaseParser(supplier_name: Optional[str] = None)

Base class to inherit from for creating File Parser.

Example

>>> import aiviro
>>> import pathlib
>>> from typing import Any
>>> from aiviro.modules.parser import FileBaseParser, ParserInvalidCheck
>>>
>>> class SupplierParser(EmailBaseParser[str]):
...     def __init__(self):
...         super().__init__("supplier name")
...
...     def parse(self, file_path: Union[str, pathlib.Path]) -> str:
...         lib_path = pathlib.Path(file_path)  # convert into Path object
...         if lib_path.stem.find("Supplier name") == -1:
...             raise ParserInvalidCheck
...
...         # additional code
...         return lib_path.name
class aiviro.modules.parser.ParserHandler(parser_module: typing.Optional[module], ignorable_python_files: typing.Optional[typing.List[str]] = None, ignorable_parser_objects: typing.Optional[typing.List[typing.Type[aiviro.modules.parser.base.BaseLoadable]]] = None, parse_strategy: typing.Optional[aiviro.modules.parser.strategy.BaseParsingStrategy] = None, loader: typing.Type[aiviro.modules.parser.base.BaseLoader] = <class 'aiviro.modules.parser.loader.DefaultLoader'>)

Parser handler which loads and instantiate Parsers from provided directory. It provides interface to select correct parser for processing the input data.

Parameters
  • parser_module – Python module with parsers to load

  • ignorable_python_files – Python source files excluded from module loading

  • ignorable_parser_objects – Parser objects excluded from module loading

  • parse_strategy – Strategy based on which the correct parser is selected, if None, NaiveParsingStrategy is used

Example

>>> from aiviro.modules.parser import ParserHandler
>>> from aiviro.modules.pdf import create_pdf_robot
>>> import src.parsers.pdf
>>> handler = ParserHandler(
...     src.parsers.pdf
... )
>>> r = create_pdf_robot("path/to/file.pdf")
>>> r.set_as_stream_source()
>>> result, parser = handler.parse(r)
>>> parser.supplier_name
"supplier name"
>>> from aiviro.modules.email import EmailClient
>>> from src.common import CustomBasePDFParser
>>> import src.parsers.email
>>> handler = ParserHandler(
...     src.parsers.email,
...     ["ignore-file.py"],
...     [CustomBasePDFParser]
... )
>>> client = EmailClient("<EMAIL_ADDRESS>", "<EMAIL_PASSWORD>")
>>> client.setup_imap_basic_auth("<IMAP_SERVER>")
>>> for email in client.inbox.all():
...     result, parser = handler.parse(email)
>>> import src.parsers.files
>>> handler = ParserHandler(
...     src.parsers.files,
...     ["common.py"]
... )
>>> result, parser = handler.parse("path/to/file")
add_module(parser_module: module, ignorable_python_files: Optional[List[str]] = None, ignorable_parser_objects: Optional[List[Type[aiviro.modules.parser.base.BaseLoadable]]] = None)

Loads parsers from python module.

Parameters
  • parser_module – Python module with parsers to load

  • ignorable_python_files – Python source files excluded from module loading

add_parser(parser: Union[aiviro.modules.parser.base.BaseLoadable, Type[aiviro.modules.parser.base.BaseLoadable]])

Add additional parser.

Parameters

parser – Instance of the parser or type of parser to instantiate

property parsers: List[aiviro.modules.parser.base.BaseParser[aiviro.modules.parser.handler.T]]

All parsers loaded by the handler.

Returns

List of parsers, sorted by their priority

parse(*args) Tuple[aiviro.modules.parser.handler.T, aiviro.modules.parser.base.BaseParser[aiviro.modules.parser.handler.T]]

Passes the input data into provided parsing-strategy.

Parameters

*args – Arguments passed to parsing-strategy object

Returns

Tuple of result-data obtained from parser and selected parser

class aiviro.modules.parser.BaseParsingStrategy
abstract parse(*args, parsers: List[aiviro.modules.parser.base.BaseParser]) Tuple[Any, aiviro.modules.parser.base.BaseParser]

Passes the input data through input list of Parsers and select the valid one.

Parameters
  • *args – Arguments passed to ‘parse’ method of loaded parsers

  • parsers – List of parsers used for parsing

Returns

Tuple of result-data obtained from parser and selected parser

class aiviro.modules.parser.NaiveParsingStrategy

Naive and default parsing strategy for ParserHandler. Strategy goes through all the parsers and select the first one which don’t raise ParserInvalidCheck exception.

parse(*args, parsers: List[aiviro.modules.parser.base.BaseParser]) Tuple[Any, aiviro.modules.parser.base.BaseParser]

Passes the input data through input list of Parsers and select the valid one.

Parameters
  • *args – Arguments passed to ‘parse’ method of loaded parsers

  • parsers – List of parsers used for parsing

Raises
Returns

Tuple of result-data obtained from parser and selected parser

class aiviro.modules.parser.AutoSelectParsingStrategy(strategy: Optional[aiviro.modules.parser.strategy.BaseParsingStrategy] = None)

Strategy selects automatically appropriate type of parses based on the type of input argument. It checks the type of the first argument args[0]:

The parsing logic is then handled by NaiveParsingStrategy.

Parameters

strategy – Parser that handles data-parsing logic, if None, NaiveParsingStrategy is used

parse(*args, parsers: List[aiviro.modules.parser.base.BaseParser]) Tuple[Any, aiviro.modules.parser.base.BaseParser]

Selects appropriate type of the parses based on the type of input argument. And then it passes into NaiveParsingStrategy.

Parameters
  • *args – Arguments used for selecting correct parsers

  • parsers – List of parsers to select from

Returns

Tuple of result-data obtained from parser and selected parser

exception aiviro.modules.parser.ParserInvalidCheck
exception aiviro.modules.parser.ParserNotFound
exception aiviro.modules.parser.ParserProcessingError(*args, parser: Optional[BaseParser] = None, parsing_data: Any = None)

Powershell

Note

It’s required to install rdp from Optional dependencies section.

class aiviro.modules.powershell.ShellCommands(rdp_robot: RDPRobot, timeout: int = None, as_admin: bool = None, use_likely_area: bool = None, sleep_time: int = None)

Class contains the most commonly used powershell Windows commands. Every command is called using start_process() method.

Parameters
  • rdp_robot – Instance of RDPRobot

  • timeout – Timeout in which should the Windows “Run” window be found

  • as_admin – Start this command as admin.

  • use_likely_area – If True, it uses area in which is more likely to find “Run” window.

  • sleep_time – Implicit sleep between sub-commands execution

execute()

Executes commands.

Example

>>> import aiviro
>>> from aiviro.modules.powershell import ShellCommands
>>> r = aiviro.create_rdp_robot()
>>> ShellCommands(r).remove_file("C:/user/Documents/*").stop_process("notepad").execute()
open_explorer(*path: Union[str, pathlib.PureWindowsPath]) aiviro.modules.powershell.commands.ShellCommands

Open Windows explorer on supplied path.

Warning

When specifing drive you must also include suffix :/. If you don’t then it is treated like a folder. If you write only : then the path points to current working directory the drive. You should always use X:/ for the root location of drive X.

Parameters

path – Path to a folder.

Example

>>> import pathlib
>>> import aiviro
>>> from aiviro.modules.powershell import ShellCommands
>>> r = aiviro.create_rdp_robot()
>>> shell_cmd = ShellCommands(rdp_robot=r)
>>> # Here are some examples how to specify the path
>>> shell_cmd.open_explorer("c:/", "Users", "your_account").execute()
>>> shell_cmd.open_explorer(pathlib.PureWindowsPath("c:/") / "Users" / "your_account").execute()
>>> shell_cmd.open_explorer("c:/", pathlib.PureWindowsPath("Users", "your_account")).execute()
remove_file(*path: Union[str, pathlib.PureWindowsPath], recursive: bool = False) aiviro.modules.powershell.commands.ShellCommands

Removes file or all files in the folder.

Parameters
  • path – Path to a file or folder.

  • recursive – Set to True, if also sub-folders need to be removed.

Example

>>> import aiviro
>>> from aiviro.modules.powershell import ShellCommands
>>> r = aiviro.create_rdp_robot()
>>> ShellCommands(r).remove_file("C:/Users/me/Documents/*").execute()
stop_process(*process_name: str, force: bool = True, restart_explorer: bool = False) aiviro.modules.powershell.commands.ShellCommands

Closes supplied applications.

Parameters
  • process_name – Name of the process, Examples: notepad, your_application.exe.

  • force – If True applications are force-closed, otherwise gracefully closing.

  • restart_explorer – If also explorer should be restarted.

Example

>>> import aiviro
>>> from aiviro.modules.powershell import ShellCommands
>>> r = aiviro.create_rdp_robot()
>>> ShellCommands(r, as_admin=True).stop_process("notepad", "your_application.exe").execute()
close_all_open_windows(force: bool = True) aiviro.modules.powershell.commands.ShellCommands

Closes all open windows.

Parameters

force – If True applications are force-closed, otherwise gracefully closing.

Example

>>> import aiviro
>>> from aiviro.modules.powershell import ShellCommands
>>> r = aiviro.create_rdp_robot()
>>> ShellCommands(r).close_all_open_windows().execute()
create_directory(*path: Union[str, pathlib.PureWindowsPath], open: bool = False) aiviro.modules.powershell.commands.ShellCommands

Creates new directory.

Parameters
  • path – Path to a new directory.

  • open – If True, new created directory will be open.

Example

>>> import pathlib
>>> import aiviro
>>> from aiviro.modules.powershell import ShellCommands
>>> r = aiviro.create_rdp_robot()
>>> shell_cmd = ShellCommands(rdp_robot=r)
>>> # Here are some examples how to specify the path
>>> shell_cmd.create_directory("c:/", "Users", "your_account").execute()
>>> shell_cmd.create_directory(pathlib.PureWindowsPath("c:/") / "Users" / "your_account").execute()
>>> shell_cmd.create_directory("c:/", pathlib.PureWindowsPath("Users", "your_account"), open=True).execute()
move_file(source_path: Union[str, pathlib.PureWindowsPath], destination_path: Union[str, pathlib.PureWindowsPath], create_output_directory: bool = False, force: bool = False) aiviro.modules.powershell.commands.ShellCommands

Moves file from source to destination path.

Parameters
  • source_path – Source path of the file

  • destination_path – Destination path of the file

  • create_output_directory – If True, output directory will be created

  • force – Command runs without asking for user confirmation

Example

>>> import aiviro
>>> from aiviro.modules.powershell import ShellCommands
>>> r = aiviro.create_rdp_robot()
>>> ShellCommands(r).move_file(
...     "c:/path/file.pdf",
...     "c:/path/folder/file.pdf",
...     create_output_directory=True
... ).execute()
copy_file(source_path: Union[str, pathlib.PureWindowsPath], destination_path: Union[str, pathlib.PureWindowsPath], recursive: bool = False, force: bool = False) aiviro.modules.powershell.commands.ShellCommands

Copy file from source to destination path.

Parameters
  • source_path – Source path of the file

  • destination_path – Destination path of the file

  • recursive – It does a recursive copy

  • force – Copies items that can’t otherwise be changed, such as copying over a read-only file or alias

Example

>>> import aiviro
>>> from aiviro.modules.powershell import ShellCommands
>>> r = aiviro.create_rdp_robot()
>>> ShellCommands(r).copy_file(
...     "c:/path/file.pdf",
...     "c:/path/folder/file.pdf",
... ).execute()
copy_file_into_clipboard(file_path: Union[str, pathlib.PureWindowsPath]) aiviro.modules.powershell.commands.ShellCommands

Copies file into remote(guest’s) clipboard. The command can be then combined with transfer_files_from_guests_clipboard().

Parameters

file_path – Path to a file

Example

>>> import aiviro
>>> from aiviro.modules.powershell import ShellCommands
>>> r = aiviro.create_rdp_robot()
>>> ShellCommands(r).copy_file_into_clipboard("c:/path/file.pdf").execute()
>>> r.transfer_files_from_guests_clipboard("some/local/dir/")
["some/local/dir/file.pdf"]
paste_file_from_clipboard(destination_dir: Union[str, pathlib.PureWindowsPath], create_destination_directory: bool = False) aiviro.modules.powershell.commands.ShellCommands

Pastes file from clipboard into destination folder.

Parameters

destination_dir – Folder where file will be pasted

Example

>>> import aiviro
>>> from aiviro.modules.powershell import ShellCommands
>>> r = aiviro.create_rdp_robot()
>>> ShellCommands(r).paste_file_from_clipboard("c:/destination/dir/").execute()

QR, Bar Codes

Note

It’s required to install codes from Optional dependencies section.

class aiviro.modules.codes.CodesExtractor(pdf_data: Optional[Union[aiviro.modules.pdf.robot.PDFRobot, aiviro.modules.pdf.convertor.PDFConvertor, List[numpy.ndarray]]] = None)

Codes extractor detects and extracts QR and Bar codes from PDFs and images. For list of supported codes, see https://pypi.org/project/pyzbar/ package documentation.

Parameters

pdf_data – Source of the image data for processing

Example

>>> from aiviro.modules.pdf import create_pdf_robot
>>> from aiviro.modules.codes import CodesExtractor
>>> r = create_pdf_robot("path/to/file.pdf")
>>> ce = CodesExtractor(r)
>>> qr_codes = ce.qr_codes(page=1)
>>> bar_codes = ce.bar_codes(page=0)
>>> from aiviro.modules.codes import ZBarSymbol
>>> r = create_pdf_robot("path/to/file.pdf")
>>> ce = CodesExtractor(r)
>>> custom_codes = ce.any_codes(code_types=[ZBarSymbol.PDF417])
qr_codes(page: int = 0) List[aiviro.modules.codes.common.CodeData]

Extracts QR codes.

Parameters

page – Index of the page to process

bar_codes(page: int = 0) List[aiviro.modules.codes.common.CodeData]

Extracts Bar codes.

Parameters

page – Index of the page to process

any_codes(page: int, code_types: List[pyzbar.wrapper.ZBarSymbol]) List[aiviro.modules.codes.common.CodeData]

Extracts any of the supported codes.

Parameters
  • page – Index of the page to process

  • code_types – Types of codes to extract

static any_codes_img(image: numpy.ndarray, code_types: List[pyzbar.wrapper.ZBarSymbol]) List[aiviro.modules.codes.common.CodeData]

Extracts any of the supported codes from input image.

Parameters
  • image – Image containing codes

  • code_types – Types of codes to extract

class aiviro.modules.codes.BaseCodeDecoder(*args, **kwds)

Base class to inherit from for creating custom code decoder.

abstract decode(raw_text: List[aiviro.modules.codes.common.CodeData]) aiviro.modules.codes.common.T

Main decoding logic

Parameters

raw_text – Raw text data

Czech Invoice Format

class aiviro.modules.codes.CzechQRInvoiceDecoder(*args, **kwds)

Decodes QR data based on https://qr-faktura.cz/ format definition. See CzechQRInvoiceData for further information.

Example

>>> from aiviro.modules.pdf import create_pdf_robot
>>> from aiviro.modules.codes import CodesExtractor, CzechQRInvoiceDecoder
>>> r = create_pdf_robot("path/to/file.pdf")
>>> qr_data = CodesExtractor(r).qr_codes()
>>> decoded_data = CzechQRInvoiceDecoder().decode(qr_data)[0]
...
>>> invoice_id = decoded_data.get_value("ID")
class aiviro.modules.codes.CzechQRInvoiceData(_dict_values: typing.Dict[str, str] = <factory>)

Data class containing decoded data from QR code.

get_value(key: str) str

Returns value based on the specified key.

property currency: str

Returns type of currency, based on ‘CC’ key.

property total_amount: decimal.Decimal

Returns total_amount, based on ‘AM’ key.

get_decimal(key: str = 'AM') decimal.Decimal

Returns value in Decimal format based on input key.

get_date(key: str = 'DD') datetime.date

Returns value in date format based on input key.

Configuration

To easily load and access your configuration options, you can use one of the provided objects. Loaded options are accessible via the dot notation of variables.

Note

Keys from the configuration files are normalized into variables names, e.g. lower-cased, additional spaces are removed, special characters are replaced with “_” and accents are removed. For example Č. org. will transform into c_org or DIČ DPH into dic_dph.

class aiviro.modules.config.YAMLConfig(file_name: str, file_dir: Optional[Union[str, pathlib.Path]] = None, encoding: str = 'utf-8')

It loads YAML configuration file, and provides interface for easy access to the loaded data.

Parameters
  • file_name – Name of the yaml configuration file

  • file_dir – Folder of the configuration files, can be also set by CONFIG_PATH environmental variable If CONFIG_PATH is not set, file_dir must be set

# example of YAML configuration file
# "data/configuration/config.yaml"
email:
  username: aiviro.robot
  password: "*******"
  smtp: smtp.server.com
  imap: smtp.server.com
rdp:
  ip_address: 192.168.0.15
  username: aiviro
  password: "*******"
  domain: ""
Example

>>> import aiviro
>>> from aiviro.modules.config import YAMLConfig
>>> cfg = YAMLConfig("config.yaml", "data/configuration/")
>>> r = aiviro.create_rdp_robot(
...     cfg.rdp.ip_address,
...     cfg.rdp.username,
...     cfg.rdp.password,
...     cfg.rdp.domain
... )
class aiviro.modules.config.CSVConfig(file_name: str, file_dir: Optional[Union[str, pathlib.Path]] = None, encoding: str = 'utf-8', dialect: str = 'excel')

It loads CSV configuration file, and provides interface for easy access to the loaded data.

Parameters
  • file_name – Name of the yaml configuration file

  • file_dir – Folder of the configuration files, can be also set by CONFIG_PATH environmental variable If CONFIG_PATH is not set, file_dir must be set

Č. org.

Název

Řada

Měna

DIČ DPH

52

Supplier 1

601

CZK

CZ12345678

53

Supplier 2

603

CZK

CZ99998888

98

Supplier 3

555

EUR

DE12345678

Example

>>> from aiviro.modules.config import CSVConfig
>>> cfg = CSVConfig("robot_config.csv", "data/configuration/")
>>> # get "Č. org." of "Supplier 2"
>>> org_number = cfg.nazev["Supplier 2"].c_org