signature:
def parse ( args ) :
    """Define the available arguments"""

implementation:
from tzlocal import get_localzone
try :
    timezone = get_localzone ( )
    if isinstance ( timezone , pytz . BaseTzInfo ) :
        timezone = timezone . zone
except Exception : # pragma : no cover
    timezone = 'UTC'
if timezone == 'local' :
    timezone = 'UTC'
parser = argparse . ArgumentParser ( description = """Bootstrap a django CMS project.
Major usage modes:

- wizard: djangocms -w -p /path/whatever project_name: ask for all the options through a
          CLI wizard.

- batch: djangocms project_name: runs with the default values plus any
         additional option provided (see below) with no question asked.

- config file: djangocms_installer --config-file /path/to/config.ini project_name: reads values
               from an ini-style config file.

Check https://djangocms-installer.readthedocs.io/en/latest/usage.html for detailed usage
information.
""" , formatter_class = argparse . RawTextHelpFormatter )
parser . add_argument ( '--config-file' , dest = 'config_file' , action = 'store' , default = None , help = 'Configuration file for djangocms_installer' )
parser . add_argument ( '--config-dump' , dest = 'config_dump' , action = 'store' , default = None , help = 'Dump configuration file with current args' )
parser . add_argument ( '--db' , '-d' , dest = 'db' , action = DbAction , default = 'sqlite://localhost/project.db' , help = 'Database configuration (in URL format). ' 'Example: sqlite://localhost/project.db' )
parser . add_argument ( '--i18n' , '-i' , dest = 'i18n' , action = 'store' , choices = ( 'yes' , 'no' ) , default = 'yes' , help = 'Activate Django I18N / L10N setting; this is ' 'automatically activated if more than ' 'language is provided' )
parser . add_argument ( '--use-tz' , '-z' , dest = 'use_timezone' , action = 'store' , choices = ( 'yes' , 'no' ) , default = 'yes' , help = 'Activate Django timezone support' )
parser . add_argument ( '--timezone' , '-t' , dest = 'timezone' , required = False , default = timezone , action = 'store' , help = 'Optional default time zone. Example: Europe/Rome' )
parser . add_argument ( '--reversion' , '-e' , dest = 'reversion' , action = 'store' , choices = ( 'yes' , 'no' ) , default = 'yes' , help = 'Install and configure reversion support ' '(only for django CMS 3.2 and 3.3)' )
parser . add_argument ( '--permissions' , dest = 'permissions' , action = 'store' , choices = ( 'yes' , 'no' ) , default = 'no' , help = 'Activate CMS permission management' )
parser . add_argument ( '--pip-options' , help = 'pass custom pip options' , default = '' )
parser . add_argument ( '--languages' , '-l' , dest = 'languages' , action = 'append' , help = 'Languages to enable. Option can be provided multiple times, or as a ' 'comma separated list. Only language codes supported by Django can ' 'be used here. Example: en, fr-FR, it-IT' )
parser . add_argument ( '--django-version' , dest = 'django_version' , action = 'store' , choices = data . DJANGO_SUPPORTED , default = data . DJANGO_DEFAULT , help = 'Django version' )
parser . add_argument ( '--cms-version' , '-v' , dest = 'cms_version' , action = 'store' , choices = data . DJANGOCMS_SUPPORTED , default = data . DJANGOCMS_DEFAULT , help = 'django CMS version' )
parser . add_argument ( '--parent-dir' , '-p' , dest = 'project_directory' , default = '' , action = 'store' , help = 'Optional project parent directory' )
parser . add_argument ( '--bootstrap' , dest = 'bootstrap' , action = 'store' , choices = ( 'yes' , 'no' ) , default = 'no' , help = 'Use Twitter Bootstrap Theme' )
parser . add_argument ( '--templates' , dest = 'templates' , action = 'store' , default = 'no' , help = 'Use custom template set' )
parser . add_argument ( '--starting-page' , dest = 'starting_page' , action = 'store' , choices = ( 'yes' , 'no' ) , default = 'no' , help = 'Load a starting page with examples after installation ' '(english language only). Choose "no" if you use a ' 'custom template set.' )
parser . add_argument ( dest = 'project_name' , action = 'store' , help = 'Name of the project to be created' )
# Command that lists the supported plugins in verbose description
parser . add_argument ( '--list-plugins' , '-P' , dest = 'plugins' , action = 'store_true' , help = 'List plugins that\'s going to be installed and configured' )
# Command that lists the supported plugins in verbose description
parser . add_argument ( '--dump-requirements' , '-R' , dest = 'dump_reqs' , action = 'store_true' , help = 'It dumps the requirements that would be installed according to ' 'parameters given. Together with --requirements argument is useful ' 'for customizing the virtualenv' )
# Advanced options . These have a predefined default and are not asked
# by config wizard .
parser . add_argument ( '--no-input' , '-q' , dest = 'noinput' , action = 'store_true' , default = True , help = 'Don\'t run the configuration wizard, just use the ' 'provided values' )
parser . add_argument ( '--wizard' , '-w' , dest = 'wizard' , action = 'store_true' , default = False , help = 'Run the configuration wizard' )
parser . add_argument ( '--verbose' , dest = 'verbose' , action = 'store_true' , default = False , help = 'Be more verbose and don\'t swallow subcommands output' )
parser . add_argument ( '--filer' , '-f' , dest = 'filer' , action = 'store_true' , default = True , help = 'Install and configure django-filer plugins ' '- Always enabled' )
parser . add_argument ( '--requirements' , '-r' , dest = 'requirements_file' , action = 'store' , default = None , help = 'Externally defined requirements file' )
parser . add_argument ( '--no-deps' , '-n' , dest = 'no_deps' , action = 'store_true' , default = False , help = 'Don\'t install package dependencies' )
parser . add_argument ( '--no-plugins' , dest = 'no_plugins' , action = 'store_true' , default = False , help = 'Don\'t install plugins' )
parser . add_argument ( '--no-db-driver' , dest = 'no_db_driver' , action = 'store_true' , default = False , help = 'Don\'t install database package' )
parser . add_argument ( '--no-sync' , '-m' , dest = 'no_sync' , action = 'store_true' , default = False , help = 'Don\'t run syncdb / migrate after bootstrapping' )
parser . add_argument ( '--no-user' , '-u' , dest = 'no_user' , action = 'store_true' , default = False , help = 'Don\'t create the admin user' )
parser . add_argument ( '--template' , dest = 'template' , action = 'store' , default = None , help = 'The path or URL to load the django project ' 'template from.' )
parser . add_argument ( '--extra-settings' , dest = 'extra_settings' , action = 'store' , default = None , help = 'The path to an file that contains extra settings.' )
parser . add_argument ( '--skip-empty-check' , '-s' , dest = 'skip_project_dir_check' , action = 'store_true' , default = False , help = 'Skip the check if project dir is empty.' )
parser . add_argument ( '--delete-project-dir' , '-c' , dest = 'delete_project_dir' , action = 'store_true' , default = False , help = 'Delete project directory on creation failure.' )
parser . add_argument ( '--utc' , dest = 'utc' , action = 'store_true' , default = False , help = 'Use UTC timezone.' )
if '--utc' in args :
    for action in parser . _positionals . _actions :
        if action . dest == 'timezone' :
            action . default = 'UTC'
# If config _ args then pretend that config args came from the stdin and run parser again .
config_args = ini . parse_config_file ( parser , args )
args = parser . parse_args ( config_args + args )
if not args . wizard :
    args . noinput = True
else :
    args . noinput = False
if not args . project_directory :
    args . project_directory = args . project_name
args . project_directory = os . path . abspath ( args . project_directory )
# First of all , check if the project name is valid
if not validate_project ( args . project_name ) :
    sys . stderr . write ( 'Project name "{0}" is not a valid app name, or it\'s already defined. ' 'Please use only numbers, letters and underscores.\n' . format ( args . project_name ) )
    sys . exit ( 3 )
# Checking the given path
setattr ( args , 'project_path' , os . path . join ( args . project_directory , args . project_name ) . strip ( ) )
if not args . skip_project_dir_check :
    if ( os . path . exists ( args . project_directory ) and [ path for path in os . listdir ( args . project_directory ) if not path . startswith ( '.' ) ] ) :
        sys . stderr . write ( 'Path "{0}" already exists and is not empty, please choose a different one\n' 'If you want to use this path anyway use the -s flag to skip this check.\n' '' . format ( args . project_directory ) )
        sys . exit ( 4 )
if os . path . exists ( args . project_path ) :
    sys . stderr . write ( 'Path "{0}" already exists, please choose a different one\n' . format ( args . project_path ) )
    sys . exit ( 4 )
if args . config_dump and os . path . isfile ( args . config_dump ) :
    sys . stdout . write ( 'Cannot dump because given configuration file "{0}" exists.\n' . format ( args . config_dump ) )
    sys . exit ( 8 )
args = _manage_args ( parser , args )
# what do we want here ? !
# * if languages are given as multiple arguments , let ' s use it as is
# * if no languages are given , use a default and stop handling it further
# * if languages are given as a comma - separated list , split it and use the
# resulting list .
if not args . languages :
    try :
        args . languages = [ locale . getdefaultlocale ( ) [ 0 ] . split ( '_' ) [ 0 ] ]
    except Exception : # pragma : no cover
        args . languages = [ 'en' ]
elif isinstance ( args . languages , six . string_types ) :
    args . languages = args . languages . split ( ',' )
elif len ( args . languages ) == 1 and isinstance ( args . languages [ 0 ] , six . string_types ) :
    args . languages = args . languages [ 0 ] . split ( ',' )
args . languages = [ lang . strip ( ) . lower ( ) for lang in args . languages ]
if len ( args . languages ) > 1 :
    args . i18n = 'yes'
args . aldryn = False
args . filer = True
# Convert version to numeric format for easier checking
try :
    django_version , cms_version = supported_versions ( args . django_version , args . cms_version )
    cms_package = data . PACKAGE_MATRIX . get ( cms_version , data . PACKAGE_MATRIX [ data . DJANGOCMS_LTS ] )
except RuntimeError as e : # pragma : no cover
    sys . stderr . write ( compat . unicode ( e ) )
    sys . exit ( 6 )
if django_version is None : # pragma : no cover
    sys . stderr . write ( 'Please provide a Django supported version: {0}. Only Major.Minor ' 'version selector is accepted\n' . format ( ', ' . join ( data . DJANGO_SUPPORTED ) ) )
    sys . exit ( 6 )
if cms_version is None : # pragma : no cover
    sys . stderr . write ( 'Please provide a django CMS supported version: {0}. Only Major.Minor ' 'version selector is accepted\n' . format ( ', ' . join ( data . DJANGOCMS_SUPPORTED ) ) )
    sys . exit ( 6 )
default_settings = '{}.settings' . format ( args . project_name )
env_settings = os . environ . get ( 'DJANGO_SETTINGS_MODULE' , default_settings )
if env_settings != default_settings :
    sys . stderr . write ( '`DJANGO_SETTINGS_MODULE` is currently set to \'{0}\' which is not compatible with ' 'djangocms installer.\nPlease unset `DJANGO_SETTINGS_MODULE` and re-run the installer ' '\n' . format ( env_settings ) )
    sys . exit ( 10 )
if not getattr ( args , 'requirements_file' ) :
    requirements = [ ]
    # django CMS version check
    if args . cms_version == 'develop' :
        requirements . append ( cms_package )
        warnings . warn ( data . VERSION_WARNING . format ( 'develop' , 'django CMS' ) )
    elif args . cms_version == 'rc' : # pragma : no cover
        requirements . append ( cms_package )
    elif args . cms_version == 'beta' : # pragma : no cover
        requirements . append ( cms_package )
        warnings . warn ( data . VERSION_WARNING . format ( 'beta' , 'django CMS' ) )
    else :
        requirements . append ( cms_package )
    if args . cms_version in ( 'rc' , 'develop' ) :
        requirements . extend ( data . REQUIREMENTS [ 'cms-master' ] )
    elif LooseVersion ( cms_version ) >= LooseVersion ( '3.6' ) :
        requirements . extend ( data . REQUIREMENTS [ 'cms-3.6' ] )
    elif LooseVersion ( cms_version ) >= LooseVersion ( '3.5' ) :
        requirements . extend ( data . REQUIREMENTS [ 'cms-3.5' ] )
    elif LooseVersion ( cms_version ) >= LooseVersion ( '3.4' ) :
        requirements . extend ( data . REQUIREMENTS [ 'cms-3.4' ] )
    if not args . no_db_driver :
        requirements . append ( args . db_driver )
    if not args . no_plugins :
        if args . cms_version in ( 'rc' , 'develop' ) :
            requirements . extend ( data . REQUIREMENTS [ 'plugins-master' ] )
        elif LooseVersion ( cms_version ) >= LooseVersion ( '3.6' ) :
            requirements . extend ( data . REQUIREMENTS [ 'plugins-3.6' ] )
        elif LooseVersion ( cms_version ) >= LooseVersion ( '3.5' ) :
            requirements . extend ( data . REQUIREMENTS [ 'plugins-3.5' ] )
        elif LooseVersion ( cms_version ) >= LooseVersion ( '3.4' ) :
            requirements . extend ( data . REQUIREMENTS [ 'plugins-3.4' ] )
        requirements . extend ( data . REQUIREMENTS [ 'filer' ] )
    if args . aldryn : # pragma : no cover
        requirements . extend ( data . REQUIREMENTS [ 'aldryn' ] )
    # Django version check
    if args . django_version == 'develop' : # pragma : no cover
        requirements . append ( data . DJANGO_DEVELOP )
        warnings . warn ( data . VERSION_WARNING . format ( 'develop' , 'Django' ) )
    elif args . django_version == 'beta' : # pragma : no cover
        requirements . append ( data . DJANGO_BETA )
        warnings . warn ( data . VERSION_WARNING . format ( 'beta' , 'Django' ) )
    else :
        requirements . append ( 'Django<{0}' . format ( less_than_version ( django_version ) ) )
    if django_version == '1.8' :
        requirements . extend ( data . REQUIREMENTS [ 'django-1.8' ] )
    elif django_version == '1.9' :
        requirements . extend ( data . REQUIREMENTS [ 'django-1.9' ] )
    elif django_version == '1.10' :
        requirements . extend ( data . REQUIREMENTS [ 'django-1.10' ] )
    elif django_version == '1.11' :
        requirements . extend ( data . REQUIREMENTS [ 'django-1.11' ] )
    elif django_version == '2.0' :
        requirements . extend ( data . REQUIREMENTS [ 'django-2.0' ] )
    elif django_version == '2.1' :
        requirements . extend ( data . REQUIREMENTS [ 'django-2.1' ] )
    requirements . extend ( data . REQUIREMENTS [ 'default' ] )
    setattr ( args , 'requirements' , '\n' . join ( requirements ) . strip ( ) )
# Convenient shortcuts
setattr ( args , 'cms_version' , cms_version )
setattr ( args , 'django_version' , django_version )
setattr ( args , 'settings_path' , os . path . join ( args . project_directory , args . project_name , 'settings.py' ) . strip ( ) )
setattr ( args , 'urlconf_path' , os . path . join ( args . project_directory , args . project_name , 'urls.py' ) . strip ( ) )
if args . config_dump :
    ini . dump_config_file ( args . config_dump , args , parser )
return args


signature:
def _manage_args ( parser , args ) :
    """Checks and validate provided input"""

implementation:
for item in data . CONFIGURABLE_OPTIONS :
    action = parser . _option_string_actions [ item ]
    choices = default = ''
    input_value = getattr ( args , action . dest )
    new_val = None
    # cannot count this until we find a way to test input
    if not args . noinput : # pragma : no cover
        if action . choices :
            choices = ' (choices: {0})' . format ( ', ' . join ( action . choices ) )
        if input_value :
            if type ( input_value ) == list :
                default = ' [default {0}]' . format ( ', ' . join ( input_value ) )
            else :
                default = ' [default {0}]' . format ( input_value )
        while not new_val :
            prompt = '{0}{1}{2}: ' . format ( action . help , choices , default )
            if action . choices in ( 'yes' , 'no' ) :
                new_val = utils . query_yes_no ( prompt )
            else :
                new_val = compat . input ( prompt )
            new_val = compat . clean ( new_val )
            if not new_val and input_value :
                new_val = input_value
            if new_val and action . dest == 'templates' :
                if new_val != 'no' and not os . path . isdir ( new_val ) :
                    sys . stdout . write ( 'Given directory does not exists, retry\n' )
                    new_val = False
            if new_val and action . dest == 'db' :
                action ( parser , args , new_val , action . option_strings )
                new_val = getattr ( args , action . dest )
    else :
        if not input_value and action . required :
            raise ValueError ( 'Option {0} is required when in no-input mode' . format ( action . dest ) )
        new_val = input_value
        if action . dest == 'db' :
            action ( parser , args , new_val , action . option_strings )
            new_val = getattr ( args , action . dest )
    if action . dest == 'templates' and ( new_val == 'no' or not os . path . isdir ( new_val ) ) :
        new_val = False
    if action . dest in ( 'bootstrap' , 'starting_page' ) :
        new_val = ( new_val == 'yes' )
    setattr ( args , action . dest , new_val )
return args


signature:
def query_yes_no ( question , default = None ) : # pragma : no cover
    """Ask a yes / no question via ` raw _ input ( ) ` and return their answer .
 : param question : A string that is presented to the user .
 : param default : The presumed answer if the user just hits < Enter > .
 It must be " yes " ( the default ) , " no " or None ( meaning
 an answer is required of the user ) .
 The " answer " return value is one of " yes " or " no " .
 Code borrowed from cookiecutter
 https : / / github . com / audreyr / cookiecutter / blob / master / cookiecutter / prompt . py"""

implementation:
valid = { 'yes' : True , 'y' : True , 'ye' : True , 'no' : False , 'n' : False }
if default is None :
    prompt = ' [y/n] '
elif default == 'yes' :
    prompt = ' [Y/n] '
elif default == 'no' :
    prompt = ' [y/N] '
else :
    raise ValueError ( 'invalid default answer: "{0}"' . format ( default ) )
while True :
    sys . stdout . write ( question + prompt )
    choice = compat . input ( ) . lower ( )
    if default is not None and choice == '' :
        return valid [ default ]
    elif choice in valid :
        return valid [ choice ]
    else :
        sys . stdout . write ( 'Please answer with "yes" or "no" (or "y" or "n").\n' )


signature:
def supported_versions ( django , cms ) :
    """Convert numeric and literal version information to numeric format"""

implementation:
cms_version = None
django_version = None
try :
    cms_version = Decimal ( cms )
except ( ValueError , InvalidOperation ) :
    try :
        cms_version = CMS_VERSION_MATRIX [ str ( cms ) ]
    except KeyError :
        pass
try :
    django_version = Decimal ( django )
except ( ValueError , InvalidOperation ) :
    try :
        django_version = DJANGO_VERSION_MATRIX [ str ( django ) ]
    except KeyError : # pragma : no cover
        pass
try :
    if ( cms_version and django_version and not ( LooseVersion ( VERSION_MATRIX [ compat . unicode ( cms_version ) ] [ 0 ] ) <= LooseVersion ( compat . unicode ( django_version ) ) <= LooseVersion ( VERSION_MATRIX [ compat . unicode ( cms_version ) ] [ 1 ] ) ) ) :
        raise RuntimeError ( 'Django and django CMS versions doesn\'t match: ' 'Django {0} is not supported by django CMS {1}' . format ( django_version , cms_version ) )
except KeyError :
    raise RuntimeError ( 'Django and django CMS versions doesn\'t match: ' 'Django {0} is not supported by django CMS {1}' . format ( django_version , cms_version ) )
return ( compat . unicode ( django_version ) if django_version else django_version , compat . unicode ( cms_version ) if cms_version else cms_version )


signature:
def less_than_version ( value ) :
    """Converts the current version to the next one for inserting into requirements
 in the ' < version ' format"""

implementation:
items = list ( map ( int , str ( value ) . split ( '.' ) ) )
if len ( items ) == 1 :
    items . append ( 0 )
items [ 1 ] += 1
if value == '1.11' :
    return '2.0'
else :
    return '.' . join ( map ( str , items ) )


signature:
def format_val ( val ) :
    """Returns val as integer or as escaped string according to its value
 : param val : any value
 : return : formatted string"""

implementation:
val = text_type ( val )
if val . isdigit ( ) :
    return int ( val )
else :
    return '\'{0}\'' . format ( val )


signature:
def parse_config_file ( parser , stdin_args ) :
    """Parse config file .
 Returns a list of additional args ."""

implementation:
config_args = [ ]
# Temporary switch required args and save them to restore .
required_args = [ ]
for action in parser . _actions :
    if action . required :
        required_args . append ( action )
        action . required = False
parsed_args = parser . parse_args ( stdin_args )
# Restore required args .
for action in required_args :
    action . required = True
if not parsed_args . config_file :
    return config_args
config = ConfigParser ( )
if not config . read ( parsed_args . config_file ) :
    sys . stderr . write ( 'Config file "{0}" doesn\'t exists\n' . format ( parsed_args . config_file ) )
    sys . exit ( 7 )
# It isn ' t used anywhere .
config_args = _convert_config_to_stdin ( config , parser )
return config_args


signature:
def dump_config_file ( filename , args , parser = None ) :
    """Dump args to config file ."""

implementation:
config = ConfigParser ( )
config . add_section ( SECTION )
if parser is None :
    for attr in args :
        config . set ( SECTION , attr , args . attr )
else :
    keys_empty_values_not_pass = ( '--extra-settings' , '--languages' , '--requirements' , '--template' , '--timezone' )
    # positionals . _ option _ string _ actions
    for action in parser . _actions :
        if action . dest in ( 'help' , 'config_file' , 'config_dump' , 'project_name' ) :
            continue
        keyp = action . option_strings [ 0 ]
        option_name = keyp . lstrip ( '-' )
        option_value = getattr ( args , action . dest )
        if any ( [ i for i in keys_empty_values_not_pass if i in action . option_strings ] ) :
            if action . dest == 'languages' :
                if len ( option_value ) == 1 and option_value [ 0 ] == 'en' :
                    config . set ( SECTION , option_name , '' )
                else :
                    config . set ( SECTION , option_name , ',' . join ( option_value ) )
            else :
                config . set ( SECTION , option_name , option_value if option_value else '' )
        elif action . choices == ( 'yes' , 'no' ) :
            config . set ( SECTION , option_name , 'yes' if option_value else 'no' )
        elif action . dest == 'templates' :
            config . set ( SECTION , option_name , option_value if option_value else 'no' )
        elif action . dest == 'cms_version' :
            version = ( 'stable' if option_value == CMS_VERSION_MATRIX [ 'stable' ] else option_value )
            config . set ( SECTION , option_name , version )
        elif action . dest == 'django_version' :
            version = ( 'stable' if option_value == DJANGO_VERSION_MATRIX [ 'stable' ] else option_value )
            config . set ( SECTION , option_name , version )
        elif action . const :
            config . set ( SECTION , option_name , 'true' if option_value else 'false' )
        else :
            config . set ( SECTION , option_name , str ( option_value ) )
with open ( filename , 'w' ) as fp :
    config . write ( fp )


signature:
def _convert_config_to_stdin ( config , parser ) :
    """Convert config options to stdin args .
 Especially boolean values , for more information
 @ see https : / / docs . python . org / 3.4 / library / configparser . html # supported - datatypes"""

implementation:
keys_empty_values_not_pass = ( '--extra-settings' , '--languages' , '--requirements' , '--template' , '--timezone' )
args = [ ]
for key , val in config . items ( SECTION ) :
    keyp = '--{0}' . format ( key )
    action = parser . _option_string_actions [ keyp ]
    if action . const :
        try :
            if config . getboolean ( SECTION , key ) :
                args . append ( keyp )
        except ValueError :
            args . extend ( [ keyp , val ] )
            # Pass it as is to get the error from ArgumentParser .
    elif any ( [ i for i in keys_empty_values_not_pass if i in action . option_strings ] ) : # Some keys with empty values shouldn ' t be passed into args to use their defaults
    # from ArgumentParser .
        if val != '' :
            args . extend ( [ keyp , val ] )
    else :
        args . extend ( [ keyp , val ] )
return args


signature:
def create_project ( config_data ) :
    """Call django - admin to create the project structure
 : param config _ data : configuration data"""

implementation:
env = deepcopy ( dict ( os . environ ) )
env [ str ( 'DJANGO_SETTINGS_MODULE' ) ] = str ( '{0}.settings' . format ( config_data . project_name ) )
env [ str ( 'PYTHONPATH' ) ] = str ( os . pathsep . join ( map ( shlex_quote , sys . path ) ) )
kwargs = { }
args = [ ]
if config_data . template :
    kwargs [ 'template' ] = config_data . template
args . append ( config_data . project_name )
if config_data . project_directory :
    args . append ( config_data . project_directory )
    if not os . path . exists ( config_data . project_directory ) :
        os . makedirs ( config_data . project_directory )
base_cmd = 'django-admin.py'
start_cmds = [ os . path . join ( os . path . dirname ( sys . executable ) , base_cmd ) ]
start_cmd_pnodes = [ 'Scripts' ]
start_cmds . extend ( [ os . path . join ( os . path . dirname ( sys . executable ) , pnode , base_cmd ) for pnode in start_cmd_pnodes ] )
start_cmd = [ base_cmd ]
for p in start_cmds :
    if os . path . exists ( p ) :
        start_cmd = [ sys . executable , p ]
        break
cmd_args = start_cmd + [ 'startproject' ] + args
if config_data . verbose :
    sys . stdout . write ( 'Project creation command: {0}\n' . format ( ' ' . join ( cmd_args ) ) )
try :
    output = subprocess . check_output ( cmd_args , stderr = subprocess . STDOUT )
    sys . stdout . write ( output . decode ( 'utf-8' ) )
except subprocess . CalledProcessError as e : # pragma : no cover
    if config_data . verbose :
        sys . stdout . write ( e . output . decode ( 'utf-8' ) )
    raise


signature:
def _detect_migration_layout ( vars , apps ) :
    """Detect migrations layout for plugins
 : param vars : installer settings
 : param apps : installed applications"""

implementation:
DJANGO_MODULES = { }
for module in vars . MIGRATIONS_CHECK_MODULES :
    if module in apps :
        try :
            mod = __import__ ( '{0}.migrations_django' . format ( module ) )
            # NOQA
            DJANGO_MODULES [ module ] = '{0}.migrations_django' . format ( module )
        except Exception :
            pass
return DJANGO_MODULES


signature:
def _install_aldryn ( config_data ) : # pragma : no cover
    """Install aldryn boilerplate
 : param config _ data : configuration data"""

implementation:
import requests
media_project = os . path . join ( config_data . project_directory , 'dist' , 'media' )
static_main = False
static_project = os . path . join ( config_data . project_directory , 'dist' , 'static' )
template_target = os . path . join ( config_data . project_directory , 'templates' )
tmpdir = tempfile . mkdtemp ( )
aldrynzip = requests . get ( data . ALDRYN_BOILERPLATE )
zip_open = zipfile . ZipFile ( BytesIO ( aldrynzip . content ) )
zip_open . extractall ( path = tmpdir )
for component in os . listdir ( os . path . join ( tmpdir , 'aldryn-boilerplate-standard-master' ) ) :
    src = os . path . join ( tmpdir , 'aldryn-boilerplate-standard-master' , component )
    dst = os . path . join ( config_data . project_directory , component )
    if os . path . isfile ( src ) :
        shutil . copy ( src , dst )
    else :
        shutil . copytree ( src , dst )
shutil . rmtree ( tmpdir )
return media_project , static_main , static_project , template_target


signature:
def copy_files ( config_data ) :
    """It ' s a little rude actually : it just overwrites the django - generated urls . py
 with a custom version and put other files in the project directory .
 : param config _ data : configuration data"""

implementation:
if config_data . i18n == 'yes' :
    urlconf_path = os . path . join ( os . path . dirname ( __file__ ) , '../config/urls_i18n.py' )
else :
    urlconf_path = os . path . join ( os . path . dirname ( __file__ ) , '../config/urls_noi18n.py' )
share_path = os . path . join ( os . path . dirname ( __file__ ) , '../share' )
template_path = os . path . join ( share_path , 'templates' )
if config_data . aldryn : # pragma : no cover
    media_project , static_main , static_project , template_target = _install_aldryn ( config_data )
else :
    media_project = os . path . join ( config_data . project_directory , 'media' )
    static_main = os . path . join ( config_data . project_path , 'static' )
    static_project = os . path . join ( config_data . project_directory , 'static' )
    template_target = os . path . join ( config_data . project_path , 'templates' )
    if config_data . templates and os . path . isdir ( config_data . templates ) :
        template_path = config_data . templates
    elif config_data . bootstrap :
        template_path = os . path . join ( template_path , 'bootstrap' )
    else :
        template_path = os . path . join ( template_path , 'basic' )
shutil . copy ( urlconf_path , config_data . urlconf_path )
if media_project :
    os . makedirs ( media_project )
if static_main :
    os . makedirs ( static_main )
if not os . path . exists ( static_project ) :
    os . makedirs ( static_project )
if not os . path . exists ( template_target ) :
    os . makedirs ( template_target )
for filename in glob . glob ( os . path . join ( template_path , '*.html' ) ) :
    if os . path . isfile ( filename ) :
        shutil . copy ( filename , template_target )
if config_data . noinput and not config_data . no_user :
    script_path = os . path . join ( share_path , 'create_user.py' )
    if os . path . isfile ( script_path ) :
        shutil . copy ( script_path , os . path . join ( config_data . project_path , '..' ) )
if config_data . starting_page :
    for filename in glob . glob ( os . path . join ( share_path , 'starting_page.*' ) ) :
        if os . path . isfile ( filename ) :
            shutil . copy ( filename , os . path . join ( config_data . project_path , '..' ) )


signature:
def patch_settings ( config_data ) :
    """Modify the settings file created by Django injecting the django CMS
 configuration
 : param config _ data : configuration data"""

implementation:
import django
current_django_version = LooseVersion ( django . __version__ )
declared_django_version = LooseVersion ( config_data . django_version )
if not os . path . exists ( config_data . settings_path ) :
    sys . stderr . write ( 'Error while creating target project, ' 'please check the given configuration: {0}\n' . format ( config_data . settings_path ) )
    return sys . exit ( 5 )
if current_django_version . version [ : 2 ] != declared_django_version . version [ : 2 ] :
    sys . stderr . write ( 'Currently installed Django version {} differs from the declared {}. ' 'Please check the given `--django-version` installer argument, your virtualenv ' 'configuration and any package forcing a different Django version' '\n' . format ( current_django_version , declared_django_version ) )
    return sys . exit ( 9 )
overridden_settings = ( 'MIDDLEWARE_CLASSES' , 'MIDDLEWARE' , 'INSTALLED_APPS' , 'TEMPLATE_LOADERS' , 'TEMPLATE_CONTEXT_PROCESSORS' , 'TEMPLATE_DIRS' , 'LANGUAGES' )
extra_settings = ''
with open ( config_data . settings_path , 'r' ) as fd_original :
    original = fd_original . read ( )
# extra settings reading
if config_data . extra_settings and os . path . exists ( config_data . extra_settings ) :
    with open ( config_data . extra_settings , 'r' ) as fd_extra :
        extra_settings = fd_extra . read ( )
original = original . replace ( '# -*- coding: utf-8 -*-\n' , '' )
if config_data . aldryn : # pragma : no cover
    DATA_DIR = ( 'DATA_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), \'dist\')\n' )
    STATICFILES_DIR = 'os.path.join(BASE_DIR, \'static\'),'
else :
    DATA_DIR = 'DATA_DIR = os.path.dirname(os.path.dirname(__file__))\n'
    STATICFILES_DIR = 'os.path.join(BASE_DIR, \'{0}\', \'static\'),' . format ( config_data . project_name )
original = data . DEFAULT_PROJECT_HEADER + DATA_DIR + original
original += 'MEDIA_URL = \'/media/\'\n'
original += 'MEDIA_ROOT = os.path.join(DATA_DIR, \'media\')\n'
original += 'STATIC_ROOT = os.path.join(DATA_DIR, \'static\')\n'
original += """
STATICFILES_DIRS = (
    {0}
)
""" . format ( STATICFILES_DIR )
original = original . replace ( '# -*- coding: utf-8 -*-\n' , '' )
# I18N
if config_data . i18n == 'no' :
    original = original . replace ( 'I18N = True' , 'I18N = False' )
    original = original . replace ( 'L10N = True' , 'L10N = False' )
# TZ
if config_data . use_timezone == 'no' :
    original = original . replace ( 'USE_TZ = True' , 'USE_TZ = False' )
if config_data . languages :
    original = original . replace ( 'LANGUAGE_CODE = \'en-us\'' , 'LANGUAGE_CODE = \'{0}\'' . format ( config_data . languages [ 0 ] ) )
if config_data . timezone :
    original = original . replace ( 'TIME_ZONE = \'UTC\'' , 'TIME_ZONE = \'{0}\'' . format ( config_data . timezone ) )
for item in overridden_settings :
    if declared_django_version >= LooseVersion ( '1.9' ) :
        item_re = re . compile ( r'{0} = [^\]]+\]' . format ( item ) , re . DOTALL | re . MULTILINE )
    else :
        item_re = re . compile ( r'{0} = [^\)]+\)' . format ( item ) , re . DOTALL | re . MULTILINE )
    original = item_re . sub ( '' , original )
# TEMPLATES is special , so custom regexp needed
if declared_django_version >= LooseVersion ( '2.0' ) :
    item_re = re . compile ( r'TEMPLATES = .+\},\n\s+\},\n]$' , re . DOTALL | re . MULTILINE )
else :
    item_re = re . compile ( r'TEMPLATES = .+\]$' , re . DOTALL | re . MULTILINE )
original = item_re . sub ( '' , original )
# DATABASES is a dictionary , so different regexp needed
item_re = re . compile ( r'DATABASES = [^\}]+\}[^\}]+\}' , re . DOTALL | re . MULTILINE )
original = item_re . sub ( '' , original )
if original . find ( 'SITE_ID' ) == - 1 :
    original += 'SITE_ID = 1\n\n'
original += _build_settings ( config_data )
# Append extra settings at the end of the file
original += ( '\n' + extra_settings )
with open ( config_data . settings_path , 'w' ) as fd_dest :
    fd_dest . write ( original )


signature:
def _build_settings ( config_data ) :
    """Build the django CMS settings dictionary
 : param config _ data : configuration data"""

implementation:
spacer = '    '
text = [ ]
vars = get_settings ( )
vars . MIDDLEWARE_CLASSES . insert ( 0 , vars . APPHOOK_RELOAD_MIDDLEWARE_CLASS )
processors = vars . TEMPLATE_CONTEXT_PROCESSORS + vars . TEMPLATE_CONTEXT_PROCESSORS_3
text . append ( data . TEMPLATES_1_8 . format ( loaders = ( ',\n' + spacer * 4 ) . join ( [ "'{0}'" . format ( var ) for var in vars . TEMPLATE_LOADERS if ( LooseVersion ( config_data . django_version ) < LooseVersion ( '2.0' ) or 'eggs' not in var ) ] ) , processors = ( ',\n' + spacer * 4 ) . join ( [ "'{0}'" . format ( var ) for var in processors ] ) , dirs = "os.path.join(BASE_DIR, '{0}', 'templates')," . format ( config_data . project_name ) ) )
if LooseVersion ( config_data . django_version ) >= LooseVersion ( '1.10' ) :
    text . append ( 'MIDDLEWARE = [\n{0}{1}\n]' . format ( spacer , ( ',\n' + spacer ) . join ( [ '\'{0}\'' . format ( var ) for var in vars . MIDDLEWARE_CLASSES ] ) ) )
else :
    text . append ( 'MIDDLEWARE_CLASSES = [\n{0}{1}\n]' . format ( spacer , ( ',\n' + spacer ) . join ( [ "'{0}'" . format ( var ) for var in vars . MIDDLEWARE_CLASSES ] ) ) )
apps = list ( vars . INSTALLED_APPS )
apps = list ( vars . CMS_3_HEAD ) + apps
apps . extend ( vars . TREEBEARD_APPS )
apps . extend ( vars . CMS_3_APPLICATIONS )
if not config_data . no_plugins :
    apps . extend ( vars . FILER_PLUGINS_3 )
if config_data . aldryn : # pragma : no cover
    apps . extend ( vars . ALDRYN_APPLICATIONS )
if config_data . reversion and LooseVersion ( config_data . cms_version ) < LooseVersion ( '3.4' ) :
    apps . extend ( vars . REVERSION_APPLICATIONS )
text . append ( 'INSTALLED_APPS = [\n{0}{1}\n]' . format ( spacer , ( ',\n' + spacer ) . join ( [ '\'{0}\'' . format ( var ) for var in apps ] + [ '\'{0}\'' . format ( config_data . project_name ) ] ) ) )
text . append ( 'LANGUAGES = (\n{0}{1}\n{0}{2}\n)' . format ( spacer , '## Customize this' , ( '\n' + spacer ) . join ( [ '(\'{0}\', gettext(\'{0}\')),' . format ( item ) for item in config_data . languages ] ) # NOQA
) )
cms_langs = deepcopy ( vars . CMS_LANGUAGES )
for lang in config_data . languages :
    lang_dict = { 'code' : lang , 'name' : lang }
    lang_dict . update ( copy ( cms_langs [ 'default' ] ) )
    cms_langs [ 1 ] . append ( lang_dict )
cms_text = [ 'CMS_LANGUAGES = {' ]
cms_text . append ( '{0}{1}' . format ( spacer , '## Customize this' ) )
for key , value in iteritems ( cms_langs ) :
    if key == 'default' :
        cms_text . append ( '{0}\'{1}\': {{' . format ( spacer , key ) )
        for config_name , config_value in iteritems ( value ) :
            cms_text . append ( '{0}\'{1}\': {2},' . format ( spacer * 2 , config_name , config_value ) )
        cms_text . append ( '{0}}},' . format ( spacer ) )
    else :
        cms_text . append ( '{0}{1}: [' . format ( spacer , key ) )
        for lang in value :
            cms_text . append ( '{0}{{' . format ( spacer * 2 ) )
            for config_name , config_value in iteritems ( lang ) :
                if config_name == 'code' :
                    cms_text . append ( '{0}\'{1}\': \'{2}\',' . format ( spacer * 3 , config_name , config_value ) )
                    # NOQA
                elif config_name == 'name' :
                    cms_text . append ( '{0}\'{1}\': gettext(\'{2}\'),' . format ( spacer * 3 , config_name , config_value ) )
                    # NOQA
                else :
                    cms_text . append ( '{0}\'{1}\': {2},' . format ( spacer * 3 , config_name , config_value ) )
            cms_text . append ( '{0}}},' . format ( spacer * 2 ) )
        cms_text . append ( '{0}],' . format ( spacer ) )
cms_text . append ( '}' )
text . append ( '\n' . join ( cms_text ) )
if config_data . bootstrap :
    cms_templates = 'CMS_TEMPLATES_BOOTSTRAP'
else :
    cms_templates = 'CMS_TEMPLATES'
text . append ( 'CMS_TEMPLATES = (\n{0}{1}\n{0}{2}\n)' . format ( spacer , '## Customize this' , ( ',\n' + spacer ) . join ( [ '(\'{0}\', \'{1}\')' . format ( * item ) for item in getattr ( vars , cms_templates ) ] ) ) )
text . append ( 'CMS_PERMISSION = {0}' . format ( vars . CMS_PERMISSION ) )
text . append ( 'CMS_PLACEHOLDER_CONF = {0}' . format ( vars . CMS_PLACEHOLDER_CONF ) )
database = [ '\'{0}\': {1}' . format ( key , format_val ( val ) ) for key , val in sorted ( config_data . db_parsed . items ( ) , key = lambda x : x [ 0 ] ) ]
# NOQA
text . append ( textwrap . dedent ( """
        DATABASES = {{
            'default': {{
                {0}
            }}
        }}""" ) . strip ( ) . format ( ( ',\n' + spacer * 2 ) . join ( database ) ) )
# NOQA
DJANGO_MIGRATION_MODULES = _detect_migration_layout ( vars , apps )
text . append ( 'MIGRATION_MODULES = {{\n{0}{1}\n}}' . format ( spacer , ( ',\n' + spacer ) . join ( [ '\'{0}\': \'{1}\'' . format ( * item ) for item in DJANGO_MIGRATION_MODULES . items ( ) ] ) ) )
if config_data . filer :
    text . append ( 'THUMBNAIL_PROCESSORS = (\n{0}{1}\n)' . format ( spacer , ( ',\n' + spacer ) . join ( [ '\'{0}\'' . format ( var ) for var in vars . THUMBNAIL_PROCESSORS ] ) ) )
return '\n\n' . join ( text )


signature:
def setup_database ( config_data ) :
    """Run the migrate command to create the database schema
 : param config _ data : configuration data"""

implementation:
with chdir ( config_data . project_directory ) :
    env = deepcopy ( dict ( os . environ ) )
    env [ str ( 'DJANGO_SETTINGS_MODULE' ) ] = str ( '{0}.settings' . format ( config_data . project_name ) )
    env [ str ( 'PYTHONPATH' ) ] = str ( os . pathsep . join ( map ( shlex_quote , sys . path ) ) )
    commands = [ ]
    commands . append ( [ sys . executable , '-W' , 'ignore' , 'manage.py' , 'migrate' ] , )
    if config_data . verbose :
        sys . stdout . write ( 'Database setup commands: {0}\n' . format ( ', ' . join ( [ ' ' . join ( cmd ) for cmd in commands ] ) ) )
    for command in commands :
        try :
            output = subprocess . check_output ( command , env = env , stderr = subprocess . STDOUT )
            sys . stdout . write ( output . decode ( 'utf-8' ) )
        except subprocess . CalledProcessError as e : # pragma : no cover
            if config_data . verbose :
                sys . stdout . write ( e . output . decode ( 'utf-8' ) )
            raise
    if not config_data . no_user :
        sys . stdout . write ( 'Creating admin user\n' )
        if config_data . noinput :
            create_user ( config_data )
        else :
            subprocess . check_call ( ' ' . join ( [ sys . executable , '-W' , 'ignore' , 'manage.py' , 'createsuperuser' ] ) , shell = True , stderr = subprocess . STDOUT )


signature:
def create_user ( config_data ) :
    """Create admin user without user input
 : param config _ data : configuration data"""

implementation:
with chdir ( os . path . abspath ( config_data . project_directory ) ) :
    env = deepcopy ( dict ( os . environ ) )
    env [ str ( 'DJANGO_SETTINGS_MODULE' ) ] = str ( '{0}.settings' . format ( config_data . project_name ) )
    env [ str ( 'PYTHONPATH' ) ] = str ( os . pathsep . join ( map ( shlex_quote , sys . path ) ) )
    subprocess . check_call ( [ sys . executable , 'create_user.py' ] , env = env , stderr = subprocess . STDOUT )
    for ext in [ 'py' , 'pyc' ] :
        try :
            os . remove ( 'create_user.{0}' . format ( ext ) )
        except OSError :
            pass


signature:
def sox ( args ) :
    '''Pass an argument list to SoX .
 Parameters
 args : iterable
 Argument list for SoX . The first item can , but does not
 need to , be ' sox ' .
 Returns :
 status : bool
 True on success .'''

implementation:
if args [ 0 ] . lower ( ) != "sox" :
    args . insert ( 0 , "sox" )
else :
    args [ 0 ] = "sox"
try :
    logger . info ( "Executing: %s" , ' ' . join ( args ) )
    process_handle = subprocess . Popen ( args , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
    out , err = process_handle . communicate ( )
    out = out . decode ( "utf-8" )
    err = err . decode ( "utf-8" )
    status = process_handle . returncode
    return status , out , err
except OSError as error_msg :
    logger . error ( "OSError: SoX failed! %s" , error_msg )
except TypeError as error_msg :
    logger . error ( "TypeError: %s" , error_msg )
return 1 , None , None


signature:
def _get_valid_formats ( ) :
    '''Calls SoX help for a lists of audio formats available with the current
 install of SoX .
 Returns :
 formats : list
 List of audio file extensions that SoX can process .'''

implementation:
if NO_SOX :
    return [ ]
so = subprocess . check_output ( [ 'sox' , '-h' ] )
if type ( so ) is not str :
    so = str ( so , encoding = 'UTF-8' )
so = so . split ( '\n' )
idx = [ i for i in range ( len ( so ) ) if 'AUDIO FILE FORMATS:' in so [ i ] ] [ 0 ]
formats = so [ idx ] . split ( ' ' ) [ 3 : ]
return formats


signature:
def soxi ( filepath , argument ) :
    '''Base call to SoXI .
 Parameters
 filepath : str
 Path to audio file .
 argument : str
 Argument to pass to SoXI .
 Returns
 shell _ output : str
 Command line output of SoXI'''

implementation:
if argument not in SOXI_ARGS :
    raise ValueError ( "Invalid argument '{}' to SoXI" . format ( argument ) )
args = [ 'sox' , '--i' ]
args . append ( "-{}" . format ( argument ) )
args . append ( filepath )
try :
    shell_output = subprocess . check_output ( args , stderr = subprocess . PIPE )
except CalledProcessError as cpe :
    logger . info ( "SoXI error message: {}" . format ( cpe . output ) )
    raise SoxiError ( "SoXI failed with exit code {}" . format ( cpe . returncode ) )
shell_output = shell_output . decode ( "utf-8" )
return str ( shell_output ) . strip ( '\n' )


signature:
def play ( args ) :
    '''Pass an argument list to play .
 Parameters
 args : iterable
 Argument list for play . The first item can , but does not
 need to , be ' play ' .
 Returns :
 status : bool
 True on success .'''

implementation:
if args [ 0 ] . lower ( ) != "play" :
    args . insert ( 0 , "play" )
else :
    args [ 0 ] = "play"
try :
    logger . info ( "Executing: %s" , " " . join ( args ) )
    process_handle = subprocess . Popen ( args , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
    status = process_handle . wait ( )
    if process_handle . stderr is not None :
        logger . info ( process_handle . stderr )
    if status == 0 :
        return True
    else :
        logger . info ( "Play returned with error code %s" , status )
        return False
except OSError as error_msg :
    logger . error ( "OSError: Play failed! %s" , error_msg )
except TypeError as error_msg :
    logger . error ( "TypeError: %s" , error_msg )
return False


signature:
def _validate_file_formats ( input_filepath_list , combine_type ) :
    '''Validate that combine method can be performed with given files .
 Raises IOError if input file formats are incompatible .'''

implementation:
_validate_sample_rates ( input_filepath_list , combine_type )
if combine_type == 'concatenate' :
    _validate_num_channels ( input_filepath_list , combine_type )


signature:
def _validate_sample_rates ( input_filepath_list , combine_type ) :
    '''Check if files in input file list have the same sample rate'''

implementation:
sample_rates = [ file_info . sample_rate ( f ) for f in input_filepath_list ]
if not core . all_equal ( sample_rates ) :
    raise IOError ( "Input files do not have the same sample rate. The {} combine " "type requires that all files have the same sample rate" . format ( combine_type ) )


signature:
def _validate_num_channels ( input_filepath_list , combine_type ) :
    '''Check if files in input file list have the same number of channels'''

implementation:
channels = [ file_info . channels ( f ) for f in input_filepath_list ]
if not core . all_equal ( channels ) :
    raise IOError ( "Input files do not have the same number of channels. The " "{} combine type requires that all files have the same " "number of channels" . format ( combine_type ) )


signature:
def _build_input_format_list ( input_filepath_list , input_volumes = None , input_format = None ) :
    '''Set input formats given input _ volumes .
 Parameters
 input _ filepath _ list : list of str
 List of input files
 input _ volumes : list of float , default = None
 List of volumes to be applied upon combining input files . Volumes
 are applied to the input files in order .
 If None , input files will be combined at their original volumes .
 input _ format : list of lists , default = None
 List of input formats to be applied to each input file . Formatting
 arguments are applied to the input files in order .
 If None , the input formats will be inferred from the file header .'''

implementation:
n_inputs = len ( input_filepath_list )
input_format_list = [ ]
for _ in range ( n_inputs ) :
    input_format_list . append ( [ ] )
# Adjust length of input _ volumes list
if input_volumes is None :
    vols = [ 1 ] * n_inputs
else :
    n_volumes = len ( input_volumes )
    if n_volumes < n_inputs :
        logger . warning ( 'Volumes were only specified for %s out of %s files.' 'The last %s files will remain at their original volumes.' , n_volumes , n_inputs , n_inputs - n_volumes )
        vols = input_volumes + [ 1 ] * ( n_inputs - n_volumes )
    elif n_volumes > n_inputs :
        logger . warning ( '%s volumes were specified but only %s input files exist.' 'The last %s volumes will be ignored.' , n_volumes , n_inputs , n_volumes - n_inputs )
        vols = input_volumes [ : n_inputs ]
    else :
        vols = [ v for v in input_volumes ]
# Adjust length of input _ format list
if input_format is None :
    fmts = [ [ ] for _ in range ( n_inputs ) ]
else :
    n_fmts = len ( input_format )
    if n_fmts < n_inputs :
        logger . warning ( 'Input formats were only specified for %s out of %s files.' 'The last %s files will remain unformatted.' , n_fmts , n_inputs , n_inputs - n_fmts )
        fmts = [ f for f in input_format ]
        fmts . extend ( [ [ ] for _ in range ( n_inputs - n_fmts ) ] )
    elif n_fmts > n_inputs :
        logger . warning ( '%s Input formats were specified but only %s input files exist' '. The last %s formats will be ignored.' , n_fmts , n_inputs , n_fmts - n_inputs )
        fmts = input_format [ : n_inputs ]
    else :
        fmts = [ f for f in input_format ]
for i , ( vol , fmt ) in enumerate ( zip ( vols , fmts ) ) :
    input_format_list [ i ] . extend ( [ '-v' , '{}' . format ( vol ) ] )
    input_format_list [ i ] . extend ( fmt )
return input_format_list


signature:
def _build_input_args ( input_filepath_list , input_format_list ) :
    '''Builds input arguments by stitching input filepaths and input
 formats together .'''

implementation:
if len ( input_format_list ) != len ( input_filepath_list ) :
    raise ValueError ( "input_format_list & input_filepath_list are not the same size" )
input_args = [ ]
zipped = zip ( input_filepath_list , input_format_list )
for input_file , input_fmt in zipped :
    input_args . extend ( input_fmt )
    input_args . append ( input_file )
return input_args


signature:
def _validate_volumes ( input_volumes ) :
    '''Check input _ volumes contains a valid list of volumes .
 Parameters
 input _ volumes : list
 list of volume values . Castable to numbers .'''

implementation:
if not ( input_volumes is None or isinstance ( input_volumes , list ) ) :
    raise TypeError ( "input_volumes must be None or a list." )
if isinstance ( input_volumes , list ) :
    for vol in input_volumes :
        if not core . is_number ( vol ) :
            raise ValueError ( "Elements of input_volumes must be numbers: found {}" . format ( vol ) )


signature:
def build ( self , input_filepath_list , output_filepath , combine_type , input_volumes = None ) :
    '''Builds the output _ file by executing the current set of commands .
 Parameters
 input _ filepath _ list : list of str
 List of paths to input audio files .
 output _ filepath : str
 Path to desired output file . If a file already exists at the given
 path , the file will be overwritten .
 combine _ type : str
 Input file combining method . One of the following values :
 * concatenate : combine input files by concatenating in the
 order given .
 * merge : combine input files by stacking each input file into
 a new channel of the output file .
 * mix : combine input files by summing samples in corresponding
 channels .
 * mix - power : combine input files with volume adjustments such
 that the output volume is roughly equivlent to one of the
 input signals .
 * multiply : combine input files by multiplying samples in
 corresponding samples .
 input _ volumes : list of float , default = None
 List of volumes to be applied upon combining input files . Volumes
 are applied to the input files in order .
 If None , input files will be combined at their original volumes .'''

implementation:
file_info . validate_input_file_list ( input_filepath_list )
file_info . validate_output_file ( output_filepath )
_validate_combine_type ( combine_type )
_validate_volumes ( input_volumes )
input_format_list = _build_input_format_list ( input_filepath_list , input_volumes , self . input_format )
try :
    _validate_file_formats ( input_filepath_list , combine_type )
except SoxiError :
    logger . warning ( "unable to validate file formats." )
args = [ ]
args . extend ( self . globals )
args . extend ( [ '--combine' , combine_type ] )
input_args = _build_input_args ( input_filepath_list , input_format_list )
args . extend ( input_args )
args . extend ( self . output_format )
args . append ( output_filepath )
args . extend ( self . effects )
status , out , err = sox ( args )
if status != 0 :
    raise SoxError ( "Stdout: {}\nStderr: {}" . format ( out , err ) )
else :
    logger . info ( "Created %s with combiner %s and  effects: %s" , output_filepath , combine_type , " " . join ( self . effects_log ) )
    if out is not None :
        logger . info ( "[SoX] {}" . format ( out ) )
    return True


signature:
def preview ( self , input_filepath_list , combine_type , input_volumes = None ) :
    '''Play a preview of the output with the current set of effects
 Parameters
 input _ filepath _ list : list of str
 List of paths to input audio files .
 combine _ type : str
 Input file combining method . One of the following values :
 * concatenate : combine input files by concatenating in the
 order given .
 * merge : combine input files by stacking each input file into
 a new channel of the output file .
 * mix : combine input files by summing samples in corresponding
 channels .
 * mix - power : combine input files with volume adjustments such
 that the output volume is roughly equivlent to one of the
 input signals .
 * multiply : combine input files by multiplying samples in
 corresponding samples .
 input _ volumes : list of float , default = None
 List of volumes to be applied upon combining input files . Volumes
 are applied to the input files in order .
 If None , input files will be combined at their original volumes .'''

implementation:
args = [ "play" , "--no-show-progress" ]
args . extend ( self . globals )
args . extend ( [ '--combine' , combine_type ] )
input_format_list = _build_input_format_list ( input_filepath_list , input_volumes , self . input_format )
input_args = _build_input_args ( input_filepath_list , input_format_list )
args . extend ( input_args )
args . extend ( self . effects )
play ( args )


signature:
def set_input_format ( self , file_type = None , rate = None , bits = None , channels = None , encoding = None , ignore_length = None ) :
    '''Sets input file format arguments . This is primarily useful when
 dealing with audio files without a file extension . Overwrites any
 previously set input file arguments .
 If this function is not explicity called the input format is inferred
 from the file extension or the file ' s header .
 Parameters
 file _ type : list of str or None , default = None
 The file type of the input audio file . Should be the same as what
 the file extension would be , for ex . ' mp3 ' or ' wav ' .
 rate : list of float or None , default = None
 The sample rate of the input audio file . If None the sample rate
 is inferred .
 bits : list of int or None , default = None
 The number of bits per sample . If None , the number of bits per
 sample is inferred .
 channels : list of int or None , default = None
 The number of channels in the audio file . If None the number of
 channels is inferred .
 encoding : list of str or None , default = None
 The audio encoding type . Sometimes needed with file - types that
 support more than one encoding type . One of :
 * signed - integer : PCM data stored as signed ( ‘ two ’ s
 complement ’ ) integers . Commonly used with a 16 or 24 − bit
 encoding size . A value of 0 represents minimum signal
 power .
 * unsigned - integer : PCM data stored as unsigned integers .
 Commonly used with an 8 - bit encoding size . A value of 0
 represents maximum signal power .
 * floating - point : PCM data stored as IEEE 753 single precision
 (32 - bit ) or double precision ( 64 - bit ) floating - point
 ( ‘ real ’ ) numbers . A value of 0 represents minimum signal
 power .
 * a - law : International telephony standard for logarithmic
 encoding to 8 bits per sample . It has a precision
 equivalent to roughly 13 - bit PCM and is sometimes encoded
 with reversed bit - ordering .
 * u - law : North American telephony standard for logarithmic
 encoding to 8 bits per sample . A . k . a . μ - law . It has a
 precision equivalent to roughly 14 - bit PCM and is sometimes
 encoded with reversed bit - ordering .
 * oki - adpcm : OKI ( a . k . a . VOX , Dialogic , or Intel ) 4 - bit ADPCM ;
 it has a precision equivalent to roughly 12 - bit PCM . ADPCM
 is a form of audio compression that has a good compromise
 between audio quality and encoding / decoding speed .
 * ima - adpcm : IMA ( a . k . a . DVI ) 4 - bit ADPCM ; it has a precision
 equivalent to roughly 13 - bit PCM .
 * ms - adpcm : Microsoft 4 - bit ADPCM ; it has a precision
 equivalent to roughly 14 - bit PCM .
 * gsm - full - rate : GSM is currently used for the vast majority
 of the world ’ s digital wireless telephone calls . It
 utilises several audio formats with different bit - rates and
 associated speech quality . SoX has support for GSM ’ s
 original 13kbps ‘ Full Rate ’ audio format . It is usually
 CPU - intensive to work with GSM audio .
 ignore _ length : list of bool or None , default = None
 If True , overrides an ( incorrect ) audio length given in an audio
 file ’ s header . If this option is given then SoX will keep reading
 audio until it reaches the end of the input file .'''

implementation:
if file_type is not None and not isinstance ( file_type , list ) :
    raise ValueError ( "file_type must be a list or None." )
if file_type is not None :
    if not all ( [ f in VALID_FORMATS for f in file_type ] ) :
        raise ValueError ( 'file_type elements ' 'must be one of {}' . format ( VALID_FORMATS ) )
else :
    file_type = [ ]
if rate is not None and not isinstance ( rate , list ) :
    raise ValueError ( "rate must be a list or None." )
if rate is not None :
    if not all ( [ is_number ( r ) and r > 0 for r in rate ] ) :
        raise ValueError ( 'rate elements must be positive floats.' )
else :
    rate = [ ]
if bits is not None and not isinstance ( bits , list ) :
    raise ValueError ( "bits must be a list or None." )
if bits is not None :
    if not all ( [ isinstance ( b , int ) and b > 0 for b in bits ] ) :
        raise ValueError ( 'bit elements must be positive ints.' )
else :
    bits = [ ]
if channels is not None and not isinstance ( channels , list ) :
    raise ValueError ( "channels must be a list or None." )
if channels is not None :
    if not all ( [ isinstance ( c , int ) and c > 0 for c in channels ] ) :
        raise ValueError ( 'channel elements must be positive ints.' )
else :
    channels = [ ]
if encoding is not None and not isinstance ( encoding , list ) :
    raise ValueError ( "encoding must be a list or None." )
if encoding is not None :
    if not all ( [ e in ENCODING_VALS for e in encoding ] ) :
        raise ValueError ( 'elements of encoding must ' 'be one of {}' . format ( ENCODING_VALS ) )
else :
    encoding = [ ]
if ignore_length is not None and not isinstance ( ignore_length , list ) :
    raise ValueError ( "ignore_length must be a list or None." )
if ignore_length is not None :
    if not all ( [ isinstance ( l , bool ) for l in ignore_length ] ) :
        raise ValueError ( "ignore_length elements must be booleans." )
else :
    ignore_length = [ ]
max_input_arg_len = max ( [ len ( file_type ) , len ( rate ) , len ( bits ) , len ( channels ) , len ( encoding ) , len ( ignore_length ) ] )
input_format = [ ]
for _ in range ( max_input_arg_len ) :
    input_format . append ( [ ] )
for i , f in enumerate ( file_type ) :
    input_format [ i ] . extend ( [ '-t' , '{}' . format ( f ) ] )
for i , r in enumerate ( rate ) :
    input_format [ i ] . extend ( [ '-r' , '{}' . format ( r ) ] )
for i , b in enumerate ( bits ) :
    input_format [ i ] . extend ( [ '-b' , '{}' . format ( b ) ] )
for i , c in enumerate ( channels ) :
    input_format [ i ] . extend ( [ '-c' , '{}' . format ( c ) ] )
for i , e in enumerate ( encoding ) :
    input_format [ i ] . extend ( [ '-e' , '{}' . format ( e ) ] )
for i , l in enumerate ( ignore_length ) :
    if l is True :
        input_format [ i ] . append ( '--ignore-length' )
self . input_format = input_format
return self


signature:
def bitrate ( input_filepath ) :
    '''Number of bits per sample ( 0 if not applicable ) .
 Parameters
 input _ filepath : str
 Path to audio file .
 Returns
 bitrate : int
 number of bits per sample
 returns 0 if not applicable'''

implementation:
validate_input_file ( input_filepath )
output = soxi ( input_filepath , 'b' )
if output == '0' :
    logger . warning ( "Bitrate unavailable for %s" , input_filepath )
return int ( output )


signature:
def duration ( input_filepath ) :
    '''Show duration in seconds ( 0 if unavailable ) .
 Parameters
 input _ filepath : str
 Path to audio file .
 Returns
 duration : float
 Duration of audio file in seconds .
 If unavailable or empty , returns 0.'''

implementation:
validate_input_file ( input_filepath )
output = soxi ( input_filepath , 'D' )
if output == '0' :
    logger . warning ( "Duration unavailable for %s" , input_filepath )
return float ( output )


signature:
def num_samples ( input_filepath ) :
    '''Show number of samples ( 0 if unavailable ) .
 Parameters
 input _ filepath : str
 Path to audio file .
 Returns
 n _ samples : int
 total number of samples in audio file .
 Returns 0 if empty or unavailable'''

implementation:
validate_input_file ( input_filepath )
output = soxi ( input_filepath , 's' )
if output == '0' :
    logger . warning ( "Number of samples unavailable for %s" , input_filepath )
return int ( output )


signature:
def silent ( input_filepath , threshold = 0.001 ) :
    '''Determine if an input file is silent .
 Parameters
 input _ filepath : str
 The input filepath .
 threshold : float
 Threshold for determining silence
 Returns
 is _ silent : bool
 True if file is determined silent .'''

implementation:
validate_input_file ( input_filepath )
stat_dictionary = stat ( input_filepath )
mean_norm = stat_dictionary [ 'Mean    norm' ]
if mean_norm is not float ( 'nan' ) :
    if mean_norm >= threshold :
        return False
    else :
        return True
else :
    return True


signature:
def validate_input_file ( input_filepath ) :
    '''Input file validation function . Checks that file exists and can be
 processed by SoX .
 Parameters
 input _ filepath : str
 The input filepath .'''

implementation:
if not os . path . exists ( input_filepath ) :
    raise IOError ( "input_filepath {} does not exist." . format ( input_filepath ) )
ext = file_extension ( input_filepath )
if ext not in VALID_FORMATS :
    logger . info ( "Valid formats: %s" , " " . join ( VALID_FORMATS ) )
    logger . warning ( "This install of SoX cannot process .{} files." . format ( ext ) )


signature:
def validate_input_file_list ( input_filepath_list ) :
    '''Input file list validation function . Checks that object is a list and
 contains valid filepaths that can be processed by SoX .
 Parameters
 input _ filepath _ list : list
 A list of filepaths .'''

implementation:
if not isinstance ( input_filepath_list , list ) :
    raise TypeError ( "input_filepath_list must be a list." )
elif len ( input_filepath_list ) < 2 :
    raise ValueError ( "input_filepath_list must have at least 2 files." )
for input_filepath in input_filepath_list :
    validate_input_file ( input_filepath )


signature:
def validate_output_file ( output_filepath ) :
    '''Output file validation function . Checks that file can be written , and
 has a valid file extension . Throws a warning if the path already exists ,
 as it will be overwritten on build .
 Parameters
 output _ filepath : str
 The output filepath .
 Returns :
 output _ filepath : str
 The output filepath .'''

implementation:
nowrite_conditions = [ bool ( os . path . dirname ( output_filepath ) ) or not os . access ( os . getcwd ( ) , os . W_OK ) , not os . access ( os . path . dirname ( output_filepath ) , os . W_OK ) ]
if all ( nowrite_conditions ) :
    raise IOError ( "SoX cannot write to output_filepath {}" . format ( output_filepath ) )
ext = file_extension ( output_filepath )
if ext not in VALID_FORMATS :
    logger . info ( "Valid formats: %s" , " " . join ( VALID_FORMATS ) )
    logger . warning ( "This install of SoX cannot process .{} files." . format ( ext ) )
if os . path . exists ( output_filepath ) :
    logger . warning ( 'output_file: %s already exists and will be overwritten on build' , output_filepath )


signature:
def info ( filepath ) :
    '''Get a dictionary of file information
 Parameters
 filepath : str
 File path .
 Returns :
 info _ dictionary : dict
 Dictionary of file information . Fields are :
 * channels
 * sample _ rate
 * bitrate
 * duration
 * num _ samples
 * encoding
 * silent'''

implementation:
info_dictionary = { 'channels' : channels ( filepath ) , 'sample_rate' : sample_rate ( filepath ) , 'bitrate' : bitrate ( filepath ) , 'duration' : duration ( filepath ) , 'num_samples' : num_samples ( filepath ) , 'encoding' : encoding ( filepath ) , 'silent' : silent ( filepath ) }
return info_dictionary


signature:
def _stat_call ( filepath ) :
    '''Call sox ' s stat function .
 Parameters
 filepath : str
 File path .
 Returns
 stat _ output : str
 Sox output from stderr .'''

implementation:
validate_input_file ( filepath )
args = [ 'sox' , filepath , '-n' , 'stat' ]
_ , _ , stat_output = sox ( args )
return stat_output


signature:
def _parse_stat ( stat_output ) :
    '''Parse the string output from sox ' s stat function
 Parameters
 stat _ output : str
 Sox output from stderr .
 Returns
 stat _ dictionary : dict
 Dictionary of audio statistics .'''

implementation:
lines = stat_output . split ( '\n' )
stat_dict = { }
for line in lines :
    split_line = line . split ( ':' )
    if len ( split_line ) == 2 :
        key = split_line [ 0 ]
        val = split_line [ 1 ] . strip ( ' ' )
        try :
            val = float ( val )
        except ValueError :
            val = None
        stat_dict [ key ] = val
return stat_dict


signature:
def set_globals ( self , dither = False , guard = False , multithread = False , replay_gain = False , verbosity = 2 ) :
    '''Sets SoX ' s global arguments .
 Overwrites any previously set global arguments .
 If this function is not explicity called , globals are set to this
 function ' s defaults .
 Parameters
 dither : bool , default = False
 If True , dithering is applied for low files with low bit rates .
 guard : bool , default = False
 If True , invokes the gain effect to guard against clipping .
 multithread : bool , default = False
 If True , each channel is processed in parallel .
 replay _ gain : bool , default = False
 If True , applies replay - gain adjustment to input - files .
 verbosity : int , default = 2
 SoX ' s verbosity level . One of :
 * 0 : No messages are shown at all
 * 1 : Only error messages are shown . These are generated if SoX
 cannot complete the requested commands .
 * 2 : Warning messages are also shown . These are generated if
 SoX can complete the requested commands , but not exactly
 according to the requested command parameters , or if
 clipping occurs .
 * 3 : Descriptions of SoX ’ s processing phases are also shown .
 Useful for seeing exactly how SoX is processing your audio .
 * 4 , > 4 : Messages to help with debugging SoX are also shown .'''

implementation:
if not isinstance ( dither , bool ) :
    raise ValueError ( 'dither must be a boolean.' )
if not isinstance ( guard , bool ) :
    raise ValueError ( 'guard must be a boolean.' )
if not isinstance ( multithread , bool ) :
    raise ValueError ( 'multithread must be a boolean.' )
if not isinstance ( replay_gain , bool ) :
    raise ValueError ( 'replay_gain must be a boolean.' )
if verbosity not in VERBOSITY_VALS :
    raise ValueError ( 'Invalid value for VERBOSITY. Must be one {}' . format ( VERBOSITY_VALS ) )
global_args = [ ]
if not dither :
    global_args . append ( '-D' )
if guard :
    global_args . append ( '-G' )
if multithread :
    global_args . append ( '--multi-threaded' )
if replay_gain :
    global_args . append ( '--replay-gain' )
    global_args . append ( 'track' )
global_args . append ( '-V{}' . format ( verbosity ) )
self . globals = global_args
return self


signature:
def set_input_format ( self , file_type = None , rate = None , bits = None , channels = None , encoding = None , ignore_length = False ) :
    '''Sets input file format arguments . This is primarily useful when
 dealing with audio files without a file extension . Overwrites any
 previously set input file arguments .
 If this function is not explicity called the input format is inferred
 from the file extension or the file ' s header .
 Parameters
 file _ type : str or None , default = None
 The file type of the input audio file . Should be the same as what
 the file extension would be , for ex . ' mp3 ' or ' wav ' .
 rate : float or None , default = None
 The sample rate of the input audio file . If None the sample rate
 is inferred .
 bits : int or None , default = None
 The number of bits per sample . If None , the number of bits per
 sample is inferred .
 channels : int or None , default = None
 The number of channels in the audio file . If None the number of
 channels is inferred .
 encoding : str or None , default = None
 The audio encoding type . Sometimes needed with file - types that
 support more than one encoding type . One of :
 * signed - integer : PCM data stored as signed ( ‘ two ’ s
 complement ’ ) integers . Commonly used with a 16 or 24 − bit
 encoding size . A value of 0 represents minimum signal
 power .
 * unsigned - integer : PCM data stored as unsigned integers .
 Commonly used with an 8 - bit encoding size . A value of 0
 represents maximum signal power .
 * floating - point : PCM data stored as IEEE 753 single precision
 (32 - bit ) or double precision ( 64 - bit ) floating - point
 ( ‘ real ’ ) numbers . A value of 0 represents minimum signal
 power .
 * a - law : International telephony standard for logarithmic
 encoding to 8 bits per sample . It has a precision
 equivalent to roughly 13 - bit PCM and is sometimes encoded
 with reversed bit - ordering .
 * u - law : North American telephony standard for logarithmic
 encoding to 8 bits per sample . A . k . a . μ - law . It has a
 precision equivalent to roughly 14 - bit PCM and is sometimes
 encoded with reversed bit - ordering .
 * oki - adpcm : OKI ( a . k . a . VOX , Dialogic , or Intel ) 4 - bit ADPCM ;
 it has a precision equivalent to roughly 12 - bit PCM . ADPCM
 is a form of audio compression that has a good compromise
 between audio quality and encoding / decoding speed .
 * ima - adpcm : IMA ( a . k . a . DVI ) 4 - bit ADPCM ; it has a precision
 equivalent to roughly 13 - bit PCM .
 * ms - adpcm : Microsoft 4 - bit ADPCM ; it has a precision
 equivalent to roughly 14 - bit PCM .
 * gsm - full - rate : GSM is currently used for the vast majority
 of the world ’ s digital wireless telephone calls . It
 utilises several audio formats with different bit - rates and
 associated speech quality . SoX has support for GSM ’ s
 original 13kbps ‘ Full Rate ’ audio format . It is usually
 CPU - intensive to work with GSM audio .
 ignore _ length : bool , default = False
 If True , overrides an ( incorrect ) audio length given in an audio
 file ’ s header . If this option is given then SoX will keep reading
 audio until it reaches the end of the input file .'''

implementation:
if file_type not in VALID_FORMATS + [ None ] :
    raise ValueError ( 'Invalid file_type. Must be one of {}' . format ( VALID_FORMATS ) )
if not is_number ( rate ) and rate is not None :
    raise ValueError ( 'rate must be a float or None' )
if rate is not None and rate <= 0 :
    raise ValueError ( 'rate must be a positive number' )
if not isinstance ( bits , int ) and bits is not None :
    raise ValueError ( 'bits must be an int or None' )
if bits is not None and bits <= 0 :
    raise ValueError ( 'bits must be a positive number' )
if not isinstance ( channels , int ) and channels is not None :
    raise ValueError ( 'channels must be an int or None' )
if channels is not None and channels <= 0 :
    raise ValueError ( 'channels must be a positive number' )
if encoding not in ENCODING_VALS + [ None ] :
    raise ValueError ( 'Invalid encoding. Must be one of {}' . format ( ENCODING_VALS ) )
if not isinstance ( ignore_length , bool ) :
    raise ValueError ( 'ignore_length must be a boolean' )
input_format = [ ]
if file_type is not None :
    input_format . extend ( [ '-t' , '{}' . format ( file_type ) ] )
if rate is not None :
    input_format . extend ( [ '-r' , '{:f}' . format ( rate ) ] )
if bits is not None :
    input_format . extend ( [ '-b' , '{}' . format ( bits ) ] )
if channels is not None :
    input_format . extend ( [ '-c' , '{}' . format ( channels ) ] )
if encoding is not None :
    input_format . extend ( [ '-e' , '{}' . format ( encoding ) ] )
if ignore_length :
    input_format . append ( '--ignore-length' )
self . input_format = input_format
return self


signature:
def set_output_format ( self , file_type = None , rate = None , bits = None , channels = None , encoding = None , comments = None , append_comments = True ) :
    '''Sets output file format arguments . These arguments will overwrite
 any format related arguments supplied by other effects ( e . g . rate ) .
 If this function is not explicity called the output format is inferred
 from the file extension or the file ' s header .
 Parameters
 file _ type : str or None , default = None
 The file type of the output audio file . Should be the same as what
 the file extension would be , for ex . ' mp3 ' or ' wav ' .
 rate : float or None , default = None
 The sample rate of the output audio file . If None the sample rate
 is inferred .
 bits : int or None , default = None
 The number of bits per sample . If None , the number of bits per
 sample is inferred .
 channels : int or None , default = None
 The number of channels in the audio file . If None the number of
 channels is inferred .
 encoding : str or None , default = None
 The audio encoding type . Sometimes needed with file - types that
 support more than one encoding type . One of :
 * signed - integer : PCM data stored as signed ( ‘ two ’ s
 complement ’ ) integers . Commonly used with a 16 or 24 − bit
 encoding size . A value of 0 represents minimum signal
 power .
 * unsigned - integer : PCM data stored as unsigned integers .
 Commonly used with an 8 - bit encoding size . A value of 0
 represents maximum signal power .
 * floating - point : PCM data stored as IEEE 753 single precision
 (32 - bit ) or double precision ( 64 - bit ) floating - point
 ( ‘ real ’ ) numbers . A value of 0 represents minimum signal
 power .
 * a - law : International telephony standard for logarithmic
 encoding to 8 bits per sample . It has a precision
 equivalent to roughly 13 - bit PCM and is sometimes encoded
 with reversed bit - ordering .
 * u - law : North American telephony standard for logarithmic
 encoding to 8 bits per sample . A . k . a . μ - law . It has a
 precision equivalent to roughly 14 - bit PCM and is sometimes
 encoded with reversed bit - ordering .
 * oki - adpcm : OKI ( a . k . a . VOX , Dialogic , or Intel ) 4 - bit ADPCM ;
 it has a precision equivalent to roughly 12 - bit PCM . ADPCM
 is a form of audio compression that has a good compromise
 between audio quality and encoding / decoding speed .
 * ima - adpcm : IMA ( a . k . a . DVI ) 4 - bit ADPCM ; it has a precision
 equivalent to roughly 13 - bit PCM .
 * ms - adpcm : Microsoft 4 - bit ADPCM ; it has a precision
 equivalent to roughly 14 - bit PCM .
 * gsm - full - rate : GSM is currently used for the vast majority
 of the world ’ s digital wireless telephone calls . It
 utilises several audio formats with different bit - rates and
 associated speech quality . SoX has support for GSM ’ s
 original 13kbps ‘ Full Rate ’ audio format . It is usually
 CPU - intensive to work with GSM audio .
 comments : str or None , default = None
 If not None , the string is added as a comment in the header of the
 output audio file . If None , no comments are added .
 append _ comments : bool , default = True
 If True , comment strings are appended to SoX ' s default comments . If
 False , the supplied comment replaces the existing comment .'''

implementation:
if file_type not in VALID_FORMATS + [ None ] :
    raise ValueError ( 'Invalid file_type. Must be one of {}' . format ( VALID_FORMATS ) )
if not is_number ( rate ) and rate is not None :
    raise ValueError ( 'rate must be a float or None' )
if rate is not None and rate <= 0 :
    raise ValueError ( 'rate must be a positive number' )
if not isinstance ( bits , int ) and bits is not None :
    raise ValueError ( 'bits must be an int or None' )
if bits is not None and bits <= 0 :
    raise ValueError ( 'bits must be a positive number' )
if not isinstance ( channels , int ) and channels is not None :
    raise ValueError ( 'channels must be an int or None' )
if channels is not None and channels <= 0 :
    raise ValueError ( 'channels must be a positive number' )
if encoding not in ENCODING_VALS + [ None ] :
    raise ValueError ( 'Invalid encoding. Must be one of {}' . format ( ENCODING_VALS ) )
if comments is not None and not isinstance ( comments , str ) :
    raise ValueError ( 'comments must be a string or None' )
if not isinstance ( append_comments , bool ) :
    raise ValueError ( 'append_comments must be a boolean' )
output_format = [ ]
if file_type is not None :
    output_format . extend ( [ '-t' , '{}' . format ( file_type ) ] )
if rate is not None :
    output_format . extend ( [ '-r' , '{:f}' . format ( rate ) ] )
if bits is not None :
    output_format . extend ( [ '-b' , '{}' . format ( bits ) ] )
if channels is not None :
    output_format . extend ( [ '-c' , '{}' . format ( channels ) ] )
if encoding is not None :
    output_format . extend ( [ '-e' , '{}' . format ( encoding ) ] )
if comments is not None :
    if append_comments :
        output_format . extend ( [ '--add-comment' , comments ] )
    else :
        output_format . extend ( [ '--comment' , comments ] )
self . output_format = output_format
return self


signature:
def build ( self , input_filepath , output_filepath , extra_args = None , return_output = False ) :
    '''Builds the output _ file by executing the current set of commands .
 Parameters
 input _ filepath : str
 Path to input audio file .
 output _ filepath : str or None
 Path to desired output file . If a file already exists at the given
 path , the file will be overwritten .
 If None , no file will be created .
 extra _ args : list or None , default = None
 If a list is given , these additional arguments are passed to SoX
 at the end of the list of effects .
 Don ' t use this argument unless you know exactly what you ' re doing !
 return _ output : bool , default = False
 If True , returns the status and information sent to stderr and
 stdout as a tuple ( status , stdout , stderr ) .
 Otherwise returns True on success .'''

implementation:
file_info . validate_input_file ( input_filepath )
if output_filepath is not None :
    file_info . validate_output_file ( output_filepath )
else :
    output_filepath = '-n'
if input_filepath == output_filepath :
    raise ValueError ( "input_filepath must be different from output_filepath." )
args = [ ]
args . extend ( self . globals )
args . extend ( self . input_format )
args . append ( input_filepath )
args . extend ( self . output_format )
args . append ( output_filepath )
args . extend ( self . effects )
if extra_args is not None :
    if not isinstance ( extra_args , list ) :
        raise ValueError ( "extra_args must be a list." )
    args . extend ( extra_args )
status , out , err = sox ( args )
if status != 0 :
    raise SoxError ( "Stdout: {}\nStderr: {}" . format ( out , err ) )
else :
    logger . info ( "Created %s with effects: %s" , output_filepath , " " . join ( self . effects_log ) )
    if out is not None :
        logger . info ( "[SoX] {}" . format ( out ) )
    if return_output :
        return status , out , err
    else :
        return True


signature:
def preview ( self , input_filepath ) :
    '''Play a preview of the output with the current set of effects
 Parameters
 input _ filepath : str
 Path to input audio file .'''

implementation:
args = [ "play" , "--no-show-progress" ]
args . extend ( self . globals )
args . extend ( self . input_format )
args . append ( input_filepath )
args . extend ( self . effects )
play ( args )


signature:
def allpass ( self , frequency , width_q = 2.0 ) :
    '''Apply a two - pole all - pass filter . An all - pass filter changes the
 audio ’ s frequency to phase relationship without changing its frequency
 to amplitude relationship . The filter is described in detail in at
 http : / / musicdsp . org / files / Audio - EQ - Cookbook . txt
 Parameters
 frequency : float
 The filter ' s center frequency in Hz .
 width _ q : float , default = 2.0
 The filter ' s width as a Q - factor .
 See Also
 equalizer , highpass , lowpass , sinc'''

implementation:
if not is_number ( frequency ) or frequency <= 0 :
    raise ValueError ( "frequency must be a positive number." )
if not is_number ( width_q ) or width_q <= 0 :
    raise ValueError ( "width_q must be a positive number." )
effect_args = [ 'allpass' , '{:f}' . format ( frequency ) , '{:f}q' . format ( width_q ) ]
self . effects . extend ( effect_args )
self . effects_log . append ( 'allpass' )
return self


signature:
def bandpass ( self , frequency , width_q = 2.0 , constant_skirt = False ) :
    '''Apply a two - pole Butterworth band - pass filter with the given central
 frequency , and ( 3dB - point ) band - width . The filter rolls off at 6dB per
 octave ( 20dB per decade ) and is described in detail in
 http : / / musicdsp . org / files / Audio - EQ - Cookbook . txt
 Parameters
 frequency : float
 The filter ' s center frequency in Hz .
 width _ q : float , default = 2.0
 The filter ' s width as a Q - factor .
 constant _ skirt : bool , default = False
 If True , selects constant skirt gain ( peak gain = width _ q ) .
 If False , selects constant 0dB peak gain .
 See Also
 bandreject , sinc'''

implementation:
if not is_number ( frequency ) or frequency <= 0 :
    raise ValueError ( "frequency must be a positive number." )
if not is_number ( width_q ) or width_q <= 0 :
    raise ValueError ( "width_q must be a positive number." )
if not isinstance ( constant_skirt , bool ) :
    raise ValueError ( "constant_skirt must be a boolean." )
effect_args = [ 'bandpass' ]
if constant_skirt :
    effect_args . append ( '-c' )
effect_args . extend ( [ '{:f}' . format ( frequency ) , '{:f}q' . format ( width_q ) ] )
self . effects . extend ( effect_args )
self . effects_log . append ( 'bandpass' )
return self


signature:
def bend ( self , n_bends , start_times , end_times , cents , frame_rate = 25 , oversample_rate = 16 ) :
    '''Changes pitch by specified amounts at specified times .
 The pitch - bending algorithm utilises the Discrete Fourier Transform
 ( DFT ) at a particular frame rate and over - sampling rate .
 Parameters
 n _ bends : int
 The number of intervals to pitch shift
 start _ times : list of floats
 A list of absolute start times ( in seconds ) , in order
 end _ times : list of floats
 A list of absolute end times ( in seconds ) in order .
 [ start _ time , end _ time ] intervals may not overlap !
 cents : list of floats
 A list of pitch shifts in cents . A positive value shifts the pitch
 up , a negative value shifts the pitch down .
 frame _ rate : int , default = 25
 The number of DFT frames to process per second , between 10 and 80
 oversample _ rate : int , default = 16
 The number of frames to over sample per second , between 4 and 32
 See Also
 pitch'''

implementation:
if not isinstance ( n_bends , int ) or n_bends < 1 :
    raise ValueError ( "n_bends must be a positive integer." )
if not isinstance ( start_times , list ) or len ( start_times ) != n_bends :
    raise ValueError ( "start_times must be a list of length n_bends." )
if any ( [ ( not is_number ( p ) or p <= 0 ) for p in start_times ] ) :
    raise ValueError ( "start_times must be positive floats." )
if sorted ( start_times ) != start_times :
    raise ValueError ( "start_times must be in increasing order." )
if not isinstance ( end_times , list ) or len ( end_times ) != n_bends :
    raise ValueError ( "end_times must be a list of length n_bends." )
if any ( [ ( not is_number ( p ) or p <= 0 ) for p in end_times ] ) :
    raise ValueError ( "end_times must be positive floats." )
if sorted ( end_times ) != end_times :
    raise ValueError ( "end_times must be in increasing order." )
if any ( [ e <= s for s , e in zip ( start_times , end_times ) ] ) :
    raise ValueError ( "end_times must be element-wise greater than start_times." )
if any ( [ e > s for s , e in zip ( start_times [ 1 : ] , end_times [ : - 1 ] ) ] ) :
    raise ValueError ( "[start_time, end_time] intervals must be non-overlapping." )
if not isinstance ( cents , list ) or len ( cents ) != n_bends :
    raise ValueError ( "cents must be a list of length n_bends." )
if any ( [ not is_number ( p ) for p in cents ] ) :
    raise ValueError ( "elements of cents must be floats." )
if ( not isinstance ( frame_rate , int ) or frame_rate < 10 or frame_rate > 80 ) :
    raise ValueError ( "frame_rate must be an integer between 10 and 80" )
if ( not isinstance ( oversample_rate , int ) or oversample_rate < 4 or oversample_rate > 32 ) :
    raise ValueError ( "oversample_rate must be an integer between 4 and 32." )
effect_args = [ 'bend' , '-f' , '{}' . format ( frame_rate ) , '-o' , '{}' . format ( oversample_rate ) ]
last = 0
for i in range ( n_bends ) :
    t_start = round ( start_times [ i ] - last , 2 )
    t_end = round ( end_times [ i ] - start_times [ i ] , 2 )
    effect_args . append ( '{:f},{:f},{:f}' . format ( t_start , cents [ i ] , t_end ) )
    last = end_times [ i ]
self . effects . extend ( effect_args )
self . effects_log . append ( 'bend' )
return self


signature:
def biquad ( self , b , a ) :
    '''Apply a biquad IIR filter with the given coefficients .
 Parameters
 b : list of floats
 Numerator coefficients . Must be length 3
 a : list of floats
 Denominator coefficients . Must be length 3
 See Also
 fir , treble , bass , equalizer'''

implementation:
if not isinstance ( b , list ) :
    raise ValueError ( 'b must be a list.' )
if not isinstance ( a , list ) :
    raise ValueError ( 'a must be a list.' )
if len ( b ) != 3 :
    raise ValueError ( 'b must be a length 3 list.' )
if len ( a ) != 3 :
    raise ValueError ( 'a must be a length 3 list.' )
if not all ( [ is_number ( b_val ) for b_val in b ] ) :
    raise ValueError ( 'all elements of b must be numbers.' )
if not all ( [ is_number ( a_val ) for a_val in a ] ) :
    raise ValueError ( 'all elements of a must be numbers.' )
effect_args = [ 'biquad' , '{:f}' . format ( b [ 0 ] ) , '{:f}' . format ( b [ 1 ] ) , '{:f}' . format ( b [ 2 ] ) , '{:f}' . format ( a [ 0 ] ) , '{:f}' . format ( a [ 1 ] ) , '{:f}' . format ( a [ 2 ] ) ]
self . effects . extend ( effect_args )
self . effects_log . append ( 'biquad' )
return self


signature:
def channels ( self , n_channels ) :
    '''Change the number of channels in the audio signal . If decreasing the
 number of channels it mixes channels together , if increasing the number
 of channels it duplicates .
 Note : This overrides arguments used in the convert effect !
 Parameters
 n _ channels : int
 Desired number of channels .
 See Also
 convert'''

implementation:
if not isinstance ( n_channels , int ) or n_channels <= 0 :
    raise ValueError ( 'n_channels must be a positive integer.' )
effect_args = [ 'channels' , '{}' . format ( n_channels ) ]
self . effects . extend ( effect_args )
self . effects_log . append ( 'channels' )
return self


signature:
def chorus ( self , gain_in = 0.5 , gain_out = 0.9 , n_voices = 3 , delays = None , decays = None , speeds = None , depths = None , shapes = None ) :
    '''Add a chorus effect to the audio . This can makeasingle vocal sound
 like a chorus , but can also be applied to instrumentation .
 Chorus resembles an echo effect with a short delay , but whereas with
 echo the delay is constant , with chorus , it is varied using sinusoidal
 or triangular modulation . The modulation depth defines the range the
 modulated delay is played before or after the delay . Hence the delayed
 sound will sound slower or faster , that is the delayed sound tuned
 around the original one , like in a chorus where some vocals are
 slightly off key .
 Parameters
 gain _ in : float , default = 0.3
 The time in seconds over which the instantaneous level of the input
 signal is averaged to determine increases in volume .
 gain _ out : float , default = 0.8
 The time in seconds over which the instantaneous level of the input
 signal is averaged to determine decreases in volume .
 n _ voices : int , default = 3
 The number of voices in the chorus effect .
 delays : list of floats > 20 or None , default = None
 If a list , the list of delays ( in miliseconds ) of length n _ voices .
 If None , the individual delay parameters are chosen automatically
 to be between 40 and 60 miliseconds .
 decays : list of floats or None , default = None
 If a list , the list of decays ( as a fraction of gain _ in ) of length
 n _ voices .
 If None , the individual decay parameters are chosen automatically
 to be between 0.3 and 0.4.
 speeds : list of floats or None , default = None
 If a list , the list of modulation speeds ( in Hz ) of length n _ voices
 If None , the individual speed parameters are chosen automatically
 to be between 0.25 and 0.4 Hz .
 depths : list of floats or None , default = None
 If a list , the list of depths ( in miliseconds ) of length n _ voices .
 If None , the individual delay parameters are chosen automatically
 to be between 1 and 3 miliseconds .
 shapes : list of ' s ' or ' t ' or None , deault = None
 If a list , the list of modulation shapes - ' s ' for sinusoidal or
 ' t ' for triangular - of length n _ voices .
 If None , the individual shapes are chosen automatically .'''

implementation:
if not is_number ( gain_in ) or gain_in <= 0 or gain_in > 1 :
    raise ValueError ( "gain_in must be a number between 0 and 1." )
if not is_number ( gain_out ) or gain_out <= 0 or gain_out > 1 :
    raise ValueError ( "gain_out must be a number between 0 and 1." )
if not isinstance ( n_voices , int ) or n_voices <= 0 :
    raise ValueError ( "n_voices must be a positive integer." )
# validate delays
if not ( delays is None or isinstance ( delays , list ) ) :
    raise ValueError ( "delays must be a list or None" )
if delays is not None :
    if len ( delays ) != n_voices :
        raise ValueError ( "the length of delays must equal n_voices" )
    if any ( ( not is_number ( p ) or p < 20 ) for p in delays ) :
        raise ValueError ( "the elements of delays must be numbers > 20" )
else :
    delays = [ random . uniform ( 40 , 60 ) for _ in range ( n_voices ) ]
# validate decays
if not ( decays is None or isinstance ( decays , list ) ) :
    raise ValueError ( "decays must be a list or None" )
if decays is not None :
    if len ( decays ) != n_voices :
        raise ValueError ( "the length of decays must equal n_voices" )
    if any ( ( not is_number ( p ) or p <= 0 or p > 1 ) for p in decays ) :
        raise ValueError ( "the elements of decays must be between 0 and 1" )
else :
    decays = [ random . uniform ( 0.3 , 0.4 ) for _ in range ( n_voices ) ]
# validate speeds
if not ( speeds is None or isinstance ( speeds , list ) ) :
    raise ValueError ( "speeds must be a list or None" )
if speeds is not None :
    if len ( speeds ) != n_voices :
        raise ValueError ( "the length of speeds must equal n_voices" )
    if any ( ( not is_number ( p ) or p <= 0 ) for p in speeds ) :
        raise ValueError ( "the elements of speeds must be numbers > 0" )
else :
    speeds = [ random . uniform ( 0.25 , 0.4 ) for _ in range ( n_voices ) ]
# validate depths
if not ( depths is None or isinstance ( depths , list ) ) :
    raise ValueError ( "depths must be a list or None" )
if depths is not None :
    if len ( depths ) != n_voices :
        raise ValueError ( "the length of depths must equal n_voices" )
    if any ( ( not is_number ( p ) or p <= 0 ) for p in depths ) :
        raise ValueError ( "the elements of depths must be numbers > 0" )
else :
    depths = [ random . uniform ( 1.0 , 3.0 ) for _ in range ( n_voices ) ]
# validate shapes
if not ( shapes is None or isinstance ( shapes , list ) ) :
    raise ValueError ( "shapes must be a list or None" )
if shapes is not None :
    if len ( shapes ) != n_voices :
        raise ValueError ( "the length of shapes must equal n_voices" )
    if any ( ( p not in [ 't' , 's' ] ) for p in shapes ) :
        raise ValueError ( "the elements of shapes must be 's' or 't'" )
else :
    shapes = [ random . choice ( [ 't' , 's' ] ) for _ in range ( n_voices ) ]
effect_args = [ 'chorus' , '{}' . format ( gain_in ) , '{}' . format ( gain_out ) ]
for i in range ( n_voices ) :
    effect_args . extend ( [ '{:f}' . format ( delays [ i ] ) , '{:f}' . format ( decays [ i ] ) , '{:f}' . format ( speeds [ i ] ) , '{:f}' . format ( depths [ i ] ) , '-{}' . format ( shapes [ i ] ) ] )
self . effects . extend ( effect_args )
self . effects_log . append ( 'chorus' )
return self


signature:
def compand ( self , attack_time = 0.3 , decay_time = 0.8 , soft_knee_db = 6.0 , tf_points = [ ( - 70 , - 70 ) , ( - 60 , - 20 ) , ( 0 , 0 ) ] , ) :
    '''Compand ( compress or expand ) the dynamic range of the audio .
 Parameters
 attack _ time : float , default = 0.3
 The time in seconds over which the instantaneous level of the input
 signal is averaged to determine increases in volume .
 decay _ time : float , default = 0.8
 The time in seconds over which the instantaneous level of the input
 signal is averaged to determine decreases in volume .
 soft _ knee _ db : float or None , default = 6.0
 The ammount ( in dB ) for which the points at where adjacent line
 segments on the transfer function meet will be rounded .
 If None , no soft _ knee is applied .
 tf _ points : list of tuples
 Transfer function points as a list of tuples corresponding to
 points in ( dB , dB ) defining the compander ' s transfer function .
 See Also
 mcompand , contrast'''

implementation:
if not is_number ( attack_time ) or attack_time <= 0 :
    raise ValueError ( "attack_time must be a positive number." )
if not is_number ( decay_time ) or decay_time <= 0 :
    raise ValueError ( "decay_time must be a positive number." )
if attack_time > decay_time :
    logger . warning ( "attack_time is larger than decay_time.\n" "For most situations, attack_time should be shorter than " "decay time because the human ear is more sensitive to sudden " "loud music than sudden soft music." )
if not ( is_number ( soft_knee_db ) or soft_knee_db is None ) :
    raise ValueError ( "soft_knee_db must be a number or None." )
if not isinstance ( tf_points , list ) :
    raise TypeError ( "tf_points must be a list." )
if len ( tf_points ) == 0 :
    raise ValueError ( "tf_points must have at least one point." )
if any ( not isinstance ( pair , tuple ) for pair in tf_points ) :
    raise ValueError ( "elements of tf_points must be pairs" )
if any ( len ( pair ) != 2 for pair in tf_points ) :
    raise ValueError ( "Tuples in tf_points must be length 2" )
if any ( not ( is_number ( p [ 0 ] ) and is_number ( p [ 1 ] ) ) for p in tf_points ) :
    raise ValueError ( "Tuples in tf_points must be pairs of numbers." )
if any ( ( p [ 0 ] > 0 or p [ 1 ] > 0 ) for p in tf_points ) :
    raise ValueError ( "Tuple values in tf_points must be <= 0 (dB)." )
if len ( tf_points ) > len ( set ( [ p [ 0 ] for p in tf_points ] ) ) :
    raise ValueError ( "Found duplicate x-value in tf_points." )
tf_points = sorted ( tf_points , key = lambda tf_points : tf_points [ 0 ] )
transfer_list = [ ]
for point in tf_points :
    transfer_list . extend ( [ "{:f}" . format ( point [ 0 ] ) , "{:f}" . format ( point [ 1 ] ) ] )
effect_args = [ 'compand' , "{:f},{:f}" . format ( attack_time , decay_time ) ]
if soft_knee_db is not None :
    effect_args . append ( "{:f}:{}" . format ( soft_knee_db , "," . join ( transfer_list ) ) )
else :
    effect_args . append ( "," . join ( transfer_list ) )
self . effects . extend ( effect_args )
self . effects_log . append ( 'compand' )
return self


signature:
def contrast ( self , amount = 75 ) :
    '''Comparable with compression , this effect modifies an audio signal to
 make it sound louder .
 Parameters
 amount : float
 Amount of enhancement between 0 and 100.
 See Also
 compand , mcompand'''

implementation:
if not is_number ( amount ) or amount < 0 or amount > 100 :
    raise ValueError ( 'amount must be a number between 0 and 100.' )
effect_args = [ 'contrast' , '{:f}' . format ( amount ) ]
self . effects . extend ( effect_args )
self . effects_log . append ( 'contrast' )
return self


signature:
def convert ( self , samplerate = None , n_channels = None , bitdepth = None ) :
    '''Converts output audio to the specified format .
 Parameters
 samplerate : float , default = None
 Desired samplerate . If None , defaults to the same as input .
 n _ channels : int , default = None
 Desired number of channels . If None , defaults to the same as input .
 bitdepth : int , default = None
 Desired bitdepth . If None , defaults to the same as input .
 See Also
 rate'''

implementation:
bitdepths = [ 8 , 16 , 24 , 32 , 64 ]
if bitdepth is not None :
    if bitdepth not in bitdepths :
        raise ValueError ( "bitdepth must be one of {}." . format ( str ( bitdepths ) ) )
    self . output_format . extend ( [ '-b' , '{}' . format ( bitdepth ) ] )
if n_channels is not None :
    if not isinstance ( n_channels , int ) or n_channels <= 0 :
        raise ValueError ( "n_channels must be a positive integer." )
    self . output_format . extend ( [ '-c' , '{}' . format ( n_channels ) ] )
if samplerate is not None :
    if not is_number ( samplerate ) or samplerate <= 0 :
        raise ValueError ( "samplerate must be a positive number." )
    self . rate ( samplerate )
return self


signature:
def dcshift ( self , shift = 0.0 ) :
    '''Apply a DC shift to the audio .
 Parameters
 shift : float
 Amount to shift audio between - 2 and 2 . ( Audio is between - 1 and 1)
 See Also
 highpass'''

implementation:
if not is_number ( shift ) or shift < - 2 or shift > 2 :
    raise ValueError ( 'shift must be a number between -2 and 2.' )
effect_args = [ 'dcshift' , '{:f}' . format ( shift ) ]
self . effects . extend ( effect_args )
self . effects_log . append ( 'dcshift' )
return self