Source code for utilities

# python 2
from __future__ import absolute_import, print_function, division, unicode_literals
from builtins import str, round

# builtins
from re import search, findall
from inspect import currentframe
from os import path, stat, getcwd, makedirs, remove
import logging

# custom
import blowdrycss_settings as settings


__author__ = 'chad nelson'
__project__ = 'blowdrycss'


[docs]def contains_a_digit(string=''): """ Check if string contains a digit ``[0-9]``. :type string: str :param string: The string to test. :return: (bool) -- Returns True if string contains at least 1 digit. Otherwise, returns False. **Examples:** >>> contains_a_digit('abc1') True >>> contains_a_digit('876') True >>> contains_a_digit('cat') False >>> contains_a_digit('') False >>> contains_a_digit(' ') False """ return True if search(r"[0-9]", string) else False
[docs]def deny_empty_or_whitespace(string='', variable_name=''): """ Prevent ``string`` or ``variable_name`` from being empty or only containing whitespace. :raises ValueError: Raises a ValueError if the string or the variable_name is empty or only contains whitespace. The ValueError contains the name of the calling function and the variable name used in the calling function. :type string: str :type variable_name: str :param string: The string to test. :param variable_name: The name of the variable used in the calling function. :return: None """ if not variable_name: # '' and None cases calling_function = currentframe().f_back.f_code.co_name raise ValueError(calling_function + ': variable_name input cannot be empty or None.') if not variable_name.strip(): # whitespace case calling_function = currentframe().f_back.f_code.co_name raise ValueError(calling_function + ': variable_name input cannot only contain whitespace.') if not string: # '' and None cases calling_function = currentframe().f_back.f_code.co_name raise ValueError(calling_function + ':', variable_name, 'cannot be empty or None.') if not string.strip(): # whitespace case calling_function = currentframe().f_back.f_code.co_name raise ValueError(calling_function + ':', variable_name, 'cannot only contain whitespace.')
[docs]def get_file_path(file_directory='', file_name='blowdry', extension=''): """ Joins the ``file_directory``, ``file_name``, and ``extension``. Returns the joined file path. **Rules:** - Do not allow ``''`` empty input for ``file_directory``, ``file_name``, or ``extension``. - Transform extension to lowercase. - Extensions must match this regex r"(^[.][.0-9a-z]*[0-9a-z]$)". **Findall regex Decoded:** - ``r"(^[.][.0-9a-z]*[0-9a-z]$)"`` - ``^[.]`` -- ``extension`` must begin with a ``.`` dot. - ``[.0-9a-z]*`` -- ``extension`` may contain any of the character inside the brackets. - ``[0-9a-z]$`` -- ``extension`` may only end with the characters inside the brackets. :type file_directory: str :type file_name: str :type extension: str :param file_directory: Directory in which to place the file. :param file_name: Name of the file (excluding extension) :param extension: A file extension including the ``.``, for example, ``.css``, ``.min.css``, ``.md``, ``.html``, and ``.rst`` :return: (*str*) -- Returns the joined file path. """ deny_empty_or_whitespace(string=file_directory, variable_name='file_directory') deny_empty_or_whitespace(string=file_name, variable_name='file_name') extension = extension.lower() regex = r"(^[.][.0-9a-z]*[0-9a-z]$)" if len(findall(regex, extension)) == 1: return path.join(file_directory, file_name + extension) else: raise ValueError( 'Extension: ' + extension + ' contains invalid characters. Only ".", "0-9", and "a-z" are allowed.' )
[docs]def validate_output_file_name_setting(): """ Validates output_file_name from blowdrycss_settings.py. First thing that runs. :raises SyntaxError: If settings.output_file_name or settings.output_extension contain '\', '/', whitespace or ends with a dot. :return: None """ output_file_name = settings.output_file_name if search(r"\s", output_file_name): # Prevent whitespace raise SyntaxError( 'The output_file_name "' + output_file_name + '" in blowdrycss_settings.py must not contain whitespace.' ) invalid_chars = ['\\', '/'] # Prevent '\' and '/' for invalid_char in invalid_chars: if invalid_char in output_file_name: raise SyntaxError( 'The output_file_name "' + output_file_name + '" in blowdrycss_settings.py must not contain / or \.' ) if output_file_name.endswith('.'): # Prevent final '.' raise SyntaxError( 'The output_file_name "' + output_file_name + '" in blowdrycss_settings.py must not end with a dot.' )
[docs]def validate_output_extension_setting(): """ Validates output_extension from blowdrycss_settings.py. First thing that runs. :raises SyntaxError: If settings.output_extension does not begin with a dot or contains '\', '/', whitespace or ends with a dot. :return: None """ output_extension = settings.output_extension if not output_extension.startswith('.'): raise SyntaxError( 'The output_extension "' + output_extension + '" in blowdrycss_settings.py must begin with a dot.' ) if search(r"\s", output_extension): # Prevent whitespace raise SyntaxError( 'The output_extension "' + output_extension + '" in blowdrycss_settings.py must not contain whitespace.' ) invalid_chars = ['\\', '/'] # Prevent '\' and '/' for invalid_char in invalid_chars: if invalid_char in output_extension: raise SyntaxError( 'The output_extension "' + output_extension + '" in blowdrycss_settings.py must not contain / or \.' ) if output_extension.endswith('.'): # Prevent final '.' raise SyntaxError( 'The output_extension "' + output_extension + '" in blowdrycss_settings.py must not end with a dot.' )
[docs]def change_settings_for_testing(): """ Change settings directories for testing. .. warning:: This method should only be used by the unit_test framework. :return: None """ cwd = getcwd() # The if/else logic is required for unit testing. if cwd.endswith('unit_tests'): # Allows running of pycharm unittest. settings.markdown_directory = path.join(cwd, 'test_markdown') settings.project_directory = path.join(cwd, 'test_examplesite') settings.css_directory = path.join(settings.project_directory, 'test_css') settings.docs_directory = path.join(cwd, 'test_docs') else: # Run unittest cmd from the root directory. settings.markdown_directory = path.join(cwd, 'blowdrycss', 'unit_tests', 'test_markdown') settings.project_directory = path.join(cwd, 'blowdrycss', 'unit_tests', 'test_examplesite') settings.css_directory = path.join(settings.project_directory, 'test_css') settings.docs_directory = path.join(cwd, 'blowdrycss', 'unit_tests', 'test_docs')
[docs]def unittest_file_path(folder='', filename=''): """ Determines the path of assigned to the folder and file based on the directory in which the unittest command is executed. :type folder: str :type filename: str :param folder: Name of the folder where the file is located. :param filename: Name of the file including extension e.g. test_aspx.aspx :return: (*str*) -- Return the path of the file to test. """ cwd = getcwd() if cwd.endswith('unit_tests'): # Allows running of pycharm unittest. the_path = path.join(cwd, folder, filename) else: # Run unittest cmd from the root directory. the_path = path.join(cwd, 'blowdrycss', 'unit_tests', folder, filename) return the_path
[docs]def make_directory(directory=''): """ Try to make a directory or verify its' existence. Raises an error if neither of these are possible. :raise OSError: Raises an OSError if the directory cannot be made or found. :type directory: str :param directory: A directory path in the file system. :return: None """ try: # Python 2.7 Compliant makedirs(directory) # Make 'log' directory logging.debug('%s created.', directory) except OSError: if not path.isdir(directory): # Verify directory existence raise OSError(directory + ' is not a directory, and could not be created.')
[docs]def delete_file_paths(file_paths): """ Delete all file_paths. Use Caution. Note:: Ignores files that do not exist. :type file_paths: iterable of strings :param file_paths: An iterable containing file path strings. :return: None """ for file_path in file_paths: try: remove(file_path) except: pass