def make_script(python_script, target_path='', target_name='', user=False, make_link=False,
                force=False, remove=False, no_check_shebang=False, no_check_path=False):
    """v{VERSION}
    This script makes a command line script out of a python script.
    For example, 'clingon script.py' will copy or symlink script.py
    (without the .py extension) to:
    - <python-exe-path>/script (default),
    - <target-path>/script if --target-path is specfied,
    - ~/bin/script if --user is specified,
    and then set the copy / symlink as executable.
    See https://github.com/francois-vincent/clingon
    """
    if user and target_path:
        raise RunnerErrorWithUsage("You cannot specify --path and --user at the same time")
    source = os.path.abspath(python_script)
    dest_dir = os.path.normpath(os.path.expanduser('~/bin' if user else target_path or os.path.dirname(sys.executable)))
    target = os.path.join(dest_dir, target_name if target_name else os.path.splitext(os.path.basename(source))[0])
    target_exists = os.path.exists(target)
    if remove:
        if target_exists:
            os.unlink(target)
            print("Script '%s' removed" % target)
        else:
            print("Script '%s' not found, nothing to do" % target)
        return
    if not os.path.exists(source):
        raise RunnerError("Could not find source '%s', aborting" % source)
    if DEBUG:
        print('Source, target:', source, target)

    if target_exists:
        def same_file_same_type(source, target):
            if os.path.islink(target):
                return make_link and os.path.samefile(source, target)
            else:
                return not make_link and (open(source, 'rb').read() == open(target, 'rb').read())

        if same_file_same_type(source, target):
            print("Target '%s' already created, nothing to do" % target)
            return
        elif not force:
            raise RunnerError("Target '%s' already exists, aborting" % target)

    if not os.path.isdir(dest_dir):
        # Create directory
        try:
            os.makedirs(dest_dir)
        except OSError:
            raise RunnerError("Target folder '%s' does not exist, and cannot create it, aborting" % dest_dir)

    if not no_check_shebang:
        # Check that file starts with python shebang (#!/usr/bin/env python)
        first_line = open(source).readline()
        if not ('#!' in first_line and 'python' in first_line):
            raise RunnerError("Your script's first line should start with '#!' and contain 'python', aborting")

    # Now it's time to copy or symlink file
    if target_exists:
        os.unlink(target)
    import stat

    perms = stat.S_IXUSR | stat.S_IXGRP
    if os.getuid() == 0:
        perms |= stat.S_IXOTH
    if make_link:
        st = os.stat(source)
        if st.st_mode & perms != perms:
            os.chmod(source, st.st_mode | perms)
        os.symlink(source, target)
        st = os.stat(target)
        os.chmod(target, st.st_mode | perms)
        print('Script %s has been symlinked to %s' % (source, target))
    else:
        import shutil

        shutil.copyfile(source, target)
        st = os.stat(target)
        os.chmod(target, st.st_mode | perms)
        print('Script %s has been copied to %s' % (source, target))
        # check PATH and advise user to update it if relevant
    path_env = os.environ.get('PATH')
    if not no_check_path and (not path_env or dest_dir not in path_env):
        print("Please add your local bin path [%s] to your environment PATH" % dest_dir)
def make_script ( python_script , target_path = '' , target_name = '' , user = False , make_link = False , force = False , remove = False , no_check_shebang = False , no_check_path = False ) : if user and target_path : raise RunnerErrorWithUsage ( "You cannot specify --path and --user at the same time" ) source = os . path . abspath ( python_script ) dest_dir = os . path . normpath ( os . path . expanduser ( '~/bin' if user else target_path or os . path . dirname ( sys . executable ) ) ) target = os . path . join ( dest_dir , target_name if target_name else os . path . splitext ( os . path . basename ( source ) ) [ 0 ] ) target_exists = os . path . exists ( target ) if remove : if target_exists : os . unlink ( target ) print ( "Script '%s' removed" % target ) else : print ( "Script '%s' not found, nothing to do" % target ) return if not os . path . exists ( source ) : raise RunnerError ( "Could not find source '%s', aborting" % source ) if DEBUG : print ( 'Source, target:' , source , target ) if target_exists : def same_file_same_type ( source , target ) : if os . path . islink ( target ) : return make_link and os . path . samefile ( source , target ) else : return not make_link and ( open ( source , 'rb' ) . read ( ) == open ( target , 'rb' ) . read ( ) ) if same_file_same_type ( source , target ) : print ( "Target '%s' already created, nothing to do" % target ) return elif not force : raise RunnerError ( "Target '%s' already exists, aborting" % target ) if not os . path . isdir ( dest_dir ) : try : os . makedirs ( dest_dir ) except OSError : raise RunnerError ( "Target folder '%s' does not exist, and cannot create it, aborting" % dest_dir ) if not no_check_shebang : first_line = open ( source ) . readline ( ) if not ( '#!' in first_line and 'python' in first_line ) : raise RunnerError ( "Your script's first line should start with '#!' and contain 'python', aborting" ) if target_exists : os . unlink ( target ) import stat perms = stat . S_IXUSR | stat . S_IXGRP if os . getuid ( ) == 0 : perms |= stat . S_IXOTH if make_link : st = os . stat ( source ) if st . st_mode & perms != perms : os . chmod ( source , st . st_mode | perms ) os . symlink ( source , target ) st = os . stat ( target ) os . chmod ( target , st . st_mode | perms ) print ( 'Script %s has been symlinked to %s' % ( source , target ) ) else : import shutil shutil . copyfile ( source , target ) st = os . stat ( target ) os . chmod ( target , st . st_mode | perms ) print ( 'Script %s has been copied to %s' % ( source , target ) ) path_env = os . environ . get ( 'PATH' ) if not no_check_path and ( not path_env or dest_dir not in path_env ) : print ( "Please add your local bin path [%s] to your environment PATH" % dest_dir )
v{VERSION}
    This script makes a command line script out of a python script.
    For example, 'clingon script.py' will copy or symlink script.py
    (without the .py extension) to:
    - <python-exe-path>/script (default),
    - <target-path>/script if --target-path is specfied,
    - ~/bin/script if --user is specified,
    and then set the copy / symlink as executable.
    See https://github.com/francois-vincent/clingon