
# pcof - Python Collection Of Functions

![Build Status](https://github.com/thobiast/pcof/workflows/Python%20application/badge.svg)
![GitHub License](https://img.shields.io/github/license/thobiast/pcof)(https://github.com/thobiast/pcof/blob/master/LICENSE)

## Prerequisites

All functions were tested using Python version 3.


## Documentation (automatically generated using pydoc)

Help on module pcof:

NAME
    pcof - Python Collection Of Functions

DESCRIPTION
    This module has a collection of many small generic useful functions.
    
    Developed for Python 3

FUNCTIONS
    bytes2human(size, *, unit='', precision=2, base=1024)
        Convert number in bytes to human format
        
        Arguments:
            size        (int): bytes to be converted
        
        Keyword arguments (opt):
            unit       (str): If it will convert bytes to a specific unit
                              'KB', 'MB', 'GB', 'TB', 'PB', 'EB'
            precision  (int): number of digits after the decimal point
            base       (int): 1000 - for decimal base
                              1024 - for binary base (it is the default)
        
        Returns:
            (int): number
            (str): unit (Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB']
        
        Exemple:
            >>> bytes2human(10)
            ('10.00', 'Bytes')
            >>> bytes2human(2048)
            ('2.00', 'KB')
            >>> bytes2human(27273042329)
            ('25.40', 'GB')
            >>> bytes2human(27273042329, precision=1)
            ('25.4', 'GB')
            >>> bytes2human(27273042329, unit='MB')
            ('26009.60', 'MB')
    
    convert_datetime_to_tz(*, date, date_fmt, from_tz='UTC', to_tz='America/Sao_Paulo')
        Convert a date to a specific timezone.
        
        Keyword arguments:
        
            date      (str):      date to convert
            date_fmt  (str):      format of the date to convert
            from_tz   (timezone): source timezone name (default: UTC)
            to_tz     (timezone): target timezone name (default: America/Sao_Paulo)
        
        Returns:
            datetime object with the target timezone defined.
        
        Example:
        >>> convert_datetime_to_tz(date='2019-04-26T10:38:05Z', date_fmt="%Y-%m-%dT%H:%M:%SZ")
        datetime.datetime(2019, 4, 26, 7, 38, 5, tzinfo=<DstTzInfo 'America/Sao_Paulo' -03-1 day, 21:00:00 STD>)
        
        >>> convert_datetime_to_tz(date='2019-04-26T10:38:05Z', date_fmt="%Y-%m-%dT%H:%M:%SZ", from_tz="America/Sao_Paulo", to_tz="America/Los_Angeles")
        datetime.datetime(2019, 4, 26, 6, 38, 5, tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>)
        
        >>> convert_datetime_to_tz(date='2019-04-26T10:38:05Z', date_fmt="%Y-%m-%dT%H:%M:%SZ", from_tz="America/Sao_Paulo", to_tz="Asia/Dubai")
        datetime.datetime(2019, 4, 26, 17, 38, 5, tzinfo=<DstTzInfo 'Asia/Dubai' +04+4:00:00 STD>)
    
    epoch_time_days_ago(days=1, *, utc='no')
        Return current date and time with less x days in unix epoch time format
        
        Unix epoch time -  number of seconds that have elapsed since
                           00:00:00 Coordinated Universal Time (UTC),
                           1 January 1970
        
        Arguments (opt):
            days       (int):   Number of days ago to return unix timestamp
                                  default is 1 day
        
        Keyword arguments (opt):
            utc       (yes/no): If unix epoch time in UTC timezone
                                default is no
        Example:
        >>> epoch_time_days_ago()
        1530239517
        >>> epoch_time_days_ago(7)
        1529721118
    
    epoch_time_hours_ago(hours=1, *, utc='no')
        Return current date and time with less x hours in unix epoch time format
        
        Unix epoch time -  number of seconds that have elapsed since
                           00:00:00 Coordinated Universal Time (UTC),
                           1 January 1970
        
        Arguments (opt):
            hours     (int):    Number of hours ago to return unix timestamp
                                default is 1 hour
        
        Keyword arguments (opt):
            utc       (yes/no): If unix epoch time in UTC timezone
                                default is no
        Example:
        >>> epoch_time_hours_ago()
        1530322279
        >>> epoch_time_hours_ago(8)
        1530297083
    
    epoch_time_min_ago(minutes=5, *, utc='no')
        Return current date and time less x minutes in unix epoch time format
        
        Unix epoch time -  number of seconds that have elapsed since
                           00:00:00 Coordinated Universal Time (UTC),
                           1 January 1970
        
        Arguments (opt):
            minutes  (int): Number of minutes ago to return unix timestamp
                            default is 5 minutes
        
        Keyword arguments (opt):
            utc         (yes/no): If unix epoch time in UTC timezone
                                  default is no
        Example:
        >>> epoch_time_min_ago()
        1530325377
        >>> epoch_time_min_ago(30)
        1530323879
    
    epoch_time_now(*, utc='no')
        Return current date and time in unix epoch time format
        
        Unix epoch time -  number of seconds that have elapsed since
                           00:00:00 Coordinated Universal Time (UTC),
                           1 January 1970
        
        Arguments:
            utc         (yes/no): If returns unix epoch time in UTC timezone
                                  default is no
        Example:
        >>> epoch_time_now()
        1530325275
    
    epoch_time_to_human(epoch, *, date_format='%c', utc='no')
        Convert a unix epoch time to human format
        
        Unix epoch time -  number of seconds that have elapsed since
                           00:00:00 Coordinated Universal Time (UTC),
                           1 January 1970
        
        Arguments:
            epoch       (int):    unix epoch time (timestamp)
        
        Keyword arguments (opt):
            date_format (str):    strftime format to show the epoch time
                                  default is '%c' (Locale’s appropriate
                                  date and time representation)
            utc         (yes/no): If unix epoch time in UTC timezone
                                  default is no
        
        Example:
        >>> epoch_time_to_human(1530324373,'%m/%d/%Y %H:%M:%S')
        '06/29/2018 23:06:13'
        >>> epoch_time_to_human(1530324373)
        'Fri Jun 29 23:06:13 2018'
        >>> epoch_time_to_human(1530324373, utc='yes')
        'Sat Jun 30 02:06:13 2018'
    
    find_key(dict_obj, key)
        Function to loop over a dictionary and search for an specific key
        It supports nested dictionary
        Params:
            dict_obj    (obj): A list or a dictionary
            key         (str): dictionary key
        
        Return a list with values that matches the key
    
    human2bytes(size, unit, *, precision=2, base=1024)
        Convert size from human to bytes
        
        Arguments:
            size       (int): number
            unit       (str): converts from this unit to bytes
                              'KB', 'MB', 'GB', 'TB', 'PB', 'EB'
        
        Keyword arguments (opt):
            precision  (int): number of digits after the decimal point
                              default is 2
            base       (int): 1000 - for decimal base
                              1024 - for binary base (it is the default)
        
        Returns:
            (int) number in bytes
        
        Example:
            >>> human2bytes(10, 'GB')
            '10737418240.00'
            >>> human2bytes(10, 'GB', precision=0)
            '10737418240'
            >>> human2bytes(10, 'PB')
            '11258999068426240.00'
    
    msg(color, msg_text, exitcode=0, *, mail_from=None, mail_to=None, mail_server='localhost', subject=None, end='\n')
        Print colored text.
        
        Arguments:
            size      (str): color name (blue, red, green, yellow,
                                         cyan or nocolor)
            msg_text  (str): text to be printed
            exitcode  (int, opt): Optional parameter. If exitcode is different
                                  from zero, it terminates the script, i.e,
                                  it calls sys.exit with the exitcode informed
        
        Keyword arguments to send the msg_text by email too:
            mail_from   (str, opt): send email from this address
            mail_to     (str, opt): send email to this address
            subject     (str, opt): mail subject
            mail_server (str, opt): mail server address
            end         (str, opt): string appended after the last value,
                                    default a newline
        
        
        Exemplo:
            msg("blue", "nice text in blue")
            msg("red", "Error in my script.. terminating", 1)
    
    nested_dict()
        Returns a nested dictionary, i.e, an dictionary with
        arbitrary number of levels.
        
        Example:
        >>> mydict = nested_dict()
        >>> mydict['aa']['bb']['cc'] = 'teste'
        >>> print(mydict)
             defaultdict(<function nested_dict at 0x7f1e74b8bea0>, {'aa':
             defaultdict(<function nested_dict at 0x7f1e74b8bea0>, {'bb':
             defaultdict(<function nested_dict at 0x7f1e74b8bea0>, {'cc':
             'teste'})})})
        >>> import pprint
        >>> pprint.pprint(mydict)
             {'aa': {'bb': {'cc': 'teste'}}}
    
    pct_two_numbers(number1, number2, *, precision='2')
        Calculate the percentage of number1 to number2, i.e,
        number1 is what percent of number2
        
        Arguments:
            number1 (int): number
            number2 (int): number
        
        Keyword arguments (opt):
            precision  (int): number of digits after the decimal point
                              default is 2
        
        Returns:
            (int): Pct value
        
        Example:
        >>> pct_two_numbers(30, 90)
        '33.33'
        >>> pct_two_numbers(30, 90, precision=0)
        '33'
        >>> pct_two_numbers(30, 90, precision=4)
        '33.3333'
        >>> pct_two_numbers(10, 50)
        '20.00'
    
    print_table(header, rows, *, sortby='', alignl='', alignr='', hrules='')
        Print table using module prettytable
        Arguments:
            header     (list): List with table header
            rows       (list): Nested list with table rows
                               [ [row1], [row2], [row3], ... ]
        
        Keyword arguments (optional):
            sortby      (str): header name to sort the output
            alignl     (list): headers name to align to left
            alignr     (list): headers name to align to right
            hrules      (str): Controls printing of horizontal rules after rows.
                               Allowed values: FRAME, HEADER, ALL, NONE
    
    return_dict_value(dictionary, keys, *, ignore_key_error=False)
        Recursively iterate over a dictionary and return value
        for the key. Key must be a list. Each element of the list refers
        to the level of the dicionary
        
        It helps to reduce number of code lines when we need to perform may
        try: except: to catch KeyErrors
        
        Args:
           dictionary              (dict): Dictionary
           keys                    (list): List with key(s)
           ignore_key_error  (True/False): Ignore key not found errors:
                                             True  - return '' if key not found
                                             False - raise exception
                                           default: False
        
        Example:
        >>> from pcof import return_dict_value
        >>> mydic = { 'a': 'value_a',
        ...           'b': {
        ...                  'b1': 'value_b1',
        ...                  'b2': 'value_b2'
        ...                },
        ...           'c': {
        ...                  'c1': {
        ...                          'c11': 'value_c11',
        ...                          'c12': 'value_c12'
        ...                         }
        ...                },
        ...          }
        >>> return_dict_value(mydic, ['a'])
            'value_a'
        >>> return_dict_value(mydic, ['b'])
            {'b2': 'value_b2', 'b1': 'value_b1'}
        >>> return_dict_value(mydic, ['b', 'b1'])
            'value_b1'
        >>> return_dict_value(mydic, ['c', 'c1', 'c12'])
            'value_c12'
        >>> return_dict_value(mydic, ['c', 'c1', 'c13'])
            Traceback (most recent call last):
              File "<stdin>", line 1, in <module>
              File "/home/thobias/repo/pcof/pcof.py", line 288, in return_dict_value
                return return_dict_value(dictionary[keys[0]], keys[1:])
              File "/home/thobias/repo/pcof/pcof.py", line 288, in return_dict_value
                return return_dict_value(dictionary[keys[0]], keys[1:])
              File "/home/thobias/repo/pcof/pcof.py", line 297, in return_dict_value
                return dictionary[keys[0]]
            KeyError: 'c13'
        >>> return_dict_value(mydic, ['c', 'c1', 'c13'], ignore_key_error=True)
            ''
        >>> return_dict_value(mydic, ['x'], ignore_key_error=True)
            ''
    
    run_cmd(cmd)
        Execute a command on the operating system
        
        Arguments:
            cmd    (str): the command to be executed
        
        Return:
            - If command complete with return code zero
            return: command_return_code, stdout
        
            - If command completes with return code different from zero
            return: command_return_code, stderr
    
    seconds_to_human(seconds, *, unit=None)
        Convert number in seconds to human format
        
        Arguments:
            seconds   (int):                               Number of seconds
        
        Keyword arguments (opt):
            unit      (Months/Days/Hours/Minutes/Seconds): Max unit used
                                                           to convert
        
        Example:
        >>> seconds_to_human(300)
        '5 Minutes'
        >>> seconds_to_human(310)
        '5 Minutes, 10 Seconds'
        >>> seconds_to_human(10810)
        '3 Hours, 10 Seconds'
        >>> seconds_to_human(10810, unit='Minutes')
        '180 Minutes, 10 Seconds'
        >>> seconds_to_human(180072)
        '2 Days, 2 Hours, 1 Minutes, 12 Seconds'
        >>> seconds_to_human(5191272)
        '2 Months, 2 Hours, 1 Minutes, 12 Seconds'
    
    send_email(mail_from, mail_to, subject, body, mailserver='localhost')
        Send an email using smtplib module
        
        Arguments:
            mail_from   (str): send email from this address
            mail_to     (str): send email to this address
            subject     (str): mail subject
            mail_server (str, opt): mail server address. Default is localhost
    
    setup_logging(logfile=None, *, filemode='a', date_format=None, log_level='DEBUG')
        Configure logging
        
        Arguments (opt):
            logfile     (str): log file to write the log messages
                                   If not specified, it shows log messages
                                   on screen (stderr)
        Keyword arguments (opt):
            filemode    (a/w): a - log messages are appended to the file (default)
                               w - log messages overwrite the file
            date_format (str): date format in strftime format
                               default is %m/%d/%Y %H:%M:%S
            log_level   (str): specifies the lowest-severity log message
                               DEBUG, INFO, WARNING, ERROR or CRITICAL
                               default is DEBUG
    
    validate_ip(ip_address)
        Validate IP address format
        
        Arguments:
            ip_address   (str): IP address
        
        Returns:
            If it is a valid IP address, return a corresponding match object,
            otherwise, return None.
        
        Exemple:
            >>> pcof.validate_ip('127.0.0.1')
            <_sre.SRE_Match object; span=(0, 9), match='127.0.0.1'>
            >>> pcof.validate_ip('127.0.0.a')
            >>>
    
    x_pct_of_number(pct, number, *, precision='2')
        Calculate what is the x% of a number
        
        Arguments:
            pct        (int): percentage
            number     (int): number
        
        Keyword arguments (opt):
            precision  (int): number of digits after the decimal point
                              default is 2
        
        Returns:
            (int):  number
        
        Exemple:
        >>> x_pct_of_number(33.333, 90)     # what is 33.333% of 90
        '30.00'
        >>> x_pct_of_number(40, 200)        # what is 40% of 200
        '80.00'
        >>> x_pct_of_number(40.9, 200)      # what is 40.9* of 200
        '81.80'
        >>> x_pct_of_number(40.9, 200, precision=4)
        '81.8000'
        >>> x_pct_of_number(40.9, 200, precision=0)

