<commit_before>#!/usr/bin/env python

# # Docbuilder
# *Docbuilder is a small python script that will take another Python program, and turn it into documentation.*
# Docbuilder is a tool for developing *Literate Programs* with Python.
# A literate program combines both Markdown and a programming language. It is traditionally used for scientific purposes.
# ## Why Docbuilder?
# * No need to detangle programs before running them - Python reads the Docbuilder syntax fine. If your code is written correctly, it will run.
# * Generates Markdown instead of generating both Markdown and an executable file.
# * The options for Literate Programming under Python is few and far between.
# * Impressive compatibility. It doesn't really matter what version of Python you are running. Docbuilder will run.

# # Notes:
# * Docbuilder will not ask before clobbering your output file.
# * Docbuilder has no dependencies.
# * Docbuilder simply converts your comments and code into Markdown.
# * Docbuilder builds Markdown, and is mostly compatible with whatever [Python Markdown](https://pythonhosted.org/Markdown/) can read. But just in case, check the [Issues](https://github.com/shakna-israel/docbuilder/issues).

# # Dependencies:
# Used to read, write and check files.
import os
# Used so we can kill Docbuilder to make it behave.
import sys
# Used to handle command-line arguments.
import argparse

# # Metadata:
# These are used with setuptools and Pip to let people know what exactly they are installing.

__author__ = 'James Milne'
__version__ = '0.4-dev'
__license__ = 'MIT'
__description__ = 'Docbuilder allows you to build Markdown documents without the need for detangling executables from literate Python programs. http://docbuilder.rtfd.org'

# # String Manage:
# *stringManage* is one of the main functions of Docbuilder.
# It is in this function that each line of the Python Literate program is examined.
def stringManage(lineInFile):
    # verboseActive checks to see how talkative Docbuilder is expected to be.
    verboseActive = getFlags()[3]
    # We set up the line fed into stringManage as the unmodified *stringUnstripped* variable.
    stringUnstripped = lineInFile
    # We check if the line is a UNIX style *hash bang*, because we don't particularly want to see that in the documentation file.
    if stringUnstripped[:3] == "#!/":
        if verboseActive:
            print("Found hashbang! Ignoring.")
        # By setting *stringUnstripped* to *hashBang* it can be discarded later by another function.
        stringUnstripped = "hashBang"
    # If Docbuilder is talkative, it will tell the console exactly what the line it is examining looks like.
    if verboseActive:
        print("The current unstripped line is... " + stringUnstripped)
    # We strip the white space around the unmodified string, and name this new variable *stringStripped*.
    stringStripped = stringUnstripped.strip()
    # We fetch the first character of the string so we can compare it later.
    firstChar = stringStripped[:1]
    # If Docbuilder is talkative, it will tell us what the first character looks like.
    if verboseActive:
        print("The first character of the current line is..." + firstChar)
    # Then it will tell us what the whitespace stripped line looks like.
    if verboseActive:
        print("The current stripped line is... " + stringStripped)
    # Finally, we strip the first character from the line so we can examine it better, without having to strip the character away later.
    stringStripped = stringStripped[1:].strip()
    # If Docbuilder is talkative, it will tell us what that line looks like without the first character.
    if verboseActive:
        print("After first character stripping, the current unstripped line is..." + stringStripped)
    # Finally, we send the three variables, *stringUnstripped*, *stringStripped* and *firstChar* back to whatever function called *stringManage*.
    return (stringUnstripped, stringStripped, firstChar)

# # Check Export File
# This is a simple function, that gets given a file name, checks if it exists, and if so, clobbers it.
def checkExportFile(fileExists):
    clobberFile = getFlags()[4]
    if clobberFile:
        if os.path.isfile(fileExists):
            os.remove(fileExists)
    else:
        print("File " + fileExists + " exists. Not clobbering.")
        sys.exit(0)

# # Check Export Directory
# This is a naive function that gets given a directory path, checks if it exists, and if it doesn't, attempts to create it.
def checkExportDir(directory):
    if '/' in directory:
        previousFolder = False
        for folder in directory.split('/'):
            if not previousFolder:
                if folder != "":
                    if not os.path.exists(folder):
                        print(folder)
                        os.makedirs(folder)
                        previousFolder = folder
            else:
                if not os.path.exists(previousFolder + "/" + folder):
                    print(previousFolder + '/' + folder)
                    os.makedirs(previousFolder + "/" + folder)
                    previousFolder = previousFolder + "/" + folder
    if not os.path.exists(directory):
        os.makedirs(directory)

# # Unicode Compare Character
# This is a function that only exists due to the unicode differences between Python 2.8, 3.0, and 3.3.
# It checks the allowed functions are returns the correct unicode character for the code it was given.
def unicodeCompareChar(uniCode):
    try:
        compareChar = unichr(uniCode)
    except NameError:
        compareChar = chr(uniCode)
    return compareChar

# # Markdown Write
# This is a simple function, that is given both a line of Markdown to write, and a file to append to.
# It takes that file, and attempts to append it, ensuring aline break underneath each line for compatibility's sake.
def markdownWrite(stringLine, fileToWrite):
    verboseActive = getFlags()[3]
    if verboseActive:
        print("Attempting to open " + fileToWrite + " file to append...")
    outFile = open(fileToWrite, "a")
    outFile.write(stringLine + "\n\n")
    if verboseActive:
        print("Closing " + fileToWrite + " file.")
    outFile.close()

# # Codeblock Write
# This is a function that, when given a line and file to append to, attempts to turn that line into a Markdown codeblock.
def codeblockWrite(stringLine, fileToWrite):
    verboseActive = getFlags()[3]
    # Firstly, it checks if the line is simply *hashBang*, a line created by *stringManage*, and it is, refuses to write it.
    if stringLine != "hashBang":
        # It then proceeds to append to the given file, inside a Markdown codeblock.
        if verboseActive:
            print("Attempting to open " + fileToWrite + " file to append...")
        outFile = open(fileToWrite, "a")
        outFile.write("\n```\n" + stringLine + "\n```\n")
        if verboseActive:
            print("Closing " + fileToWrite + " file.")
        outFile.close()

# # Initiate File Out
# This is a simple function that attempts to create a file in a cross-platform friendly way, based on a file location itis given.
def initFileOut(outFile):
    verboseActive = getFlags()[3]
    if verboseActive:
        print("Attempting to create file... " + outFile + ".")
    initFile = open(outFile, "w+")
    if verboseActive:
        print("Closing new file... " + outFile + ".")
    initFile.close()

# # Read File
# *readFile* is function that attempts to read a Python Literate Program, and send each line it reads away to be parsed.
def readFile(inputFile):
    # Firstly, it checks to see what file the documentation is supposed to be getting written to.
    outFile = getFlags()[1]
    # It then opens the file given the path it has received, in read-only mode.
    inFile = open(inputFile, "r")
    # It asks (nicely) that the file being written to be created.
    initFileOut(outFile)
    # Check if we want Markdown Indented or not
    markdownIndent = getFlags()[5]
    # It then reads the file it was given, line by line.
    for lineRead in inFile.read().split("\n"):
        # For each line it reads, it asks *stringManage* to deal with.
        stringUnstripped = stringManage(lineRead)[0]
        stringStripped = stringManage(lineRead)[1]
        firstChar = stringManage(lineRead)[2]
        # It initiates the first-line comparator (#) so it can compare.
        compareChar = unicodeCompareChar(35)
        # If the first line is a hash, and not just *hashBang*, it asks *markdownWrite* to write some Markdown.
        if firstChar == compareChar:
            if stringUnstripped != "hashBang":
                if markdownIndent:
                    indentedString = stringUnstripped[2:]
                    markdownWrite(indentedString, outFile)
                else:
                    markdownWrite(stringStripped, outFile)
        else:
            # Otherwise, if the line isn't an empty line, it asks *codeBlockWrite* to write a Markdown codeblock.
            # The strip() statement is just to ensure there isn't any invisible indentation that might muck us around.
            if stringUnstripped.strip() != "":
                codeblockWrite(stringUnstripped, outFile)
    inFile.close()

# # Get Flags
# *getFlags* is the function that attempts to see what the user is asking of Docbuilder.
# It's also where we define the Public API.
# NOTE: All command-line arguments are *optional*.
def getFlags():
    # Initialise our parser for arguments.
    parser = argparse.ArgumentParser()
    # Create the parsing for the input file. (The file to build documentation from).
    parser.add_argument("-i", "--input", help="The input file. Normally, a *.pylit file.")
    # Create the parsing for the output file. (The file to build documentation for).
    parser.add_argument("-o", "--output", help="The output file name, without file extension.")
    # Create the parsing for verbose arguments.
    parser.add_argument("-v", "--verbose", help="Print more information to the console", action="store_true")
    # Create the parsing for the output directory.
    parser.add_argument("-d", "--directory", help="Set the output directory.")
    # Create the parsing for Markdown Indentation.
    parser.add_argument("--indent", help="Indent Markdown", action="store_true")
    # Create the parsing for file clobbering politeness.
    parser.add_argument("-q", "--quiet", help="Clobber existing files without asking.", action="store_true")
    # Simplify parsing the arguments.
    cliArgs = parser.parse_args()
    # Work out the filepath of the file Docbuilder is building documentation for.
    if cliArgs.input:
        inFile = cliArgs.input
    # If the user didn't specify a file, assume they're build Docbuilder's own documentation.
    else:
        inFile = "docbuilder.py"
    # Set whether verbose is turned on or not:
    if cliArgs.verbose:
        verboseActive = True
    # If the user didn't ask for verbose, set Docbuilder to not be verbose.
    else:
        verboseActive = False
    # Set what directory Docbuilder will build to:
    if cliArgs.directory:
        outDir = cliArgs.directory + "/"
        # If the output directory doesn't exist, ask Docbuilder to create it.
        checkExportDir(outDir)
    # If the user didn't specify a directory, assume they want the *docs* directory.
    else:
        outDir = "docs" + "/"
    # Set the output file path.
    if cliArgs.output:
        outFile = outDir + cliArgs.output + ".md"
    else:
        # If the user specified an input file, try and magic up a name.
        if cliArgs.input:
            outFile = outDir + cliArgs.input + ".md"
        # If the user didn't specify an input file either, build for Docbuilder.
        else:
            outFile = outDir + "docbuilder.md"
    # Set Docbuilder's politeness when clobbering files.
    if cliArgs.quiet:
        clobberFile = True
    else:
        clobberFile = False
    if cliArgs.indent:
        markdownIndent = True
    else:
        markdownIndent = False
    # Return the found values.
    return (inFile, outFile, outDir, verboseActive, clobberFile, markdownIndent)

# # Main
# This is the main function that sets Docbuilder running.
def main():
    # The *main* function asks *getFlags* what file the user is generating documentation for.
    inFile = getFlags()[0]
    # The *main* function asks *getFlags* what file the user is generating documentation to.
    outFile = getFlags()[1]
    # The main function checks if the output file pre-exists.
    checkExportFile(outFile)
    # It then tells *readFile* what file it is building documentation for.
    readFile(inFile)

# # If Name
# This is a simple function that tells Python what the main function is.
if __name__ == '__main__':
    main()
<commit_msg>Fixed noClobber mode.<commit_after>#!/usr/bin/env python

# # Docbuilder
# *Docbuilder is a small python script that will take another Python program, and turn it into documentation.*
# Docbuilder is a tool for developing *Literate Programs* with Python.
# A literate program combines both Markdown and a programming language. It is traditionally used for scientific purposes.
# ## Why Docbuilder?
# * No need to detangle programs before running them - Python reads the Docbuilder syntax fine. If your code is written correctly, it will run.
# * Generates Markdown instead of generating both Markdown and an executable file.
# * The options for Literate Programming under Python is few and far between.
# * Impressive compatibility. It doesn't really matter what version of Python you are running. Docbuilder will run.

# # Notes:
# * Docbuilder will not ask before clobbering your output file.
# * Docbuilder has no dependencies.
# * Docbuilder simply converts your comments and code into Markdown.
# * Docbuilder builds Markdown, and is mostly compatible with whatever [Python Markdown](https://pythonhosted.org/Markdown/) can read. But just in case, check the [Issues](https://github.com/shakna-israel/docbuilder/issues).

# # Dependencies:
# Used to read, write and check files.
import os
# Used so we can kill Docbuilder to make it behave.
import sys
# Used to handle command-line arguments.
import argparse

# # Metadata:
# These are used with setuptools and Pip to let people know what exactly they are installing.

__author__ = 'James Milne'
__version__ = '0.4-dev'
__license__ = 'MIT'
__description__ = 'Docbuilder allows you to build Markdown documents without the need for detangling executables from literate Python programs. http://docbuilder.rtfd.org'

# # String Manage:
# *stringManage* is one of the main functions of Docbuilder.
# It is in this function that each line of the Python Literate program is examined.
def stringManage(lineInFile):
    # verboseActive checks to see how talkative Docbuilder is expected to be.
    verboseActive = getFlags()[3]
    # We set up the line fed into stringManage as the unmodified *stringUnstripped* variable.
    stringUnstripped = lineInFile
    # We check if the line is a UNIX style *hash bang*, because we don't particularly want to see that in the documentation file.
    if stringUnstripped[:3] == "#!/":
        if verboseActive:
            print("Found hashbang! Ignoring.")
        # By setting *stringUnstripped* to *hashBang* it can be discarded later by another function.
        stringUnstripped = "hashBang"
    # If Docbuilder is talkative, it will tell the console exactly what the line it is examining looks like.
    if verboseActive:
        print("The current unstripped line is... " + stringUnstripped)
    # We strip the white space around the unmodified string, and name this new variable *stringStripped*.
    stringStripped = stringUnstripped.strip()
    # We fetch the first character of the string so we can compare it later.
    firstChar = stringStripped[:1]
    # If Docbuilder is talkative, it will tell us what the first character looks like.
    if verboseActive:
        print("The first character of the current line is..." + firstChar)
    # Then it will tell us what the whitespace stripped line looks like.
    if verboseActive:
        print("The current stripped line is... " + stringStripped)
    # Finally, we strip the first character from the line so we can examine it better, without having to strip the character away later.
    stringStripped = stringStripped[1:].strip()
    # If Docbuilder is talkative, it will tell us what that line looks like without the first character.
    if verboseActive:
        print("After first character stripping, the current unstripped line is..." + stringStripped)
    # Finally, we send the three variables, *stringUnstripped*, *stringStripped* and *firstChar* back to whatever function called *stringManage*.
    return (stringUnstripped, stringStripped, firstChar)

# # Check Export File
# This is a simple function, that gets given a file name, checks if it exists, and if so, clobbers it.
def checkExportFile(fileExists):
    clobberFile = getFlags()[4]
    if clobberFile:
        if os.path.isfile(fileExists):
            os.remove(fileExists)
    else:
        if os.path.isfile(fileExists):
            print("File " + fileExists + " exists. Not clobbering.")
            sys.exit(0)

# # Check Export Directory
# This is a naive function that gets given a directory path, checks if it exists, and if it doesn't, attempts to create it.
def checkExportDir(directory):
    if '/' in directory:
        previousFolder = False
        for folder in directory.split('/'):
            if not previousFolder:
                if folder != "":
                    if not os.path.exists(folder):
                        print(folder)
                        os.makedirs(folder)
                        previousFolder = folder
            else:
                if not os.path.exists(previousFolder + "/" + folder):
                    print(previousFolder + '/' + folder)
                    os.makedirs(previousFolder + "/" + folder)
                    previousFolder = previousFolder + "/" + folder
    if not os.path.exists(directory):
        os.makedirs(directory)

# # Unicode Compare Character
# This is a function that only exists due to the unicode differences between Python 2.8, 3.0, and 3.3.
# It checks the allowed functions are returns the correct unicode character for the code it was given.
def unicodeCompareChar(uniCode):
    try:
        compareChar = unichr(uniCode)
    except NameError:
        compareChar = chr(uniCode)
    return compareChar

# # Markdown Write
# This is a simple function, that is given both a line of Markdown to write, and a file to append to.
# It takes that file, and attempts to append it, ensuring aline break underneath each line for compatibility's sake.
def markdownWrite(stringLine, fileToWrite):
    verboseActive = getFlags()[3]
    if verboseActive:
        print("Attempting to open " + fileToWrite + " file to append...")
    outFile = open(fileToWrite, "a")
    outFile.write(stringLine + "\n\n")
    if verboseActive:
        print("Closing " + fileToWrite + " file.")
    outFile.close()

# # Codeblock Write
# This is a function that, when given a line and file to append to, attempts to turn that line into a Markdown codeblock.
def codeblockWrite(stringLine, fileToWrite):
    verboseActive = getFlags()[3]
    # Firstly, it checks if the line is simply *hashBang*, a line created by *stringManage*, and it is, refuses to write it.
    if stringLine != "hashBang":
        # It then proceeds to append to the given file, inside a Markdown codeblock.
        if verboseActive:
            print("Attempting to open " + fileToWrite + " file to append...")
        outFile = open(fileToWrite, "a")
        outFile.write("\n```\n" + stringLine + "\n```\n")
        if verboseActive:
            print("Closing " + fileToWrite + " file.")
        outFile.close()

# # Initiate File Out
# This is a simple function that attempts to create a file in a cross-platform friendly way, based on a file location itis given.
def initFileOut(outFile):
    verboseActive = getFlags()[3]
    if verboseActive:
        print("Attempting to create file... " + outFile + ".")
    initFile = open(outFile, "w+")
    if verboseActive:
        print("Closing new file... " + outFile + ".")
    initFile.close()

# # Read File
# *readFile* is function that attempts to read a Python Literate Program, and send each line it reads away to be parsed.
def readFile(inputFile):
    # Firstly, it checks to see what file the documentation is supposed to be getting written to.
    outFile = getFlags()[1]
    # It then opens the file given the path it has received, in read-only mode.
    inFile = open(inputFile, "r")
    # It asks (nicely) that the file being written to be created.
    initFileOut(outFile)
    # Check if we want Markdown Indented or not
    markdownIndent = getFlags()[5]
    # It then reads the file it was given, line by line.
    for lineRead in inFile.read().split("\n"):
        # For each line it reads, it asks *stringManage* to deal with.
        stringUnstripped = stringManage(lineRead)[0]
        stringStripped = stringManage(lineRead)[1]
        firstChar = stringManage(lineRead)[2]
        # It initiates the first-line comparator (#) so it can compare.
        compareChar = unicodeCompareChar(35)
        # If the first line is a hash, and not just *hashBang*, it asks *markdownWrite* to write some Markdown.
        if firstChar == compareChar:
            if stringUnstripped != "hashBang":
                if markdownIndent:
                    indentedString = stringUnstripped[2:]
                    markdownWrite(indentedString, outFile)
                else:
                    markdownWrite(stringStripped, outFile)
        else:
            # Otherwise, if the line isn't an empty line, it asks *codeBlockWrite* to write a Markdown codeblock.
            # The strip() statement is just to ensure there isn't any invisible indentation that might muck us around.
            if stringUnstripped.strip() != "":
                codeblockWrite(stringUnstripped, outFile)
    inFile.close()

# # Get Flags
# *getFlags* is the function that attempts to see what the user is asking of Docbuilder.
# It's also where we define the Public API.
# NOTE: All command-line arguments are *optional*.
def getFlags():
    # Initialise our parser for arguments.
    parser = argparse.ArgumentParser()
    # Create the parsing for the input file. (The file to build documentation from).
    parser.add_argument("-i", "--input", help="The input file. Normally, a *.pylit file.")
    # Create the parsing for the output file. (The file to build documentation for).
    parser.add_argument("-o", "--output", help="The output file name, without file extension.")
    # Create the parsing for verbose arguments.
    parser.add_argument("-v", "--verbose", help="Print more information to the console", action="store_true")
    # Create the parsing for the output directory.
    parser.add_argument("-d", "--directory", help="Set the output directory.")
    # Create the parsing for Markdown Indentation.
    parser.add_argument("--indent", help="Indent Markdown", action="store_true")
    # Create the parsing for file clobbering politeness.
    parser.add_argument("-q", "--quiet", help="Clobber existing files without asking.", action="store_true")
    # Simplify parsing the arguments.
    cliArgs = parser.parse_args()
    # Work out the filepath of the file Docbuilder is building documentation for.
    if cliArgs.input:
        inFile = cliArgs.input
    # If the user didn't specify a file, assume they're build Docbuilder's own documentation.
    else:
        inFile = "docbuilder.py"
    # Set whether verbose is turned on or not:
    if cliArgs.verbose:
        verboseActive = True
    # If the user didn't ask for verbose, set Docbuilder to not be verbose.
    else:
        verboseActive = False
    # Set what directory Docbuilder will build to:
    if cliArgs.directory:
        outDir = cliArgs.directory + "/"
        # If the output directory doesn't exist, ask Docbuilder to create it.
        checkExportDir(outDir)
    # If the user didn't specify a directory, assume they want the *docs* directory.
    else:
        outDir = "docs" + "/"
    # Set the output file path.
    if cliArgs.output:
        outFile = outDir + cliArgs.output + ".md"
    else:
        # If the user specified an input file, try and magic up a name.
        if cliArgs.input:
            outFile = outDir + cliArgs.input + ".md"
        # If the user didn't specify an input file either, build for Docbuilder.
        else:
            outFile = outDir + "docbuilder.md"
    # Set Docbuilder's politeness when clobbering files.
    if cliArgs.quiet:
        clobberFile = True
    else:
        clobberFile = False
    if cliArgs.indent:
        markdownIndent = True
    else:
        markdownIndent = False
    # Return the found values.
    return (inFile, outFile, outDir, verboseActive, clobberFile, markdownIndent)

# # Main
# This is the main function that sets Docbuilder running.
def main():
    # The *main* function asks *getFlags* what file the user is generating documentation for.
    inFile = getFlags()[0]
    # The *main* function asks *getFlags* what file the user is generating documentation to.
    outFile = getFlags()[1]
    # The main function checks if the output file pre-exists.
    checkExportFile(outFile)
    # It then tells *readFile* what file it is building documentation for.
    readFile(inFile)

# # If Name
# This is a simple function that tells Python what the main function is.
if __name__ == '__main__':
    main()
<|endoftext|>


<commit_before>import os
import shutil
import subprocess
import sys
import random
import threading
import json
import time
import traceback

USER_HOME_DIR = '~'
HOME_DIR = '~/Docker'
PULSE_COOKIE_PATH = '~/.config/pulse/cookie'
TMP_DIR = '/tmp'
ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
PULSE_SERVER = 'tcp:172.17.0.1:4713'

# Init
USER_HOME_DIR = os.path.expanduser(USER_HOME_DIR)
HOME_DIR = os.path.expanduser(HOME_DIR)
PULSE_COOKIE_PATH = os.path.expanduser(PULSE_COOKIE_PATH)
TMP_DIR = os.path.expanduser(TMP_DIR)
CONF_DIR = os.path.join(HOME_DIR, '.config')
BASE_CONF_PATH = os.path.join(CONF_DIR, 'base.json')

def mkdirs(path):
    if not os.path.exists(path):
        os.makedirs(path)

mkdirs(CONF_DIR)

if not os.path.exists(BASE_CONF_PATH):
    shutil.copyfile(
        os.path.join(ROOT_DIR, 'apps', 'base', 'settings.json'),
        BASE_CONF_PATH
    )

conf_data = {}
with open(BASE_CONF_PATH, 'r') as conf_file:
    conf_data = json.loads(conf_file.read())

SUDO_DOCKER = conf_data.get('sudo_docker', False)
SHARE_CLIPBOARD = conf_data.get('share_clipboard', False)
SHARE_FONTS = conf_data.get('share_fonts', False)
SHARE_THEMES = conf_data.get('share_themes', False)
SHARE_ICONS = conf_data.get('share_icons', False)
SHARE_USER_FONTS = conf_data.get('share_user_fonfs', False)
SHARE_USER_THEMES = conf_data.get('share_user_themes', False)
DEBUG = conf_data.get('debug', False)

GPU = conf_data.get('gpu', 'auto')
if GPU == 'auto':
    try:
        subprocess.check_output(['which', 'nvidia-settings'])
        GPU = 'nvidia'
    except:
        GPU = 'intel'

DEFAULT_WIN_SIZE = conf_data.get('default_win_size', '1024x768')
DEFAULT_VOLUMES = conf_data.get('default_volumes', [])

def pull():
    subprocess.check_call((['sudo'] if SUDO_DOCKER else []) + [
        'docker',
        'pull',
        'pritunl/archlinux',
    ])

def build(app):
    app = app.split('#')[0]

    if app == 'base-intel' or app == 'base-nvidia':
        image_name = 'base-xorg'
    else:
        image_name = app

    app_dir = os.path.join(ROOT_DIR, 'apps', app)

    subprocess.check_call((['sudo'] if SUDO_DOCKER else []) + [
        'docker',
        'build',
        '--rm',
        '-t', 'dockercask/' + image_name,
        '.',
    ], cwd=app_dir)

    if app == 'base':
        build('base-' + GPU)

def build_all():
    build('base')
    for app in os.listdir(HOME_DIR):
        if not os.path.isdir(os.path.join(HOME_DIR, app)) or \
                app.startswith('.'):
            continue
        build(app)

def add(app):
    app_dir = os.path.join(HOME_DIR, app)
    app_conf_path = os.path.join(CONF_DIR, app + '.json')

    mkdirs(app_dir)

    if not os.path.exists(app_conf_path):
        shutil.copyfile(
            os.path.join(ROOT_DIR, 'apps', app.split('#')[0], 'settings.json'),
            app_conf_path,
        )

def run(app):
    app_dir = os.path.join(HOME_DIR, app)
    app_conf_path = os.path.join(CONF_DIR, app + '.json')
    fonts_dir = os.path.join(USER_HOME_DIR, '.fonts')
    themes_dir = os.path.join(USER_HOME_DIR, '.themes')
    cmd = []
    args = []
    volume_args = []

    if not os.path.exists(app_dir):
        print 'App must be added before running'
        exit(1)

    if DEBUG:
        args.append('-it')
        cmd.append('/bin/bash')

    downloads_dir = os.path.join(USER_HOME_DIR, 'Downloads')

    for src, dest in DEFAULT_VOLUMES:
        volume_args += [
            '-v', '%s:%s' % (os.path.expanduser(src), dest),
        ]

    if SHARE_FONTS:
        volume_args += [
            '-v', '%s:%s' % ('/usr/share/fonts', '/usr/share/fonts:ro'),
        ]

    if SHARE_ICONS:
        volume_args += [
            '-v', '%s:%s' % ('/usr/share/icons', '/usr/share/icons:ro'),
        ]

    if SHARE_THEMES:
        volume_args += [
            '-v', '%s:%s' % ('/usr/share/themes', '/usr/share/themes:ro'),
        ]

    if SHARE_USER_FONTS:
        volume_args += [
            '-v', '%s:%s' % (fonts_dir, '/home/docker/.fonts:ro'),
        ]

    if SHARE_USER_THEMES:
        volume_args += [
            '-v', '%s:%s' % (themes_dir, '/home/docker/.themes:ro'),
        ]

    mkdirs(fonts_dir)
    mkdirs(themes_dir)

    x_cookie = subprocess.check_output(['mcookie'])
    x_num = str(random.randint(1000, 32000))
    x_auth_path = os.path.join(TMP_DIR, '.X11-docker-' + x_num)
    x_screen_path = os.path.join(TMP_DIR, '.X11-unix', 'X' + x_num)

    with open(x_auth_path, 'w') as _:
        pass

    subprocess.check_call([
        'xauth',
        '-f', x_auth_path,
        'add',
        ':' + x_num,
        'MIT-MAGIC-COOKIE-1',
        x_cookie,
    ])

    subprocess.check_call([
        'xauth',
        'add',
        ':' + x_num,
        'MIT-MAGIC-COOKIE-1',
        x_cookie,
    ])

    x_proc = None
    docker_proc = None

    def clean_up():
        try:
            if docker_proc:
                docker_proc.kill()
        except:
            pass
        try:
            if x_proc:
                x_proc.kill()
        except:
            pass
        try:
            os.remove(x_auth_path)
        except:
            pass
        try:
            subprocess.check_output([
                'xauth',
                'remove',
                ':' + x_num,
            ])
        except:
            pass

    x_proc = subprocess.Popen([
        'Xephyr',
        '-auth', x_auth_path,
        '-screen', DEFAULT_WIN_SIZE,
        '-title', app,
        '-br',
        '-resizeable',
        '-nolisten', 'tcp',
        ':' + x_num,
    ])

    def thread_func():
        x_proc.wait()
        clean_up()

    thread = threading.Thread(target=thread_func)
    thread.daemon = True
    thread.start()

    docker_proc = subprocess.Popen((['sudo'] if SUDO_DOCKER else []) + [
        'docker',
        'run',
        '--rm',
    ] + args + [
        '-v', '%s:%s' % (x_screen_path, x_screen_path),
        '-v', '%s:%s' % (PULSE_COOKIE_PATH, '/tmp/.pulse-cookie'),
        '-v', '%s:%s' % (BASE_CONF_PATH, '/base.json:ro'),
        '-v', '%s:%s' % (app_conf_path, '/app.json:ro'),
        '-v', '%s:%s' % (app_dir, '/home/docker/Docker'),
    ] + volume_args + [
        '-e', 'DISPLAY=:' + x_num,
        '-e', 'XAUTHORITY=/tmp/.Xauth',
        '-e', 'XCOOKIE=' + x_cookie,
        '-e', 'PULSE_SERVER=' + PULSE_SERVER,
        'dockercask/' + app.split('#')[0],
    ] + cmd)

    if SHARE_CLIPBOARD:
        thread = threading.Thread(target=share_clipboard, args=(x_num,))
        thread.daemon = True
        thread.start()

    docker_proc.wait()
    clean_up()

def set_clipboard(num, val):
    proc = subprocess.Popen(
        ['xsel', '--display', ':' + num, '-b', '-i'],
        stdin=subprocess.PIPE,
    )
    proc.communicate(input=val)
    proc.wait()

def get_clipboard(num):
    return subprocess.check_output(
        ['xsel', '--display', ':' + num, '-b', '-o'],
    )

def share_clipboard(app_num):
    time.sleep(1)

    val = get_clipboard('0')
    set_clipboard(app_num,val )
    clipboards = [val, get_clipboard(app_num)]
    clipboard = None

    while True:
        try:
            for num in ('0', app_num):
                val = get_clipboard(num)
                i = 0 if num == '0' else 1
                if val != clipboards[i] and val != clipboard:
                    clipboard = val
                    clipboards[i] = val
                    new_num = app_num if num == '0' else '0'
                    set_clipboard(new_num, val)
            time.sleep(0.1)
        except:
            traceback.print_stack()
            time.sleep(5)

command = sys.argv[1]

if command == 'build':
    app = sys.argv[2]
    build(app)

elif command == 'build-all':
    build_all()

elif command == 'update':
    pull()
    build_all()

elif command == 'add':
    app = sys.argv[2]
    add(app)

elif command == 'run':
    app = sys.argv[2]
    run(app)

else:
    app = sys.argv[1]
    run(app)
<commit_msg>Hide stderr in nvidia check<commit_after>import os
import shutil
import subprocess
import sys
import random
import threading
import json
import time
import traceback

USER_HOME_DIR = '~'
HOME_DIR = '~/Docker'
PULSE_COOKIE_PATH = '~/.config/pulse/cookie'
TMP_DIR = '/tmp'
ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
PULSE_SERVER = 'tcp:172.17.0.1:4713'

# Init
USER_HOME_DIR = os.path.expanduser(USER_HOME_DIR)
HOME_DIR = os.path.expanduser(HOME_DIR)
PULSE_COOKIE_PATH = os.path.expanduser(PULSE_COOKIE_PATH)
TMP_DIR = os.path.expanduser(TMP_DIR)
CONF_DIR = os.path.join(HOME_DIR, '.config')
BASE_CONF_PATH = os.path.join(CONF_DIR, 'base.json')

def mkdirs(path):
    if not os.path.exists(path):
        os.makedirs(path)

mkdirs(CONF_DIR)

if not os.path.exists(BASE_CONF_PATH):
    shutil.copyfile(
        os.path.join(ROOT_DIR, 'apps', 'base', 'settings.json'),
        BASE_CONF_PATH
    )

conf_data = {}
with open(BASE_CONF_PATH, 'r') as conf_file:
    conf_data = json.loads(conf_file.read())

SUDO_DOCKER = conf_data.get('sudo_docker', False)
SHARE_CLIPBOARD = conf_data.get('share_clipboard', False)
SHARE_FONTS = conf_data.get('share_fonts', False)
SHARE_THEMES = conf_data.get('share_themes', False)
SHARE_ICONS = conf_data.get('share_icons', False)
SHARE_USER_FONTS = conf_data.get('share_user_fonfs', False)
SHARE_USER_THEMES = conf_data.get('share_user_themes', False)
DEBUG = conf_data.get('debug', False)

GPU = conf_data.get('gpu', 'auto')
if GPU == 'auto':
    try:
        subprocess.check_output(['which', 'nvidia-settings'],
            stderr=subprocess.PIPE)
        GPU = 'nvidia'
    except:
        GPU = 'intel'

DEFAULT_WIN_SIZE = conf_data.get('default_win_size', '1024x768')
DEFAULT_VOLUMES = conf_data.get('default_volumes', [])

def pull():
    subprocess.check_call((['sudo'] if SUDO_DOCKER else []) + [
        'docker',
        'pull',
        'pritunl/archlinux',
    ])

def build(app):
    app = app.split('#')[0]

    if app == 'base-intel' or app == 'base-nvidia':
        image_name = 'base-xorg'
    else:
        image_name = app

    app_dir = os.path.join(ROOT_DIR, 'apps', app)

    subprocess.check_call((['sudo'] if SUDO_DOCKER else []) + [
        'docker',
        'build',
        '--rm',
        '-t', 'dockercask/' + image_name,
        '.',
    ], cwd=app_dir)

    if app == 'base':
        build('base-' + GPU)

def build_all():
    build('base')
    for app in os.listdir(HOME_DIR):
        if not os.path.isdir(os.path.join(HOME_DIR, app)) or \
                app.startswith('.'):
            continue
        build(app)

def add(app):
    app_dir = os.path.join(HOME_DIR, app)
    app_conf_path = os.path.join(CONF_DIR, app + '.json')

    mkdirs(app_dir)

    if not os.path.exists(app_conf_path):
        shutil.copyfile(
            os.path.join(ROOT_DIR, 'apps', app.split('#')[0], 'settings.json'),
            app_conf_path,
        )

def run(app):
    app_dir = os.path.join(HOME_DIR, app)
    app_conf_path = os.path.join(CONF_DIR, app + '.json')
    fonts_dir = os.path.join(USER_HOME_DIR, '.fonts')
    themes_dir = os.path.join(USER_HOME_DIR, '.themes')
    cmd = []
    args = []
    volume_args = []

    if not os.path.exists(app_dir):
        print 'App must be added before running'
        exit(1)

    if DEBUG:
        args.append('-it')
        cmd.append('/bin/bash')

    downloads_dir = os.path.join(USER_HOME_DIR, 'Downloads')

    for src, dest in DEFAULT_VOLUMES:
        volume_args += [
            '-v', '%s:%s' % (os.path.expanduser(src), dest),
        ]

    if SHARE_FONTS:
        volume_args += [
            '-v', '%s:%s' % ('/usr/share/fonts', '/usr/share/fonts:ro'),
        ]

    if SHARE_ICONS:
        volume_args += [
            '-v', '%s:%s' % ('/usr/share/icons', '/usr/share/icons:ro'),
        ]

    if SHARE_THEMES:
        volume_args += [
            '-v', '%s:%s' % ('/usr/share/themes', '/usr/share/themes:ro'),
        ]

    if SHARE_USER_FONTS:
        volume_args += [
            '-v', '%s:%s' % (fonts_dir, '/home/docker/.fonts:ro'),
        ]

    if SHARE_USER_THEMES:
        volume_args += [
            '-v', '%s:%s' % (themes_dir, '/home/docker/.themes:ro'),
        ]

    mkdirs(fonts_dir)
    mkdirs(themes_dir)

    x_cookie = subprocess.check_output(['mcookie'])
    x_num = str(random.randint(1000, 32000))
    x_auth_path = os.path.join(TMP_DIR, '.X11-docker-' + x_num)
    x_screen_path = os.path.join(TMP_DIR, '.X11-unix', 'X' + x_num)

    with open(x_auth_path, 'w') as _:
        pass

    subprocess.check_call([
        'xauth',
        '-f', x_auth_path,
        'add',
        ':' + x_num,
        'MIT-MAGIC-COOKIE-1',
        x_cookie,
    ])

    subprocess.check_call([
        'xauth',
        'add',
        ':' + x_num,
        'MIT-MAGIC-COOKIE-1',
        x_cookie,
    ])

    x_proc = None
    docker_proc = None

    def clean_up():
        try:
            if docker_proc:
                docker_proc.kill()
        except:
            pass
        try:
            if x_proc:
                x_proc.kill()
        except:
            pass
        try:
            os.remove(x_auth_path)
        except:
            pass
        try:
            subprocess.check_output([
                'xauth',
                'remove',
                ':' + x_num,
            ])
        except:
            pass

    x_proc = subprocess.Popen([
        'Xephyr',
        '-auth', x_auth_path,
        '-screen', DEFAULT_WIN_SIZE,
        '-title', app,
        '-br',
        '-resizeable',
        '-nolisten', 'tcp',
        ':' + x_num,
    ])

    def thread_func():
        x_proc.wait()
        clean_up()

    thread = threading.Thread(target=thread_func)
    thread.daemon = True
    thread.start()

    docker_proc = subprocess.Popen((['sudo'] if SUDO_DOCKER else []) + [
        'docker',
        'run',
        '--rm',
    ] + args + [
        '-v', '%s:%s' % (x_screen_path, x_screen_path),
        '-v', '%s:%s' % (PULSE_COOKIE_PATH, '/tmp/.pulse-cookie'),
        '-v', '%s:%s' % (BASE_CONF_PATH, '/base.json:ro'),
        '-v', '%s:%s' % (app_conf_path, '/app.json:ro'),
        '-v', '%s:%s' % (app_dir, '/home/docker/Docker'),
    ] + volume_args + [
        '-e', 'DISPLAY=:' + x_num,
        '-e', 'XAUTHORITY=/tmp/.Xauth',
        '-e', 'XCOOKIE=' + x_cookie,
        '-e', 'PULSE_SERVER=' + PULSE_SERVER,
        'dockercask/' + app.split('#')[0],
    ] + cmd)

    if SHARE_CLIPBOARD:
        thread = threading.Thread(target=share_clipboard, args=(x_num,))
        thread.daemon = True
        thread.start()

    docker_proc.wait()
    clean_up()

def set_clipboard(num, val):
    proc = subprocess.Popen(
        ['xsel', '--display', ':' + num, '-b', '-i'],
        stdin=subprocess.PIPE,
    )
    proc.communicate(input=val)
    proc.wait()

def get_clipboard(num):
    return subprocess.check_output(
        ['xsel', '--display', ':' + num, '-b', '-o'],
    )

def share_clipboard(app_num):
    time.sleep(1)

    val = get_clipboard('0')
    set_clipboard(app_num,val )
    clipboards = [val, get_clipboard(app_num)]
    clipboard = None

    while True:
        try:
            for num in ('0', app_num):
                val = get_clipboard(num)
                i = 0 if num == '0' else 1
                if val != clipboards[i] and val != clipboard:
                    clipboard = val
                    clipboards[i] = val
                    new_num = app_num if num == '0' else '0'
                    set_clipboard(new_num, val)
            time.sleep(0.1)
        except:
            traceback.print_stack()
            time.sleep(5)

command = sys.argv[1]

if command == 'build':
    app = sys.argv[2]
    build(app)

elif command == 'build-all':
    build_all()

elif command == 'update':
    pull()
    build_all()

elif command == 'add':
    app = sys.argv[2]
    add(app)

elif command == 'run':
    app = sys.argv[2]
    run(app)

else:
    app = sys.argv[1]
    run(app)
<|endoftext|>


<commit_before>from django import forms
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.cache import cache
from django.core.cache.utils import make_template_fragment_key
from django.core.exceptions import PermissionDenied
from django.db import transaction
from django.db.models import Count, Q
from django.forms import Form, modelformset_factory
from django.http import Http404, HttpResponsePermanentRedirect, HttpResponseRedirect
from django.urls import reverse
from django.utils.translation import gettext as _, gettext_lazy, ungettext
from django.views.generic import DetailView, FormView, ListView, UpdateView, View
from django.views.generic.detail import SingleObjectMixin, SingleObjectTemplateResponseMixin
from reversion import revisions

from judge.forms import EditOrganizationForm
from judge.models import Organization, OrganizationRequest, Profile
from judge.utils.ranker import ranker
from judge.utils.views import TitleMixin, generic_message

__all__ = ['OrganizationList', 'OrganizationHome', 'OrganizationUsers', 'OrganizationMembershipChange',
           'JoinOrganization', 'LeaveOrganization', 'EditOrganization', 'RequestJoinOrganization',
           'OrganizationRequestDetail', 'OrganizationRequestView', 'OrganizationRequestLog',
           'KickUserWidgetView']

class OrganizationMixin(object):
    context_object_name = 'organization'
    model = Organization

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['logo_override_image'] = self.object.logo_override_image
        return context

    def dispatch(self, request, *args, **kwargs):
        try:
            return super(OrganizationMixin, self).dispatch(request, *args, **kwargs)
        except Http404:
            key = kwargs.get(self.slug_url_kwarg, None)
            if key:
                return generic_message(request, _('No such organization'),
                                       _('Could not find an organization with the key "%s".') % key)
            else:
                return generic_message(request, _('No such organization'),
                                       _('Could not find such organization.'))

    def can_edit_organization(self, org=None):
        if org is None:
            org = self.object
        if not self.request.user.is_authenticated:
            return False
        profile_id = self.request.profile.id
        return org.admins.filter(id=profile_id).exists() or org.registrant_id == profile_id

class OrganizationDetailView(OrganizationMixin, DetailView):
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        if self.object.slug != kwargs['slug']:
            return HttpResponsePermanentRedirect(request.get_full_path().replace(kwargs['slug'], self.object.slug))
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)

class OrganizationList(TitleMixin, ListView):
    model = Organization
    context_object_name = 'organizations'
    template_name = 'organization/list.html'
    title = gettext_lazy('Organizations')

    def get_queryset(self):
        return super(OrganizationList, self).get_queryset().annotate(member_count=Count('member'))

class OrganizationHome(OrganizationDetailView):
    template_name = 'organization/home.html'

    def get_context_data(self, **kwargs):
        context = super(OrganizationHome, self).get_context_data(**kwargs)
        context['title'] = self.object.name
        context['can_edit'] = self.can_edit_organization()
        return context

class OrganizationUsers(OrganizationDetailView):
    template_name = 'organization/users.html'

    def get_context_data(self, **kwargs):
        context = super(OrganizationUsers, self).get_context_data(**kwargs)
        context['title'] = _('%s Members') % self.object.name
        context['users'] = \
            ranker(self.object.members.filter(is_unlisted=False).order_by('-performance_points', '-problem_count')
                   .select_related('user').defer('about', 'user_script', 'notes'))
        context['partial'] = True
        context['is_admin'] = self.can_edit_organization()
        context['kick_url'] = reverse('organization_user_kick', args=[self.object.id, self.object.slug])
        return context

class OrganizationMembershipChange(LoginRequiredMixin, OrganizationMixin, SingleObjectMixin, View):
    def post(self, request, *args, **kwargs):
        org = self.get_object()
        response = self.handle(request, org, request.profile)
        if response is not None:
            return response
        return HttpResponseRedirect(org.get_absolute_url())

    def handle(self, request, org, profile):
        raise NotImplementedError()

class JoinOrganization(OrganizationMembershipChange):
    def handle(self, request, org, profile):
        if profile.organizations.filter(id=org.id).exists():
            return generic_message(request, _('Joining organization'), _('You are already in the organization.'))

        if not org.is_open:
            return generic_message(request, _('Joining organization'), _('This organization is not open.'))

        max_orgs = settings.DMOJ_USER_MAX_ORGANIZATION_COUNT
        if profile.organizations.filter(is_open=True).count() >= max_orgs:
            return generic_message(
                request, _('Joining organization'),
                _('You may not be part of more than {count} public organizations.').format(count=max_orgs),
            )

        profile.organizations.add(org)
        profile.save()
        cache.delete(make_template_fragment_key('org_member_count', (org.id,)))

class LeaveOrganization(OrganizationMembershipChange):
    def handle(self, request, org, profile):
        if not profile.organizations.filter(id=org.id).exists():
            return generic_message(request, _('Leaving organization'), _('You are not in "%s".') % org.short_name)
        profile.organizations.remove(org)
        cache.delete(make_template_fragment_key('org_member_count', (org.id,)))

class OrganizationRequestForm(Form):
    reason = forms.CharField(widget=forms.Textarea)

class RequestJoinOrganization(LoginRequiredMixin, SingleObjectMixin, FormView):
    model = Organization
    slug_field = 'key'
    slug_url_kwarg = 'key'
    template_name = 'organization/requests/request.html'
    form_class = OrganizationRequestForm

    def dispatch(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super(RequestJoinOrganization, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(RequestJoinOrganization, self).get_context_data(**kwargs)
        if self.object.is_open:
            raise Http404()
        context['title'] = _('Request to join %s') % self.object.name
        return context

    def form_valid(self, form):
        request = OrganizationRequest()
        request.organization = self.get_object()
        request.user = self.request.profile
        request.reason = form.cleaned_data['reason']
        request.state = 'P'
        request.save()
        return HttpResponseRedirect(reverse('request_organization_detail', args=(
            request.organization.id, request.organization.slug, request.id,
        )))

class OrganizationRequestDetail(LoginRequiredMixin, TitleMixin, DetailView):
    model = OrganizationRequest
    template_name = 'organization/requests/detail.html'
    title = gettext_lazy('Join request detail')
    pk_url_kwarg = 'rpk'

    def get_object(self, queryset=None):
        object = super(OrganizationRequestDetail, self).get_object(queryset)
        profile = self.request.profile
        if object.user_id != profile.id and not object.organization.admins.filter(id=profile.id).exists():
            raise PermissionDenied()
        return object

OrganizationRequestFormSet = modelformset_factory(OrganizationRequest, extra=0, fields=('state',), can_delete=True)

class OrganizationRequestBaseView(LoginRequiredMixin, SingleObjectTemplateResponseMixin, SingleObjectMixin, View):
    model = Organization
    slug_field = 'key'
    slug_url_kwarg = 'key'
    tab = None

    def get_object(self, queryset=None):
        organization = super(OrganizationRequestBaseView, self).get_object(queryset)
        if not (organization.admins.filter(id=self.request.profile.id).exists() or
                organization.registrant_id == self.request.profile.id):
            raise PermissionDenied()
        return organization

    def get_context_data(self, **kwargs):
        context = super(OrganizationRequestBaseView, self).get_context_data(**kwargs)
        context['title'] = _('Managing join requests for %s') % self.object.name
        context['tab'] = self.tab
        return context

class OrganizationRequestView(OrganizationRequestBaseView):
    template_name = 'organization/requests/pending.html'
    tab = 'pending'

    def get_context_data(self, **kwargs):
        context = super(OrganizationRequestView, self).get_context_data(**kwargs)
        context['formset'] = self.formset
        return context

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.formset = OrganizationRequestFormSet(
            queryset=OrganizationRequest.objects.filter(state='P', organization=self.object),
        )
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)

    def post(self, request, *args, **kwargs):
        self.object = organization = self.get_object()
        self.formset = formset = OrganizationRequestFormSet(request.POST, request.FILES)
        if formset.is_valid():
            if organization.slots is not None:
                deleted_set = set(formset.deleted_forms)
                to_approve = sum(form.cleaned_data['state'] == 'A' for form in formset.forms if form not in deleted_set)
                can_add = organization.slots - organization.members.count()
                if to_approve > can_add:
                    messages.error(request, _('Your organization can only receive %d more members. '
                                              'You cannot approve %d users.') % (can_add, to_approve))
                    return self.render_to_response(self.get_context_data(object=organization))

            approved, rejected = 0, 0
            for obj in formset.save():
                if obj.state == 'A':
                    obj.user.organizations.add(obj.organization)
                    approved += 1
                elif obj.state == 'R':
                    rejected += 1
            messages.success(request,
                             ungettext('Approved %d user.', 'Approved %d users.', approved) % approved + '\n' +
                             ungettext('Rejected %d user.', 'Rejected %d users.', rejected) % rejected)
            cache.delete(make_template_fragment_key('org_member_count', (organization.id,)))
            return HttpResponseRedirect(request.get_full_path())
        return self.render_to_response(self.get_context_data(object=organization))

    put = post

class OrganizationRequestLog(OrganizationRequestBaseView):
    states = ('A', 'R')
    tab = 'log'
    template_name = 'organization/requests/log.html'

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)

    def get_context_data(self, **kwargs):
        context = super(OrganizationRequestLog, self).get_context_data(**kwargs)
        context['requests'] = self.object.requests.filter(state__in=self.states)
        return context

class EditOrganization(LoginRequiredMixin, TitleMixin, OrganizationMixin, UpdateView):
    template_name = 'organization/edit.html'
    model = Organization
    form_class = EditOrganizationForm

    def get_title(self):
        return _('Editing %s') % self.object.name

    def get_object(self, queryset=None):
        object = super(EditOrganization, self).get_object()
        if not self.can_edit_organization(object):
            raise PermissionDenied()
        return object

    def get_form(self, form_class=None):
        form = super(EditOrganization, self).get_form(form_class)
        form.fields['admins'].queryset = \
            Profile.objects.filter(Q(organizations=self.object) | Q(admin_of=self.object)).distinct()
        return form

    def form_valid(self, form):
        with transaction.atomic(), revisions.create_revision():
            revisions.set_comment(_('Edited from site'))
            revisions.set_user(self.request.user)
            return super(EditOrganization, self).form_valid(form)

    def dispatch(self, request, *args, **kwargs):
        try:
            return super(EditOrganization, self).dispatch(request, *args, **kwargs)
        except PermissionDenied:
            return generic_message(request, _("Can't edit organization"),
                                   _('You are not allowed to edit this organization.'), status=403)

class KickUserWidgetView(LoginRequiredMixin, OrganizationMixin, SingleObjectMixin, View):
    def post(self, request, *args, **kwargs):
        organization = self.get_object()
        if not self.can_edit_organization(organization):
            return generic_message(request, _("Can't edit organization"),
                                   _('You are not allowed to kick people from this organization.'), status=403)

        try:
            user = Profile.objects.get(id=request.POST.get('user', None))
        except Profile.DoesNotExist:
            return generic_message(request, _("Can't kick user"),
                                   _('The user you are trying to kick does not exist!'), status=400)

        if not organization.members.filter(id=user.id).exists():
            return generic_message(request, _("Can't kick user"),
                                   _('The user you are trying to kick is not in organization: %s.') %
                                   organization.name, status=400)

        organization.members.remove(user)
        return HttpResponseRedirect(organization.get_users_url())
<commit_msg>Properly redirect when the organization slug is wrong<commit_after>from django import forms
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.cache import cache
from django.core.cache.utils import make_template_fragment_key
from django.core.exceptions import PermissionDenied
from django.db import transaction
from django.db.models import Count, Q
from django.forms import Form, modelformset_factory
from django.http import Http404, HttpResponsePermanentRedirect, HttpResponseRedirect
from django.urls import reverse
from django.utils.translation import gettext as _, gettext_lazy, ungettext
from django.views.generic import DetailView, FormView, ListView, UpdateView, View
from django.views.generic.detail import SingleObjectMixin, SingleObjectTemplateResponseMixin
from reversion import revisions

from judge.forms import EditOrganizationForm
from judge.models import Organization, OrganizationRequest, Profile
from judge.utils.ranker import ranker
from judge.utils.views import TitleMixin, generic_message

__all__ = ['OrganizationList', 'OrganizationHome', 'OrganizationUsers', 'OrganizationMembershipChange',
           'JoinOrganization', 'LeaveOrganization', 'EditOrganization', 'RequestJoinOrganization',
           'OrganizationRequestDetail', 'OrganizationRequestView', 'OrganizationRequestLog',
           'KickUserWidgetView']

class OrganizationMixin(object):
    context_object_name = 'organization'
    model = Organization

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['logo_override_image'] = self.object.logo_override_image
        return context

    def dispatch(self, request, *args, **kwargs):
        try:
            return super(OrganizationMixin, self).dispatch(request, *args, **kwargs)
        except Http404:
            key = kwargs.get(self.slug_url_kwarg, None)
            if key:
                return generic_message(request, _('No such organization'),
                                       _('Could not find an organization with the key "%s".') % key)
            else:
                return generic_message(request, _('No such organization'),
                                       _('Could not find such organization.'))

    def can_edit_organization(self, org=None):
        if org is None:
            org = self.object
        if not self.request.user.is_authenticated:
            return False
        profile_id = self.request.profile.id
        return org.admins.filter(id=profile_id).exists() or org.registrant_id == profile_id

class OrganizationDetailView(OrganizationMixin, DetailView):
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        if self.object.slug != kwargs['slug']:
            return HttpResponsePermanentRedirect(reverse('organization_home', args=(self.object.id, self.object.slug)))
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)

class OrganizationList(TitleMixin, ListView):
    model = Organization
    context_object_name = 'organizations'
    template_name = 'organization/list.html'
    title = gettext_lazy('Organizations')

    def get_queryset(self):
        return super(OrganizationList, self).get_queryset().annotate(member_count=Count('member'))

class OrganizationHome(OrganizationDetailView):
    template_name = 'organization/home.html'

    def get_context_data(self, **kwargs):
        context = super(OrganizationHome, self).get_context_data(**kwargs)
        context['title'] = self.object.name
        context['can_edit'] = self.can_edit_organization()
        return context

class OrganizationUsers(OrganizationDetailView):
    template_name = 'organization/users.html'

    def get_context_data(self, **kwargs):
        context = super(OrganizationUsers, self).get_context_data(**kwargs)
        context['title'] = _('%s Members') % self.object.name
        context['users'] = \
            ranker(self.object.members.filter(is_unlisted=False).order_by('-performance_points', '-problem_count')
                   .select_related('user').defer('about', 'user_script', 'notes'))
        context['partial'] = True
        context['is_admin'] = self.can_edit_organization()
        context['kick_url'] = reverse('organization_user_kick', args=[self.object.id, self.object.slug])
        return context

class OrganizationMembershipChange(LoginRequiredMixin, OrganizationMixin, SingleObjectMixin, View):
    def post(self, request, *args, **kwargs):
        org = self.get_object()
        response = self.handle(request, org, request.profile)
        if response is not None:
            return response
        return HttpResponseRedirect(org.get_absolute_url())

    def handle(self, request, org, profile):
        raise NotImplementedError()

class JoinOrganization(OrganizationMembershipChange):
    def handle(self, request, org, profile):
        if profile.organizations.filter(id=org.id).exists():
            return generic_message(request, _('Joining organization'), _('You are already in the organization.'))

        if not org.is_open:
            return generic_message(request, _('Joining organization'), _('This organization is not open.'))

        max_orgs = settings.DMOJ_USER_MAX_ORGANIZATION_COUNT
        if profile.organizations.filter(is_open=True).count() >= max_orgs:
            return generic_message(
                request, _('Joining organization'),
                _('You may not be part of more than {count} public organizations.').format(count=max_orgs),
            )

        profile.organizations.add(org)
        profile.save()
        cache.delete(make_template_fragment_key('org_member_count', (org.id,)))

class LeaveOrganization(OrganizationMembershipChange):
    def handle(self, request, org, profile):
        if not profile.organizations.filter(id=org.id).exists():
            return generic_message(request, _('Leaving organization'), _('You are not in "%s".') % org.short_name)
        profile.organizations.remove(org)
        cache.delete(make_template_fragment_key('org_member_count', (org.id,)))

class OrganizationRequestForm(Form):
    reason = forms.CharField(widget=forms.Textarea)

class RequestJoinOrganization(LoginRequiredMixin, SingleObjectMixin, FormView):
    model = Organization
    slug_field = 'key'
    slug_url_kwarg = 'key'
    template_name = 'organization/requests/request.html'
    form_class = OrganizationRequestForm

    def dispatch(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super(RequestJoinOrganization, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(RequestJoinOrganization, self).get_context_data(**kwargs)
        if self.object.is_open:
            raise Http404()
        context['title'] = _('Request to join %s') % self.object.name
        return context

    def form_valid(self, form):
        request = OrganizationRequest()
        request.organization = self.get_object()
        request.user = self.request.profile
        request.reason = form.cleaned_data['reason']
        request.state = 'P'
        request.save()
        return HttpResponseRedirect(reverse('request_organization_detail', args=(
            request.organization.id, request.organization.slug, request.id,
        )))

class OrganizationRequestDetail(LoginRequiredMixin, TitleMixin, DetailView):
    model = OrganizationRequest
    template_name = 'organization/requests/detail.html'
    title = gettext_lazy('Join request detail')
    pk_url_kwarg = 'rpk'

    def get_object(self, queryset=None):
        object = super(OrganizationRequestDetail, self).get_object(queryset)
        profile = self.request.profile
        if object.user_id != profile.id and not object.organization.admins.filter(id=profile.id).exists():
            raise PermissionDenied()
        return object

OrganizationRequestFormSet = modelformset_factory(OrganizationRequest, extra=0, fields=('state',), can_delete=True)

class OrganizationRequestBaseView(LoginRequiredMixin, SingleObjectTemplateResponseMixin, SingleObjectMixin, View):
    model = Organization
    slug_field = 'key'
    slug_url_kwarg = 'key'
    tab = None

    def get_object(self, queryset=None):
        organization = super(OrganizationRequestBaseView, self).get_object(queryset)
        if not (organization.admins.filter(id=self.request.profile.id).exists() or
                organization.registrant_id == self.request.profile.id):
            raise PermissionDenied()
        return organization

    def get_context_data(self, **kwargs):
        context = super(OrganizationRequestBaseView, self).get_context_data(**kwargs)
        context['title'] = _('Managing join requests for %s') % self.object.name
        context['tab'] = self.tab
        return context

class OrganizationRequestView(OrganizationRequestBaseView):
    template_name = 'organization/requests/pending.html'
    tab = 'pending'

    def get_context_data(self, **kwargs):
        context = super(OrganizationRequestView, self).get_context_data(**kwargs)
        context['formset'] = self.formset
        return context

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.formset = OrganizationRequestFormSet(
            queryset=OrganizationRequest.objects.filter(state='P', organization=self.object),
        )
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)

    def post(self, request, *args, **kwargs):
        self.object = organization = self.get_object()
        self.formset = formset = OrganizationRequestFormSet(request.POST, request.FILES)
        if formset.is_valid():
            if organization.slots is not None:
                deleted_set = set(formset.deleted_forms)
                to_approve = sum(form.cleaned_data['state'] == 'A' for form in formset.forms if form not in deleted_set)
                can_add = organization.slots - organization.members.count()
                if to_approve > can_add:
                    messages.error(request, _('Your organization can only receive %d more members. '
                                              'You cannot approve %d users.') % (can_add, to_approve))
                    return self.render_to_response(self.get_context_data(object=organization))

            approved, rejected = 0, 0
            for obj in formset.save():
                if obj.state == 'A':
                    obj.user.organizations.add(obj.organization)
                    approved += 1
                elif obj.state == 'R':
                    rejected += 1
            messages.success(request,
                             ungettext('Approved %d user.', 'Approved %d users.', approved) % approved + '\n' +
                             ungettext('Rejected %d user.', 'Rejected %d users.', rejected) % rejected)
            cache.delete(make_template_fragment_key('org_member_count', (organization.id,)))
            return HttpResponseRedirect(request.get_full_path())
        return self.render_to_response(self.get_context_data(object=organization))

    put = post

class OrganizationRequestLog(OrganizationRequestBaseView):
    states = ('A', 'R')
    tab = 'log'
    template_name = 'organization/requests/log.html'

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)

    def get_context_data(self, **kwargs):
        context = super(OrganizationRequestLog, self).get_context_data(**kwargs)
        context['requests'] = self.object.requests.filter(state__in=self.states)
        return context

class EditOrganization(LoginRequiredMixin, TitleMixin, OrganizationMixin, UpdateView):
    template_name = 'organization/edit.html'
    model = Organization
    form_class = EditOrganizationForm

    def get_title(self):
        return _('Editing %s') % self.object.name

    def get_object(self, queryset=None):
        object = super(EditOrganization, self).get_object()
        if not self.can_edit_organization(object):
            raise PermissionDenied()
        return object

    def get_form(self, form_class=None):
        form = super(EditOrganization, self).get_form(form_class)
        form.fields['admins'].queryset = \
            Profile.objects.filter(Q(organizations=self.object) | Q(admin_of=self.object)).distinct()
        return form

    def form_valid(self, form):
        with transaction.atomic(), revisions.create_revision():
            revisions.set_comment(_('Edited from site'))
            revisions.set_user(self.request.user)
            return super(EditOrganization, self).form_valid(form)

    def dispatch(self, request, *args, **kwargs):
        try:
            return super(EditOrganization, self).dispatch(request, *args, **kwargs)
        except PermissionDenied:
            return generic_message(request, _("Can't edit organization"),
                                   _('You are not allowed to edit this organization.'), status=403)

class KickUserWidgetView(LoginRequiredMixin, OrganizationMixin, SingleObjectMixin, View):
    def post(self, request, *args, **kwargs):
        organization = self.get_object()
        if not self.can_edit_organization(organization):
            return generic_message(request, _("Can't edit organization"),
                                   _('You are not allowed to kick people from this organization.'), status=403)

        try:
            user = Profile.objects.get(id=request.POST.get('user', None))
        except Profile.DoesNotExist:
            return generic_message(request, _("Can't kick user"),
                                   _('The user you are trying to kick does not exist!'), status=400)

        if not organization.members.filter(id=user.id).exists():
            return generic_message(request, _("Can't kick user"),
                                   _('The user you are trying to kick is not in organization: %s.') %
                                   organization.name, status=400)

        organization.members.remove(user)
        return HttpResponseRedirect(organization.get_users_url())
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
from __future__ import unicode_literals
from builtins import str

import os
from tempfile import mkdtemp
from shutil import rmtree

import nibabel as nb
import numpy as np

from nipype.testing import (assert_equal, assert_false, assert_true, skipif)
import nipype.interfaces.spm.base as spm
from nipype.interfaces.spm import no_spm
import nipype.interfaces.matlab as mlab
from nipype.interfaces.spm.base import SPMCommandInputSpec
from nipype.interfaces.base import traits

try:
    matlab_cmd = os.environ['MATLABCMD']
except:
    matlab_cmd = 'matlab'

mlab.MatlabCommand.set_default_matlab_cmd(matlab_cmd)

def create_files_in_directory():
    outdir = mkdtemp()
    cwd = os.getcwd()
    os.chdir(outdir)
    filelist = ['a.nii', 'b.nii']
    for f in filelist:
        hdr = nb.Nifti1Header()
        shape = (3, 3, 3, 4)
        hdr.set_data_shape(shape)
        img = np.random.random(shape)
        nb.save(nb.Nifti1Image(img, np.eye(4), hdr),
                os.path.join(outdir, f))
    return filelist, outdir, cwd

def clean_directory(outdir, old_wd):
    if os.path.exists(outdir):
        rmtree(outdir)
    os.chdir(old_wd)

def test_scan_for_fnames():
    filelist, outdir, cwd = create_files_in_directory()
    names = spm.scans_for_fnames(filelist, keep4d=True)
    yield assert_equal, names[0], filelist[0]
    yield assert_equal, names[1], filelist[1]
    clean_directory(outdir, cwd)

save_time = False
if not save_time:
    @skipif(no_spm)
    def test_spm_path():
        spm_path = spm.Info.version()['path']
        if spm_path is not None:
            yield assert_equal, type(spm_path), str
            yield assert_true, 'spm' in spm_path

def test_use_mfile():
    class TestClass(spm.SPMCommand):
        input_spec = spm.SPMCommandInputSpec
    dc = TestClass()  # dc = derived_class
    yield assert_true, dc.inputs.mfile

def test_find_mlab_cmd_defaults():
    saved_env = dict(os.environ)

    class TestClass(spm.SPMCommand):
        pass
    # test without FORCE_SPMMCR, SPMMCRCMD set
    for varname in ['FORCE_SPMMCR', 'SPMMCRCMD']:
        try:
            del os.environ[varname]
        except KeyError:
            pass
    dc = TestClass()
    yield assert_equal, dc._use_mcr, None
    yield assert_equal, dc._matlab_cmd, None
    # test with only FORCE_SPMMCR set
    os.environ['FORCE_SPMMCR'] = '1'
    dc = TestClass()
    yield assert_equal, dc._use_mcr, True
    yield assert_equal, dc._matlab_cmd, None
    # test with both, FORCE_SPMMCR and SPMMCRCMD set
    os.environ['SPMMCRCMD'] = 'spmcmd'
    dc = TestClass()
    yield assert_equal, dc._use_mcr, True
    yield assert_equal, dc._matlab_cmd, 'spmcmd'
    # restore environment
    os.environ.clear()
    os.environ.update(saved_env)

@skipif(no_spm, "SPM not found")
def test_cmd_update():
    class TestClass(spm.SPMCommand):
        input_spec = spm.SPMCommandInputSpec
    dc = TestClass()  # dc = derived_class
    dc.inputs.matlab_cmd = 'foo'
    yield assert_equal, dc.mlab._cmd, 'foo'

def test_cmd_update2():
    class TestClass(spm.SPMCommand):
        _jobtype = 'jobtype'
        _jobname = 'jobname'
        input_spec = spm.SPMCommandInputSpec
    dc = TestClass()  # dc = derived_class
    yield assert_equal, dc.jobtype, 'jobtype'
    yield assert_equal, dc.jobname, 'jobname'

def test_reformat_dict_for_savemat():
    class TestClass(spm.SPMCommand):
        input_spec = spm.SPMCommandInputSpec
    dc = TestClass()  # dc = derived_class
    out = dc._reformat_dict_for_savemat({'a': {'b': {'c': []}}})
    yield assert_equal, out, [{'a': [{'b': [{'c': []}]}]}]

def test_generate_job():
    class TestClass(spm.SPMCommand):
        input_spec = spm.SPMCommandInputSpec
    dc = TestClass()  # dc = derived_class
    out = dc._generate_job()
    yield assert_equal, out, ''
    # struct array
    contents = {'contents': [1, 2, 3, 4]}
    out = dc._generate_job(contents=contents)
    yield assert_equal, out, ('.contents(1) = 1;\n.contents(2) = 2;'
                              '\n.contents(3) = 3;\n.contents(4) = 4;\n')
    # cell array of strings
    filelist, outdir, cwd = create_files_in_directory()
    names = spm.scans_for_fnames(filelist, keep4d=True)
    contents = {'files': names}
    out = dc._generate_job(prefix='test', contents=contents)
    yield assert_equal, out, "test.files = {...\n'a.nii';...\n'b.nii';...\n};\n"
    clean_directory(outdir, cwd)
    # string assignment
    contents = 'foo'
    out = dc._generate_job(prefix='test', contents=contents)
    yield assert_equal, out, "test = 'foo';\n"
    # cell array of vectors
    contents = {'onsets': np.array((1,), dtype=object)}
    contents['onsets'][0] = [1, 2, 3, 4]
    out = dc._generate_job(prefix='test', contents=contents)
    yield assert_equal, out, 'test.onsets = {...\n[1, 2, 3, 4];...\n};\n'

def test_bool():
    class TestClassInputSpec(SPMCommandInputSpec):
        test_in = include_intercept = traits.Bool(field='testfield')

    class TestClass(spm.SPMCommand):
        input_spec = TestClassInputSpec
        _jobtype = 'jobtype'
        _jobname = 'jobname'
    dc = TestClass()  # dc = derived_class
    dc.inputs.test_in = True
    out = dc._make_matlab_command(dc._parse_inputs())
    yield assert_equal, out.find('jobs{1}.spm.jobtype.jobname.testfield = 1;') > 0, 1
    dc.inputs.use_v8struct = False
    out = dc._make_matlab_command(dc._parse_inputs())
    yield assert_equal, out.find('jobs{1}.jobtype{1}.jobname{1}.testfield = 1;') > 0, 1

def test_make_matlab_command():
    class TestClass(spm.SPMCommand):
        _jobtype = 'jobtype'
        _jobname = 'jobname'
        input_spec = spm.SPMCommandInputSpec
    dc = TestClass()  # dc = derived_class
    filelist, outdir, cwd = create_files_in_directory()
    contents = {'contents': [1, 2, 3, 4]}
    script = dc._make_matlab_command([contents])
    yield assert_true, 'jobs{1}.spm.jobtype.jobname.contents(3) = 3;' in script
    dc.inputs.use_v8struct = False
    script = dc._make_matlab_command([contents])
    yield assert_true, 'jobs{1}.jobtype{1}.jobname{1}.contents(3) = 3;' in script
    clean_directory(outdir, cwd)
<commit_msg>compat py2/3: fix spm_base test<commit_after># -*- coding: utf-8 -*-
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
from __future__ import unicode_literals
from builtins import str, bytes

import os
from tempfile import mkdtemp
from shutil import rmtree

import nibabel as nb
import numpy as np

from nipype.testing import (assert_equal, assert_false, assert_true, skipif)
import nipype.interfaces.spm.base as spm
from nipype.interfaces.spm import no_spm
import nipype.interfaces.matlab as mlab
from nipype.interfaces.spm.base import SPMCommandInputSpec
from nipype.interfaces.base import traits

try:
    matlab_cmd = os.environ['MATLABCMD']
except:
    matlab_cmd = 'matlab'

mlab.MatlabCommand.set_default_matlab_cmd(matlab_cmd)

def create_files_in_directory():
    outdir = mkdtemp()
    cwd = os.getcwd()
    os.chdir(outdir)
    filelist = ['a.nii', 'b.nii']
    for f in filelist:
        hdr = nb.Nifti1Header()
        shape = (3, 3, 3, 4)
        hdr.set_data_shape(shape)
        img = np.random.random(shape)
        nb.save(nb.Nifti1Image(img, np.eye(4), hdr),
                os.path.join(outdir, f))
    return filelist, outdir, cwd

def clean_directory(outdir, old_wd):
    if os.path.exists(outdir):
        rmtree(outdir)
    os.chdir(old_wd)

def test_scan_for_fnames():
    filelist, outdir, cwd = create_files_in_directory()
    names = spm.scans_for_fnames(filelist, keep4d=True)
    yield assert_equal, names[0], filelist[0]
    yield assert_equal, names[1], filelist[1]
    clean_directory(outdir, cwd)

save_time = False
if not save_time:
    @skipif(no_spm)
    def test_spm_path():
        spm_path = spm.Info.version()['path']
        if spm_path is not None:
            yield assert_true, isinstance(spm_path, (str, bytes))
            yield assert_true, 'spm' in spm_path

def test_use_mfile():
    class TestClass(spm.SPMCommand):
        input_spec = spm.SPMCommandInputSpec
    dc = TestClass()  # dc = derived_class
    yield assert_true, dc.inputs.mfile

def test_find_mlab_cmd_defaults():
    saved_env = dict(os.environ)

    class TestClass(spm.SPMCommand):
        pass
    # test without FORCE_SPMMCR, SPMMCRCMD set
    for varname in ['FORCE_SPMMCR', 'SPMMCRCMD']:
        try:
            del os.environ[varname]
        except KeyError:
            pass
    dc = TestClass()
    yield assert_equal, dc._use_mcr, None
    yield assert_equal, dc._matlab_cmd, None
    # test with only FORCE_SPMMCR set
    os.environ['FORCE_SPMMCR'] = '1'
    dc = TestClass()
    yield assert_equal, dc._use_mcr, True
    yield assert_equal, dc._matlab_cmd, None
    # test with both, FORCE_SPMMCR and SPMMCRCMD set
    os.environ['SPMMCRCMD'] = 'spmcmd'
    dc = TestClass()
    yield assert_equal, dc._use_mcr, True
    yield assert_equal, dc._matlab_cmd, 'spmcmd'
    # restore environment
    os.environ.clear()
    os.environ.update(saved_env)

@skipif(no_spm, "SPM not found")
def test_cmd_update():
    class TestClass(spm.SPMCommand):
        input_spec = spm.SPMCommandInputSpec
    dc = TestClass()  # dc = derived_class
    dc.inputs.matlab_cmd = 'foo'
    yield assert_equal, dc.mlab._cmd, 'foo'

def test_cmd_update2():
    class TestClass(spm.SPMCommand):
        _jobtype = 'jobtype'
        _jobname = 'jobname'
        input_spec = spm.SPMCommandInputSpec
    dc = TestClass()  # dc = derived_class
    yield assert_equal, dc.jobtype, 'jobtype'
    yield assert_equal, dc.jobname, 'jobname'

def test_reformat_dict_for_savemat():
    class TestClass(spm.SPMCommand):
        input_spec = spm.SPMCommandInputSpec
    dc = TestClass()  # dc = derived_class
    out = dc._reformat_dict_for_savemat({'a': {'b': {'c': []}}})
    yield assert_equal, out, [{'a': [{'b': [{'c': []}]}]}]

def test_generate_job():
    class TestClass(spm.SPMCommand):
        input_spec = spm.SPMCommandInputSpec
    dc = TestClass()  # dc = derived_class
    out = dc._generate_job()
    yield assert_equal, out, ''
    # struct array
    contents = {'contents': [1, 2, 3, 4]}
    out = dc._generate_job(contents=contents)
    yield assert_equal, out, ('.contents(1) = 1;\n.contents(2) = 2;'
                              '\n.contents(3) = 3;\n.contents(4) = 4;\n')
    # cell array of strings
    filelist, outdir, cwd = create_files_in_directory()
    names = spm.scans_for_fnames(filelist, keep4d=True)
    contents = {'files': names}
    out = dc._generate_job(prefix='test', contents=contents)
    yield assert_equal, out, "test.files = {...\n'a.nii';...\n'b.nii';...\n};\n"
    clean_directory(outdir, cwd)
    # string assignment
    contents = 'foo'
    out = dc._generate_job(prefix='test', contents=contents)
    yield assert_equal, out, "test = 'foo';\n"
    # cell array of vectors
    contents = {'onsets': np.array((1,), dtype=object)}
    contents['onsets'][0] = [1, 2, 3, 4]
    out = dc._generate_job(prefix='test', contents=contents)
    yield assert_equal, out, 'test.onsets = {...\n[1, 2, 3, 4];...\n};\n'

def test_bool():
    class TestClassInputSpec(SPMCommandInputSpec):
        test_in = include_intercept = traits.Bool(field='testfield')

    class TestClass(spm.SPMCommand):
        input_spec = TestClassInputSpec
        _jobtype = 'jobtype'
        _jobname = 'jobname'
    dc = TestClass()  # dc = derived_class
    dc.inputs.test_in = True
    out = dc._make_matlab_command(dc._parse_inputs())
    yield assert_equal, out.find('jobs{1}.spm.jobtype.jobname.testfield = 1;') > 0, 1
    dc.inputs.use_v8struct = False
    out = dc._make_matlab_command(dc._parse_inputs())
    yield assert_equal, out.find('jobs{1}.jobtype{1}.jobname{1}.testfield = 1;') > 0, 1

def test_make_matlab_command():
    class TestClass(spm.SPMCommand):
        _jobtype = 'jobtype'
        _jobname = 'jobname'
        input_spec = spm.SPMCommandInputSpec
    dc = TestClass()  # dc = derived_class
    filelist, outdir, cwd = create_files_in_directory()
    contents = {'contents': [1, 2, 3, 4]}
    script = dc._make_matlab_command([contents])
    yield assert_true, 'jobs{1}.spm.jobtype.jobname.contents(3) = 3;' in script
    dc.inputs.use_v8struct = False
    script = dc._make_matlab_command([contents])
    yield assert_true, 'jobs{1}.jobtype{1}.jobname{1}.contents(3) = 3;' in script
    clean_directory(outdir, cwd)
<|endoftext|>


<commit_before>import re
from collections import Iterable, OrderedDict
from functools import partial

import six

from graphql_relay import connection_from_list

from ..types import (AbstractType, Boolean, Enum, Int, Interface, List, NonNull, Scalar, String,
                     Union)
from ..types.field import Field
from ..types.objecttype import ObjectType, ObjectTypeMeta
from ..types.options import Options
from ..utils.is_base_type import is_base_type
from ..utils.props import props
from .node import is_node

class PageInfo(ObjectType):
    has_next_page = Boolean(
        required=True,
        name='hasNextPage',
        description='When paginating forwards, are there more items?',
    )

    has_previous_page = Boolean(
        required=True,
        name='hasPreviousPage',
        description='When paginating backwards, are there more items?',
    )

    start_cursor = String(
        name='startCursor',
        description='When paginating backwards, the cursor to continue.',
    )

    end_cursor = String(
        name='endCursor',
        description='When paginating forwards, the cursor to continue.',
    )

class ConnectionMeta(ObjectTypeMeta):

    def __new__(cls, name, bases, attrs):
        # Also ensure initialization is only performed for subclasses of Model
        # (excluding Model class itself).
        if not is_base_type(bases, ConnectionMeta):
            return type.__new__(cls, name, bases, attrs)

        options = Options(
            attrs.pop('Meta', None),
            name=name,
            description=None,
            node=None,
        )
        options.interfaces = ()
        options.local_fields = OrderedDict()

        assert options.node, 'You have to provide a node in {}.Meta'.format(cls.__name__)
        assert issubclass(options.node, (Scalar, Enum, ObjectType, Interface, Union, NonNull)), (
            'Received incompatible node "{}" for Connection {}.'
        ).format(options.node, name)

        base_name = re.sub('Connection$', '', options.name) or options.node._meta.name
        if not options.name:
            options.name = '{}Connection'.format(base_name)

        edge_class = attrs.pop('Edge', None)

        class EdgeBase(AbstractType):
            node = Field(options.node, description='The item at the end of the edge')
            cursor = String(required=True, description='A cursor for use in pagination')

        edge_name = '{}Edge'.format(base_name)
        if edge_class and issubclass(edge_class, AbstractType):
            edge = type(edge_name, (EdgeBase, edge_class, ObjectType, ), {})
        else:
            edge_attrs = props(edge_class) if edge_class else {}
            edge = type(edge_name, (EdgeBase, ObjectType, ), edge_attrs)

        class ConnectionBase(AbstractType):
            page_info = Field(PageInfo, name='pageInfo', required=True)
            edges = List(edge)

        bases = (ConnectionBase, ) + bases
        attrs = dict(attrs, _meta=options, Edge=edge)
        return ObjectTypeMeta.__new__(cls, name, bases, attrs)

class Connection(six.with_metaclass(ConnectionMeta, ObjectType)):
    pass

class IterableConnectionField(Field):

    def __init__(self, type, *args, **kwargs):
        kwargs.setdefault('before', String())
        kwargs.setdefault('after', String())
        kwargs.setdefault('first', Int())
        kwargs.setdefault('last', Int())
        super(IterableConnectionField, self).__init__(
            type,
            *args,
            **kwargs
        )

    @property
    def type(self):
        type = super(IterableConnectionField, self).type
        if is_node(type):
            connection_type = type.Connection
        else:
            connection_type = type
        assert issubclass(connection_type, Connection), (
            '{} type have to be a subclass of Connection. Received "{}".'
        ).format(str(self), connection_type)
        return connection_type

    @classmethod
    def connection_resolver(cls, resolver, connection, root, args, context, info):
        resolved = resolver(root, args, context, info)

        if isinstance(resolved, connection):
            return resolved

        assert isinstance(resolved, Iterable), (
            'Resolved value from the connection field have to be iterable or instance of {}. '
            'Received "{}"'
        ).format(connection, resolved)
        connection = connection_from_list(
            resolved,
            args,
            connection_type=connection,
            edge_type=connection.Edge,
            pageinfo_type=PageInfo
        )
        connection.iterable = resolved
        return connection

    def get_resolver(self, parent_resolver):
        resolver = super(IterableConnectionField, self).get_resolver(parent_resolver)
        return partial(self.connection_resolver, resolver, self.type)

ConnectionField = IterableConnectionField
<commit_msg>Add support to return a promise for connections.<commit_after>import re
from collections import Iterable, OrderedDict
from functools import partial

import six

from graphql_relay import connection_from_list

from ..types import (AbstractType, Boolean, Enum, Int, Interface, List, NonNull, Scalar, String,
                     Union)
from ..types.field import Field
from ..types.objecttype import ObjectType, ObjectTypeMeta
from ..types.options import Options
from ..utils.is_base_type import is_base_type
from ..utils.props import props
from .node import is_node

class PageInfo(ObjectType):
    has_next_page = Boolean(
        required=True,
        name='hasNextPage',
        description='When paginating forwards, are there more items?',
    )

    has_previous_page = Boolean(
        required=True,
        name='hasPreviousPage',
        description='When paginating backwards, are there more items?',
    )

    start_cursor = String(
        name='startCursor',
        description='When paginating backwards, the cursor to continue.',
    )

    end_cursor = String(
        name='endCursor',
        description='When paginating forwards, the cursor to continue.',
    )

class ConnectionMeta(ObjectTypeMeta):

    def __new__(cls, name, bases, attrs):
        # Also ensure initialization is only performed for subclasses of Model
        # (excluding Model class itself).
        if not is_base_type(bases, ConnectionMeta):
            return type.__new__(cls, name, bases, attrs)

        options = Options(
            attrs.pop('Meta', None),
            name=name,
            description=None,
            node=None,
        )
        options.interfaces = ()
        options.local_fields = OrderedDict()

        assert options.node, 'You have to provide a node in {}.Meta'.format(cls.__name__)
        assert issubclass(options.node, (Scalar, Enum, ObjectType, Interface, Union, NonNull)), (
            'Received incompatible node "{}" for Connection {}.'
        ).format(options.node, name)

        base_name = re.sub('Connection$', '', options.name) or options.node._meta.name
        if not options.name:
            options.name = '{}Connection'.format(base_name)

        edge_class = attrs.pop('Edge', None)

        class EdgeBase(AbstractType):
            node = Field(options.node, description='The item at the end of the edge')
            cursor = String(required=True, description='A cursor for use in pagination')

        edge_name = '{}Edge'.format(base_name)
        if edge_class and issubclass(edge_class, AbstractType):
            edge = type(edge_name, (EdgeBase, edge_class, ObjectType, ), {})
        else:
            edge_attrs = props(edge_class) if edge_class else {}
            edge = type(edge_name, (EdgeBase, ObjectType, ), edge_attrs)

        class ConnectionBase(AbstractType):
            page_info = Field(PageInfo, name='pageInfo', required=True)
            edges = List(edge)

        bases = (ConnectionBase, ) + bases
        attrs = dict(attrs, _meta=options, Edge=edge)
        return ObjectTypeMeta.__new__(cls, name, bases, attrs)

class Connection(six.with_metaclass(ConnectionMeta, ObjectType)):
    pass

class IterableConnectionField(Field):

    def __init__(self, type, *args, **kwargs):
        kwargs.setdefault('before', String())
        kwargs.setdefault('after', String())
        kwargs.setdefault('first', Int())
        kwargs.setdefault('last', Int())
        super(IterableConnectionField, self).__init__(
            type,
            *args,
            **kwargs
        )

    @property
    def type(self):
        type = super(IterableConnectionField, self).type
        if is_node(type):
            connection_type = type.Connection
        else:
            connection_type = type
        assert issubclass(connection_type, Connection), (
            '{} type have to be a subclass of Connection. Received "{}".'
        ).format(str(self), connection_type)
        return connection_type

    @classmethod
    def connection_resolver(cls, resolver, connection_type, root, args, context, info):
        p = Promise.resolve(resolver(root, args, context, info))

        def resolve_connection(resolved):
            if isinstance(resolved, connection_type):
                return resolved

            assert isinstance(resolved, Iterable), (
                'Resolved value from the connection field have to be iterable or instance of {}. '
                'Received "{}"'
            ).format(connection_type, resolved)
            connection = connection_from_list(
                resolved,
                args,
                connection_type=connection_type,
                edge_type=connection_type.Edge,
                pageinfo_type=PageInfo
            )
            connection.iterable = resolved
            return connection

        return p.then(resolve_connection)

    def get_resolver(self, parent_resolver):
        resolver = super(IterableConnectionField, self).get_resolver(parent_resolver)
        return partial(self.connection_resolver, resolver, self.type)

ConnectionField = IterableConnectionField
<|endoftext|>


<commit_before># Three models
# JSON data models THREAd to provide
#

# function to

try:
    from urlparse import urlunparse, urljoin
except:
    pass

def j28ThreadUri(threadUrl):
    if threadUrl:
        return "thread/" + get_url_hash(threadUrl)
    else:
        return ""

def j28PostUri(postUrl):
    """Canonicalize postURL to drop query and fragment"""
    if postUrl:
        (scheme, netloc, path, params, query, fragment) = urlparse(postUrl)
        return "post/" + get_url_hash(urlunparse( (scheme, netloc, path, params, query, "") ))
    else:
        return ""

def j28ImageUri(url):
    if url:
        return "image/" + get_url_hash(url)
    else:
        return ""

def j28FeatureProperty():
    """the name of the property"""
    pass

def j28SourceName(originalfile):
    return ".".join(originalfile.split('.')[0:-1])

J28SITEROOTS = {"airgunadvice.net": "http://www.airgunadvice.net",
                "americanpreppersnetwork.net": "http://americanpreppersnetwork.net",
                "arguntrader.com": "http://arguntrader.com",
                "claytargetclassifieds.com": "http://www.claytargetclassifieds.com",
                "comebackalive.com": "http://cafe.comebackalive.com",
                "ducksouth.com": "http://www.ducksouth.com/phpbb",
                "gobblernation.com": "http://www.gobblernation.com/phpBB3",
                "henryfirearms.org": "http://http://www.henryfirearms.org/henrybb/",
                "isthmus.com": "http://forum.isthmus.com",
                "kentuckyarmoryclub.com": "http://kentuckyarmoryclub.com",
                "levergunscommunity.com": "http://levergunscommunity.com",
                "marauderairrifle.com": "http://marauderairrifle.com/forum",
                "modernmuzzleloader.com": "http://modernmuzzleloader.com/forum",
                "newmexicoguntrader.net": "http://newmexicoguntrader.net",
                "nodakoutdoors.com": "http://nodakoutdoors.com/forums",
                "nosler.com": "http://forum.nosler.com",
                "ohioccwforums.org": "http://ohioccwforums.org",
                "pistolworld.com": "http://pistolworld.com/bbs",
                "remingtonsociety.com": "http://www.remingtonsociety.com/forums",
                "rossi-rifleman.com": "http://www.rossi-rifleman.com",
                "silencerforum.com": "http://www.silencerforum.com",
                "spokaneguntrader.com": "http://www.spokaneguntrader.com",
                "texaschlforum.com": "http://www.texaschlforum.com",
                "tfaonline.org": "http://www.tfaonline.org/forum",
                "theliberalgunclub.com": "http://www.theliberalgunclub.com/phpBB3",
                "tndeer.com": "http://www.tndeer.com/forums",
                "treasurestatearms.com": "http://www.treasurestatearms.com/phpbb3",
                "utahconcealedcarry.com": "http://www.utahconcealedcarry.com"}

HG2SITEROOTS = {"smf_abraxasgacelesox.onion": "http://www.smf_abraxasgacelesox.onion",
                "phpbb_z34uj4opd3tejafn.onion": "http://phpbb_z34uj4opd3tejafn.onion",

## To avoid changing model, just append those new entries to original

J28SITEROOTS.update(HG2SITEROOTS)

def j28SiteRoot(sourceName):
    return J28SITEROOTS.get(sourceName, "")

# future
# def hg2SiteRoot(sourceName):
#     return HG2SITEROOTS.get(sourceName, "")

def j28ThreadLinkAbsolute(siteRoot, threadLink):
    return urljoin(siteRoot, threadLink)

def j28FcUri(uri):
    return atf_fc_uri(uri)

<commit_msg>typo in HG2 data declaration<commit_after># Three models
# JSON data models THREAd to provide
#

# function to

try:
    from urlparse import urlunparse, urljoin
except:
    pass

def j28ThreadUri(threadUrl):
    if threadUrl:
        return "thread/" + get_url_hash(threadUrl)
    else:
        return ""

def j28PostUri(postUrl):
    """Canonicalize postURL to drop query and fragment"""
    if postUrl:
        (scheme, netloc, path, params, query, fragment) = urlparse(postUrl)
        return "post/" + get_url_hash(urlunparse( (scheme, netloc, path, params, query, "") ))
    else:
        return ""

def j28ImageUri(url):
    if url:
        return "image/" + get_url_hash(url)
    else:
        return ""

def j28FeatureProperty():
    """the name of the property"""
    pass

def j28SourceName(originalfile):
    return ".".join(originalfile.split('.')[0:-1])

J28SITEROOTS = {"airgunadvice.net": "http://www.airgunadvice.net",
                "americanpreppersnetwork.net": "http://americanpreppersnetwork.net",
                "arguntrader.com": "http://arguntrader.com",
                "claytargetclassifieds.com": "http://www.claytargetclassifieds.com",
                "comebackalive.com": "http://cafe.comebackalive.com",
                "ducksouth.com": "http://www.ducksouth.com/phpbb",
                "gobblernation.com": "http://www.gobblernation.com/phpBB3",
                "henryfirearms.org": "http://http://www.henryfirearms.org/henrybb/",
                "isthmus.com": "http://forum.isthmus.com",
                "kentuckyarmoryclub.com": "http://kentuckyarmoryclub.com",
                "levergunscommunity.com": "http://levergunscommunity.com",
                "marauderairrifle.com": "http://marauderairrifle.com/forum",
                "modernmuzzleloader.com": "http://modernmuzzleloader.com/forum",
                "newmexicoguntrader.net": "http://newmexicoguntrader.net",
                "nodakoutdoors.com": "http://nodakoutdoors.com/forums",
                "nosler.com": "http://forum.nosler.com",
                "ohioccwforums.org": "http://ohioccwforums.org",
                "pistolworld.com": "http://pistolworld.com/bbs",
                "remingtonsociety.com": "http://www.remingtonsociety.com/forums",
                "rossi-rifleman.com": "http://www.rossi-rifleman.com",
                "silencerforum.com": "http://www.silencerforum.com",
                "spokaneguntrader.com": "http://www.spokaneguntrader.com",
                "texaschlforum.com": "http://www.texaschlforum.com",
                "tfaonline.org": "http://www.tfaonline.org/forum",
                "theliberalgunclub.com": "http://www.theliberalgunclub.com/phpBB3",
                "tndeer.com": "http://www.tndeer.com/forums",
                "treasurestatearms.com": "http://www.treasurestatearms.com/phpbb3",
                "utahconcealedcarry.com": "http://www.utahconcealedcarry.com"}

HG2SITEROOTS = {"smf_abraxasgacelesox.onion": "http://www.smf_abraxasgacelesox.onion",
                "phpbb_z34uj4opd3tejafn.onion": "http://phpbb_z34uj4opd3tejafn.onion"}

## To avoid changing model, just append those new entries to original

J28SITEROOTS.update(HG2SITEROOTS)

def j28SiteRoot(sourceName):
    return J28SITEROOTS.get(sourceName, "")

# future
# def hg2SiteRoot(sourceName):
#     return HG2SITEROOTS.get(sourceName, "")

def j28ThreadLinkAbsolute(siteRoot, threadLink):
    return urljoin(siteRoot, threadLink)

def j28FcUri(uri):
    return atf_fc_uri(uri)

<|endoftext|>