diff --git a/python/incendium/__init__.py b/python/incendium/__init__.py index ed56cb1..80422af 100644 --- a/python/incendium/__init__.py +++ b/python/incendium/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 +# Copyright (C) 2019 # Author: Cesar Roman # Contact: thecesrom@gmail.com diff --git a/python/incendium/constants.py b/python/incendium/constants.py index 81c8611..fff6c7f 100644 --- a/python/incendium/constants.py +++ b/python/incendium/constants.py @@ -1,13 +1,28 @@ -# Copyright (C) 2018 +# Copyright (C) 2019 # Author: Cesar Roman # Contact: thecesrom@gmail.com -"""Incendium Constants module.""" +"""Constants module.""" # Email settings. SMTP = 'mail.mycompany.com:25' SENDER = 'no-reply@mycompany.com' +# Email templates. +ERROR_REPORT = """ + + + Error Report.

+ Error Message
+

%s



+ Error Details +

%s



+ System Details

+ *** Please do not reply to this email address. +
+ +""" + # Language settings. DEFAULT_LANGUAGE = 'en_US' @@ -37,6 +52,7 @@ PROCEED_WITHOUT_SAVING_CHANGES = ('Would you like to proceed without saving ' 'your changes?') SUCCESS_WINDOW_TITLE = 'Success' +TABBED_LINE = ' - ' UNEXPECTED_ERROR = 'An unexpected error occurred in %s. \n%s' UNEXPECTED_ERROR_CAUSED_BY = ('An unexpected error occurred in %s. ' '\n%s\nCaused by: %s') diff --git a/python/incendium/dataset.py b/python/incendium/dataset.py index 8272350..d35f774 100644 --- a/python/incendium/dataset.py +++ b/python/incendium/dataset.py @@ -1,8 +1,8 @@ -# Copyright (C) 2018 +# Copyright (C) 2019 # Author: Cesar Roman # Contact: thecesrom@gmail.com -"""Incendium Dataset module.""" +"""Dataset module.""" __all__ = [ 'to_xml' diff --git a/python/incendium/date.py b/python/incendium/date.py index 3083e63..6d07d40 100644 --- a/python/incendium/date.py +++ b/python/incendium/date.py @@ -1,8 +1,8 @@ -# Copyright (C) 2018 +# Copyright (C) 2019 # Author: Cesar Roman # Contact: thecesrom@gmail.com -"""Incendium Date module.""" +"""Date module.""" __all__ = [ 'compare' diff --git a/python/incendium/db.py b/python/incendium/db.py index 6d714c7..635daff 100644 --- a/python/incendium/db.py +++ b/python/incendium/db.py @@ -1,8 +1,8 @@ -# Copyright (C) 2018 +# Copyright (C) 2019 # Author: Cesar Roman # Contact: thecesrom@gmail.com -"""Incendium Database module.""" +"""Database module.""" __all__ = [ 'check', @@ -122,13 +122,16 @@ def _execute_sp(stored_procedure, database='', transaction=None, return _result -def check(stored_procedure, params=None): +def check(stored_procedure, database='', params=None): """Executes a stored procedure that returns a flag set to TRUE or FALSE. Args: stored_procedure (str): The name of the stored procedure to execute. + database (str): The name of the database connection to execute + against. If omitted or "", the project's default database + connection will be used. Optional. params (dict): A Dictionary containing all parameters. Optional. @@ -138,12 +141,14 @@ def check(stored_procedure, params=None): output = {'flag': system.db.BIT} output_params = get_output_params(stored_procedure, output=output, + database=database, params=params) return output_params['flag'] -def execute_non_query(stored_procedure, params=None, transaction=None): +def execute_non_query(stored_procedure, database='', transaction=None, + params=None): """Executes a stored procedure against the connection and returns the number of rows affected. @@ -152,16 +157,20 @@ def execute_non_query(stored_procedure, params=None, transaction=None): Args: stored_procedure (str): The name of the stored procedure to execute. - params (dict): A Dictionary containing all parameters. - Optional. + database (str): The name of the database connection to execute + against. If omitted or "", the project's default database + connection will be used. Optional. transaction (str): A transaction identifier. If omitted, the call will be executed in its own transaction. Optional. + params (dict): A Dictionary containing all parameters. + Optional. Returns: int: The number of rows modified by the stored procedure, or -1 if not applicable. """ result = _execute_sp(stored_procedure, + database=database, transaction=transaction, in_params=params, get_update_count=True) @@ -169,12 +178,15 @@ def execute_non_query(stored_procedure, params=None, transaction=None): return result.update_count -def get_data(stored_procedure, params=None): +def get_data(stored_procedure, database='', params=None): """Returns data by executing a stored procedure. Args: stored_procedure (str): The name of the stored procedure to execute. + database (str): The name of the database connection to execute + against. If omitted or "", the project's default database + connection will be used. Optional. params (dict): A Dictionary containing all parameters. Optional. @@ -183,28 +195,34 @@ def get_data(stored_procedure, params=None): procedure call, if any. """ result = _execute_sp(stored_procedure, + database=database, in_params=params, get_result_set=True) return result.result_set -def get_output_params(stored_procedure, output, params=None, transaction=None): +def get_output_params(stored_procedure, output, database='', transaction=None, + params=None): """Gets the Output parameters from the Stored Procedure. Args: stored_procedure (str): The name of the stored procedure to execute. output (dict): A Dictionary containing all output parameters. - params (dict): A Dictionary containing all parameters. - Optional. + database (str): The name of the database connection to execute + against. If omitted or "", the project's default database + connection will be used. Optional. transaction (str): A transaction identifier. If omitted, the call will be executed in its own transaction. Optional. + params (dict): A Dictionary containing all parameters. + Optional. Returns: dict: Result's output_params. """ result = _execute_sp(stored_procedure, + database=database, transaction=transaction, in_params=params, out_params=output, @@ -213,23 +231,27 @@ def get_output_params(stored_procedure, output, params=None, transaction=None): return result.output_params -def get_return_value(stored_procedure, return_type_code, params=None, - transaction=None): +def get_return_value(stored_procedure, return_type_code, database='', + transaction=None, params=None): """Gets the Return Value from the Stored Procedure. Args: stored_procedure (str): The name of the stored procedure to execute. return_type_code (int): The Type Code of the Return Value. - params (dict): A Dictionary containing all parameters. - Optional. + database (str): The name of the database connection to execute + against. If omitted or "", the project's default database + connection will be used. Optional. transaction (str): A transaction identifier. If omitted, the call will be executed in its own transaction. Optional. + params (dict): A Dictionary containing all parameters. + Optional. Returns: int: The return value. """ result = _execute_sp(stored_procedure, + database=database, transaction=transaction, in_params=params, return_type_code=return_type_code, diff --git a/python/incendium/exceptions.py b/python/incendium/exceptions.py index da0a924..8f62f3f 100644 --- a/python/incendium/exceptions.py +++ b/python/incendium/exceptions.py @@ -1,8 +1,8 @@ -# Copyright (C) 2018 +# Copyright (C) 2019 # Author: Cesar Roman # Contact: thecesrom@gmail.com -"""Incendium Exceptions module.""" +"""Exceptions module.""" __all__ = [ 'ApplicationError', diff --git a/python/incendium/gui.py b/python/incendium/gui.py index 97c3fa3..b635e2a 100644 --- a/python/incendium/gui.py +++ b/python/incendium/gui.py @@ -1,8 +1,8 @@ -# Copyright (C) 2018 +# Copyright (C) 2019 # Author: Cesar Roman # Contact: thecesrom@gmail.com -"""Incendium GUI module.""" +"""GUI module.""" __all__ = [ 'confirm', diff --git a/python/incendium/nav.py b/python/incendium/nav.py index 3c3d7cd..1fee470 100644 --- a/python/incendium/nav.py +++ b/python/incendium/nav.py @@ -1,8 +1,8 @@ -# Copyright (C) 2018 +# Copyright (C) 2019 # Authors: Cesar Roman, Kyle Chase. # Contact: thecesrom@gmail.com -"""Incendium Navigation module.""" +"""Navigation module.""" __all__ = [ 'swap_to', diff --git a/python/incendium/net.py b/python/incendium/net.py index 2620426..f6c63b2 100644 --- a/python/incendium/net.py +++ b/python/incendium/net.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 +# Copyright (C) 2019 # Author: Cesar Roman # Contact: thecesrom@gmail.com @@ -12,6 +12,21 @@ import system.net from incendium import constants +HTML_ESCAPE_TABLE = { + '&': '&', + '"': '"', + "'": ''', + '>': '>', + '<': '<', + '\n': '
', + '\t': ' ' * 4 +} + + +def _html_escape(text): + """Produce entities within text.""" + return "".join(HTML_ESCAPE_TABLE.get(c, c) for c in text) + def _send_email(subject, body, html, to, priority): """Sends an email through the given SMTP server. @@ -24,9 +39,31 @@ def _send_email(subject, body, html, to, priority): to (list[str]): A list of email addresses to send to. priority (str): Priority for the message. """ - system.net.sendEmail(smtp=constants.SMTP, fromAddr=constants.SENDER, - subject=subject, body=body, html=html, to=to, - priority=priority) + try: + system.net.sendEmail( + smtp=constants.SMTP, + fromAddr=constants.SENDER, + subject=subject, + body=body, + html=html, + to=to, + priority=priority + ) + finally: + pass + + +def report_error(subject, message, details, to): + """Sends an Error Report email message. + + Args: + subject (str): The subject line for the email. + message (str): The error message. + details (str): The error details. + to (list[str]): A list of emails addresses to send to. + """ + body = constants.ERROR_REPORT % (message, _html_escape(details)) + send_high_priority_email(subject, body, to) def send_high_priority_email(subject, body, to): @@ -46,9 +83,9 @@ def send_html_email(subject, body, to, priority='3'): Args: subject (str): The subject line for the email. body (str): The body text of the email in HTML format. - to (list[str]): A List of email addresses to send to. - priority (str): Priority of the message, from "1" to "5", with - "1" being highest priority. Defaults to "3" (normal) + to (list[str]): A list of email addresses to send to. + priority (str): Priority of the message, from "1" to "5", + with "1" being highest priority. Defaults to "3" (normal) priority. Optional. """ _send_email(subject, body, True, to, priority) diff --git a/python/incendium/user.py b/python/incendium/user.py index 7a32c8f..57b0062 100644 --- a/python/incendium/user.py +++ b/python/incendium/user.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 +# Copyright (C) 2019 # Author: Cesar Roman # Contact: thecesrom@gmail.com diff --git a/python/incendium/util.py b/python/incendium/util.py index b19bdde..621b9d1 100644 --- a/python/incendium/util.py +++ b/python/incendium/util.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 +# Copyright (C) 2019 # Author: Cesar Roman # Contact: thecesrom@gmail.com @@ -87,21 +87,36 @@ def validate_form(strings=None, numbers=None, collections=None): # Initialize variables. is_valid = True error_message = constants.EMPTY_STRING + counter = 0 if strings: - for k, v in strings.iteritems(): - if not v: - error_message += constants.NEW_TABBED_LINE + k + for key, value in strings.iteritems(): + if not value: + counter += 1 + if counter == 1: + error_message += constants.TABBED_LINE + key + else: + error_message += constants.NEW_TABBED_LINE + key is_valid = False if numbers: - for k, v in numbers.iteritems(): - if v is None or v <= 0: - error_message += constants.NEW_TABBED_LINE + k + for key, value in numbers.iteritems(): + if value is None or value <= 0: + counter += 1 + if counter == 1: + error_message += constants.TABBED_LINE + key + else: + error_message += constants.NEW_TABBED_LINE + key is_valid = False if collections: - for k, v in collections.iteritems(): - if v is None or v <= 0: - error_message += constants.NEW_TABBED_LINE + k + for key, value in collections.iteritems(): + if value is None or value <= 0: + counter += 1 + error_message += (constants.TABBED_LINE + key if counter == 1 + else constants.NEW_TABBED_LINE + key) + if counter == 1: + error_message += constants.TABBED_LINE + key + else: + error_message += constants.NEW_TABBED_LINE + key is_valid = False return is_valid, error_message