text:
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ChangeListManager">
    <list default="true" id="d02fc7ca-bc62-44fe-a834-2b910136bc1b" name="Default" comment="" />
    <ignored path="python_training.iws" />
    <ignored path=".idea/workspace.xml" />
    <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
    <option name="TRACKING_ENABLED" value="true" />
    <option name="SHOW_DIALOG" value="false" />
    <option name="HIGHLIGHT_CONFLICTS" value="true" />
    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
    <option name="LAST_RESOLUTION" value="IGNORE" />
  </component>
  <component name="ChangesViewManager" flattened_view="true" show_ignored="false" />
  <component name="CreatePatchCommitExecutor">
    <option name="PATCH_PATH" value="" />
  </component>
  <component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
  <component name="FavoritesManager">
    <favorites_list name="python_training" />
  </component>
  <component name="FileEditorManager">
    <leaf>
      <file leaf-file-name="group.py" pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/fixture/group.py">
          <provider selected="true" editor-type-id="text-editor">
            <state vertical-scroll-proportion="-5.275862">
              <caret line="9" column="0" selection-start-line="9" selection-start-column="0" selection-end-line="9" selection-end-column="101" />
              <folding />
            </state>
          </provider>
        </entry>
      </file>
      <file leaf-file-name="navigation.py" pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/fixture/navigation.py">
          <provider selected="true" editor-type-id="text-editor">
            <state vertical-scroll-proportion="0.0">
              <caret line="15" column="55" selection-start-line="15" selection-start-column="55" selection-end-line="15" selection-end-column="55" />
              <folding />
            </state>
          </provider>
        </entry>
      </file>
      <file leaf-file-name="test_delete_contact.py" pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/test/test_delete_contact.py">
          <provider selected="true" editor-type-id="text-editor">
            <state vertical-scroll-proportion="0.0">
              <caret line="19" column="25" selection-start-line="19" selection-start-column="25" selection-end-line="19" selection-end-column="25" />
              <folding />
            </state>
          </provider>
        </entry>
      </file>
      <file leaf-file-name="test_edit_contact.py" pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/test/test_edit_contact.py">
          <provider selected="true" editor-type-id="text-editor">
            <state vertical-scroll-proportion="0.0">
              <caret line="50" column="19" selection-start-line="50" selection-start-column="19" selection-end-line="50" selection-end-column="19" />
              <folding />
            </state>
          </provider>
        </entry>
      </file>
      <file leaf-file-name="application.py" pinned="false" current-in-tab="true">
        <entry file="file://$PROJECT_DIR$/fixture/application.py">
          <provider selected="true" editor-type-id="text-editor">
            <state vertical-scroll-proportion="0.16776316">
              <caret line="10" column="29" selection-start-line="10" selection-start-column="29" selection-end-line="10" selection-end-column="29" />
              <folding />
            </state>
          </provider>
        </entry>
      </file>
    </leaf>
  </component>
  <component name="FileTemplateManagerImpl">
    <option name="RECENT_TEMPLATES">
      <list>
        <option value="Python Script" />
      </list>
    </option>
  </component>
  <component name="Git.Settings">
    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
  </component>
  <component name="IdeDocumentHistory">
    <option name="CHANGED_PATHS">
      <list>
        <option value="$PROJECT_DIR$/group.py" />
        <option value="$PROJECT_DIR$/contact.py" />
        <option value="$PROJECT_DIR$/test_add_group.py" />
        <option value="$PROJECT_DIR$/test_add_contact.py" />
        <option value="$PROJECT_DIR$/application.py" />
        <option value="$PROJECT_DIR$/fixture/NavigationHelper.py" />
        <option value="$PROJECT_DIR$/test/conftest.py" />
        <option value="$PROJECT_DIR$/model/group.py" />
        <option value="$PROJECT_DIR$/model/contact.py" />
        <option value="$PROJECT_DIR$/test/test_add_contact.py" />
        <option value="$PROJECT_DIR$/test/test_add_group.py" />
        <option value="$PROJECT_DIR$/fixture/session.py" />
        <option value="$PROJECT_DIR$/conftest.py" />
        <option value="$PROJECT_DIR$/test/test_delete_group.py" />
        <option value="$PROJECT_DIR$/test/test_delete_contact.py" />
        <option value="$PROJECT_DIR$/fixture/contact.py" />
        <option value="$PROJECT_DIR$/test/test_edit_group.py" />
        <option value="$PROJECT_DIR$/test/test_edit_contact.py" />
        <option value="$PROJECT_DIR$/fixture/group.py" />
        <option value="$PROJECT_DIR$/fixture/navigation.py" />
        <option value="$PROJECT_DIR$/fixture/application.py" />
      </list>
    </option>
  </component>
  <component name="NamedScopeManager">
    <order />
  </component>
  <component name="ProjectFrameBounds">
    <option name="x" value="-8" />
    <option name="y" value="-8" />
    <option name="width" value="1936" />
    <option name="height" value="1056" />
  </component>
  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
    <OptionsSetting value="true" id="Add" />
    <OptionsSetting value="true" id="Remove" />
    <OptionsSetting value="true" id="Checkout" />
    <OptionsSetting value="true" id="Update" />
    <OptionsSetting value="true" id="Status" />
    <OptionsSetting value="true" id="Edit" />
    <ConfirmationsSetting value="0" id="Add" />
    <ConfirmationsSetting value="0" id="Remove" />
  </component>
  <component name="ProjectView">
    <navigator currentView="ProjectPane" proportions="" version="1">
      <flattenPackages />
      <showMembers />
      <showModules />
      <showLibraryContents />
      <hideEmptyPackages />
      <abbreviatePackageNames />
      <autoscrollToSource />
      <autoscrollFromSource />
      <sortByType />
    </navigator>
    <panes>
      <pane id="Scratches" />
      <pane id="ProjectPane">
        <subPane>
          <PATH>
            <PATH_ELEMENT>
              <option name="myItemId" value="python_training" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
            </PATH_ELEMENT>
          </PATH>
          <PATH>
            <PATH_ELEMENT>
              <option name="myItemId" value="python_training" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
            </PATH_ELEMENT>
            <PATH_ELEMENT>
              <option name="myItemId" value="python_training" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
            </PATH_ELEMENT>
          </PATH>
          <PATH>
            <PATH_ELEMENT>
              <option name="myItemId" value="python_training" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
            </PATH_ELEMENT>
            <PATH_ELEMENT>
              <option name="myItemId" value="python_training" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
            </PATH_ELEMENT>
            <PATH_ELEMENT>
              <option name="myItemId" value="test" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
            </PATH_ELEMENT>
          </PATH>
          <PATH>
            <PATH_ELEMENT>
              <option name="myItemId" value="python_training" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
            </PATH_ELEMENT>
            <PATH_ELEMENT>
              <option name="myItemId" value="python_training" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
            </PATH_ELEMENT>
            <PATH_ELEMENT>
              <option name="myItemId" value="model" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
            </PATH_ELEMENT>
          </PATH>
          <PATH>
            <PATH_ELEMENT>
              <option name="myItemId" value="python_training" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
            </PATH_ELEMENT>
            <PATH_ELEMENT>
              <option name="myItemId" value="python_training" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
            </PATH_ELEMENT>
            <PATH_ELEMENT>
              <option name="myItemId" value="fixture" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
            </PATH_ELEMENT>
          </PATH>
        </subPane>
      </pane>
      <pane id="Scope" />
    </panes>
  </component>
  <component name="PropertiesComponent">
    <property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
    <property name="settings.editor.splitter.proportion" value="0.2" />
    <property name="recentsLimit" value="5" />
    <property name="FullScreen" value="false" />
  </component>
  <component name="RecentsManager">
    <key name="CopyFile.RECENT_KEYS">
      <recent name="H:\Alexey\github\python_training\test" />
    </key>
    <key name="MoveFile.RECENT_KEYS">
      <recent name="H:\Alexey\github\python_training" />
      <recent name="H:\Alexey\github\python_training\test" />
      <recent name="H:\Alexey\github\python_training\fixture" />
      <recent name="H:\Alexey\github\python_training\model" />
    </key>
  </component>
  <component name="RunManager" selected="Python tests.py.test in test">
    <configuration default="false" name="py.test in test_delete_group.py" type="tests" factoryName="py.test" temporary="true">
      <option name="INTERPRETER_OPTIONS" value="" />
      <option name="PARENT_ENVS" value="true" />
      <envs />
      <option name="SDK_HOME" value="" />
      <option name="WORKING_DIRECTORY" value="" />
      <option name="IS_MODULE_SDK" value="true" />
      <option name="ADD_CONTENT_ROOTS" value="true" />
      <option name="ADD_SOURCE_ROOTS" value="true" />
      <module name="python_training" />
      <option name="SCRIPT_NAME" value="" />
      <option name="CLASS_NAME" value="" />
      <option name="METHOD_NAME" value="" />
      <option name="FOLDER_NAME" value="" />
      <option name="TEST_TYPE" value="TEST_SCRIPT" />
      <option name="PATTERN" value="" />
      <option name="USE_PATTERN" value="false" />
      <option name="testToRun" value="$PROJECT_DIR$/test/test_delete_group.py" />
      <option name="keywords" value="" />
      <option name="params" value="" />
      <option name="USE_PARAM" value="false" />
      <option name="USE_KEYWORD" value="false" />
      <method />
    </configuration>
    <configuration default="false" name="py.test in test" type="tests" factoryName="py.test" temporary="true">
      <option name="INTERPRETER_OPTIONS" value="" />
      <option name="PARENT_ENVS" value="true" />
      <envs />
      <option name="SDK_HOME" value="" />
      <option name="WORKING_DIRECTORY" value="" />
      <option name="IS_MODULE_SDK" value="true" />
      <option name="ADD_CONTENT_ROOTS" value="true" />
      <option name="ADD_SOURCE_ROOTS" value="true" />
      <module name="python_training" />
      <option name="SCRIPT_NAME" value="" />
      <option name="CLASS_NAME" value="" />
      <option name="METHOD_NAME" value="" />
      <option name="FOLDER_NAME" value="" />
      <option name="TEST_TYPE" value="TEST_SCRIPT" />
      <option name="PATTERN" value="" />
      <option name="USE_PATTERN" value="false" />
      <option name="testToRun" value="$PROJECT_DIR$/test" />
      <option name="keywords" value="" />
      <option name="params" value="" />
      <option name="USE_PARAM" value="false" />
      <option name="USE_KEYWORD" value="false" />
      <method />
    </configuration>
    <configuration default="false" name="py.test in test_edit_contact.py" type="tests" factoryName="py.test" temporary="true">
      <option name="INTERPRETER_OPTIONS" value="" />
      <option name="PARENT_ENVS" value="true" />
      <envs />
      <option name="SDK_HOME" value="" />
      <option name="WORKING_DIRECTORY" value="" />
      <option name="IS_MODULE_SDK" value="true" />
      <option name="ADD_CONTENT_ROOTS" value="true" />
      <option name="ADD_SOURCE_ROOTS" value="true" />
      <module name="python_training" />
      <option name="SCRIPT_NAME" value="" />
      <option name="CLASS_NAME" value="" />
      <option name="METHOD_NAME" value="" />
      <option name="FOLDER_NAME" value="" />
      <option name="TEST_TYPE" value="TEST_SCRIPT" />
      <option name="PATTERN" value="" />
      <option name="USE_PATTERN" value="false" />
      <option name="testToRun" value="$PROJECT_DIR$/test/test_edit_contact.py" />
      <option name="keywords" value="" />
      <option name="params" value="" />
      <option name="USE_PARAM" value="false" />
      <option name="USE_KEYWORD" value="false" />
      <method />
    </configuration>
    <configuration default="false" name="py.test in test_edit_group.py" type="tests" factoryName="py.test" temporary="true">
      <option name="INTERPRETER_OPTIONS" value="" />
      <option name="PARENT_ENVS" value="true" />
      <envs />
      <option name="SDK_HOME" value="" />
      <option name="WORKING_DIRECTORY" value="" />
      <option name="IS_MODULE_SDK" value="true" />
      <option name="ADD_CONTENT_ROOTS" value="true" />
      <option name="ADD_SOURCE_ROOTS" value="true" />
      <module name="python_training" />
      <option name="SCRIPT_NAME" value="" />
      <option name="CLASS_NAME" value="" />
      <option name="METHOD_NAME" value="" />
      <option name="FOLDER_NAME" value="" />
      <option name="TEST_TYPE" value="TEST_SCRIPT" />
      <option name="PATTERN" value="" />
      <option name="USE_PATTERN" value="false" />
      <option name="testToRun" value="$PROJECT_DIR$/test/test_edit_group.py" />
      <option name="keywords" value="" />
      <option name="params" value="" />
      <option name="USE_PARAM" value="false" />
      <option name="USE_KEYWORD" value="false" />
      <method />
    </configuration>
    <configuration default="false" name="py.test in test_add_group.py (1)" type="tests" factoryName="py.test" temporary="true">
      <option name="INTERPRETER_OPTIONS" value="" />
      <option name="PARENT_ENVS" value="true" />
      <envs />
      <option name="SDK_HOME" value="" />
      <option name="WORKING_DIRECTORY" value="" />
      <option name="IS_MODULE_SDK" value="true" />
      <option name="ADD_CONTENT_ROOTS" value="true" />
      <option name="ADD_SOURCE_ROOTS" value="true" />
      <module name="python_training" />
      <option name="SCRIPT_NAME" value="" />
      <option name="CLASS_NAME" value="" />
      <option name="METHOD_NAME" value="" />
      <option name="FOLDER_NAME" value="" />
      <option name="TEST_TYPE" value="TEST_SCRIPT" />
      <option name="PATTERN" value="" />
      <option name="USE_PATTERN" value="false" />
      <option name="testToRun" value="$PROJECT_DIR$/test/test_add_group.py" />
      <option name="keywords" value="" />
      <option name="params" value="" />
      <option name="USE_PARAM" value="false" />
      <option name="USE_KEYWORD" value="false" />
      <method />
    </configuration>
    <configuration default="true" type="PythonConfigurationType" factoryName="Python">
      <option name="INTERPRETER_OPTIONS" value="" />
      <option name="PARENT_ENVS" value="true" />
      <envs>
        <env name="PYTHONUNBUFFERED" value="1" />
      </envs>
      <option name="SDK_HOME" value="" />
      <option name="WORKING_DIRECTORY" value="" />
      <option name="IS_MODULE_SDK" value="false" />
      <option name="ADD_CONTENT_ROOTS" value="true" />
      <option name="ADD_SOURCE_ROOTS" value="true" />
      <module name="python_training" />
      <option name="SCRIPT_NAME" value="" />
      <option name="PARAMETERS" value="" />
      <option name="SHOW_COMMAND_LINE" value="false" />
      <method />
    </configuration>
    <configuration default="true" type="tests" factoryName="Attests">
      <option name="INTERPRETER_OPTIONS" value="" />
      <option name="PARENT_ENVS" value="true" />
      <envs />
      <option name="SDK_HOME" value="" />
      <option name="WORKING_DIRECTORY" value="" />
      <option name="IS_MODULE_SDK" value="false" />
      <option name="ADD_CONTENT_ROOTS" value="true" />
      <option name="ADD_SOURCE_ROOTS" value="true" />
      <module name="python_training" />
      <option name="SCRIPT_NAME" value="" />
      <option name="CLASS_NAME" value="" />
      <option name="METHOD_NAME" value="" />
      <option name="FOLDER_NAME" value="" />
      <option name="TEST_TYPE" value="TEST_SCRIPT" />
      <option name="PATTERN" value="" />
      <option name="USE_PATTERN" value="false" />
      <method />
    </configuration>
    <configuration default="true" type="tests" factoryName="Doctests">
      <option name="INTERPRETER_OPTIONS" value="" />
      <option name="PARENT_ENVS" value="true" />
      <envs />
      <option name="SDK_HOME" value="" />
      <option name="WORKING_DIRECTORY" value="" />
      <option name="IS_MODULE_SDK" value="false" />
      <option name="ADD_CONTENT_ROOTS" value="true" />
      <option name="ADD_SOURCE_ROOTS" value="true" />
      <module name="python_training" />
      <option name="SCRIPT_NAME" value="" />
      <option name="CLASS_NAME" value="" />
      <option name="METHOD_NAME" value="" />
      <option name="FOLDER_NAME" value="" />
      <option name="TEST_TYPE" value="TEST_SCRIPT" />
      <option name="PATTERN" value="" />
      <option name="USE_PATTERN" value="false" />
      <method />
    </configuration>
    <configuration default="true" type="tests" factoryName="Nosetests">
      <option name="INTERPRETER_OPTIONS" value="" />
      <option name="PARENT_ENVS" value="true" />
      <envs />
      <option name="SDK_HOME" value="" />
      <option name="WORKING_DIRECTORY" value="" />
      <option name="IS_MODULE_SDK" value="false" />
      <option name="ADD_CONTENT_ROOTS" value="true" />
      <option name="ADD_SOURCE_ROOTS" value="true" />
      <module name="python_training" />
      <option name="SCRIPT_NAME" value="" />
      <option name="CLASS_NAME" value="" />
      <option name="METHOD_NAME" value="" />
      <option name="FOLDER_NAME" value="" />
      <option name="TEST_TYPE" value="TEST_SCRIPT" />
      <option name="PATTERN" value="" />
      <option name="USE_PATTERN" value="false" />
      <option name="PARAMS" value="" />
      <option name="USE_PARAM" value="false" />
      <method />
    </configuration>
    <configuration default="true" type="tests" factoryName="Unittests">
      <option name="INTERPRETER_OPTIONS" value="" />
      <option name="PARENT_ENVS" value="true" />
      <envs />
      <option name="SDK_HOME" value="" />
      <option name="WORKING_DIRECTORY" value="" />
      <option name="IS_MODULE_SDK" value="false" />
      <option name="ADD_CONTENT_ROOTS" value="true" />
      <option name="ADD_SOURCE_ROOTS" value="true" />
      <module name="python_training" />
      <option name="SCRIPT_NAME" value="" />
      <option name="CLASS_NAME" value="" />
      <option name="METHOD_NAME" value="" />
      <option name="FOLDER_NAME" value="" />
      <option name="TEST_TYPE" value="TEST_SCRIPT" />
      <option name="PATTERN" value="" />
      <option name="USE_PATTERN" value="false" />
      <option name="PUREUNITTEST" value="true" />
      <option name="PARAMS" value="" />
      <option name="USE_PARAM" value="false" />
      <method />
    </configuration>
    <configuration default="true" type="tests" factoryName="py.test">
      <option name="INTERPRETER_OPTIONS" value="" />
      <option name="PARENT_ENVS" value="true" />
      <envs />
      <option name="SDK_HOME" value="" />
      <option name="WORKING_DIRECTORY" value="" />
      <option name="IS_MODULE_SDK" value="false" />
      <option name="ADD_CONTENT_ROOTS" value="true" />
      <option name="ADD_SOURCE_ROOTS" value="true" />
      <module name="python_training" />
      <option name="SCRIPT_NAME" value="" />
      <option name="CLASS_NAME" value="" />
      <option name="METHOD_NAME" value="" />
      <option name="FOLDER_NAME" value="" />
      <option name="TEST_TYPE" value="TEST_SCRIPT" />
      <option name="PATTERN" value="" />
      <option name="USE_PATTERN" value="false" />
      <option name="testToRun" value="" />
      <option name="keywords" value="" />
      <option name="params" value="" />
      <option name="USE_PARAM" value="false" />
      <option name="USE_KEYWORD" value="false" />
      <method />
    </configuration>
    <configuration default="false" name="py.test in test_add_group.py" type="tests" factoryName="py.test">
      <option name="INTERPRETER_OPTIONS" value="" />
      <option name="PARENT_ENVS" value="true" />
      <envs />
      <option name="SDK_HOME" value="" />
      <option name="WORKING_DIRECTORY" value="" />
      <option name="IS_MODULE_SDK" value="true" />
      <option name="ADD_CONTENT_ROOTS" value="true" />
      <option name="ADD_SOURCE_ROOTS" value="true" />
      <module name="python_training" />
      <option name="SCRIPT_NAME" value="" />
      <option name="CLASS_NAME" value="" />
      <option name="METHOD_NAME" value="" />
      <option name="FOLDER_NAME" value="" />
      <option name="TEST_TYPE" value="TEST_SCRIPT" />
      <option name="PATTERN" value="" />
      <option name="USE_PATTERN" value="false" />
      <option name="testToRun" value="$PROJECT_DIR$/test_add_group.py" />
      <option name="keywords" value="" />
      <option name="params" value="" />
      <option name="USE_PARAM" value="false" />
      <option name="USE_KEYWORD" value="false" />
      <method />
    </configuration>
    <list size="6">
      <item index="0" class="java.lang.String" itemvalue="Python tests.py.test in test_add_group.py" />
      <item index="1" class="java.lang.String" itemvalue="Python tests.py.test in test_delete_group.py" />
      <item index="2" class="java.lang.String" itemvalue="Python tests.py.test in test" />
      <item index="3" class="java.lang.String" itemvalue="Python tests.py.test in test_edit_contact.py" />
      <item index="4" class="java.lang.String" itemvalue="Python tests.py.test in test_edit_group.py" />
      <item index="5" class="java.lang.String" itemvalue="Python tests.py.test in test_add_group.py (1)" />
    </list>
    <recent_temporary>
      <list size="5">
        <item index="0" class="java.lang.String" itemvalue="Python tests.py.test in test" />
        <item index="1" class="java.lang.String" itemvalue="Python tests.py.test in test_delete_group.py" />
        <item index="2" class="java.lang.String" itemvalue="Python tests.py.test in test_edit_group.py" />
        <item index="3" class="java.lang.String" itemvalue="Python tests.py.test in test_add_group.py (1)" />
        <item index="4" class="java.lang.String" itemvalue="Python tests.py.test in test_edit_contact.py" />
      </list>
    </recent_temporary>
  </component>
  <component name="ShelveChangesManager" show_recycled="false" />
  <component name="SvnConfiguration">
    <configuration />
  </component>
  <component name="TaskManager">
    <task active="true" id="Default" summary="Default task">
      <changelist id="d02fc7ca-bc62-44fe-a834-2b910136bc1b" name="Default" comment="" />
      <created>1438542578519</created>
      <option name="number" value="Default" />
      <updated>1438542578519</updated>
    </task>
    <servers />
  </component>
  <component name="ToolWindowManager">
    <frame x="-8" y="-8" width="1936" height="1056" extended-state="0" />
    <editor active="true" />
    <layout>
      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.24895833" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
      <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
      <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
      <window_info id="Application Servers" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
      <window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32911393" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
      <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
      <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.32911393" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
      <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
      <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
      <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
      <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.39978904" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
      <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
      <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
      <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
      <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
      <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32911393" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
      <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
    </layout>
  </component>
  <component name="Vcs.Log.UiProperties">
    <option name="RECENTLY_FILTERED_USER_GROUPS">
      <collection />
    </option>
    <option name="RECENTLY_FILTERED_BRANCH_GROUPS">
      <collection />
    </option>
  </component>
  <component name="VcsContentAnnotationSettings">
    <option name="myLimit" value="2678400000" />
  </component>
  <component name="XDebuggerManager">
    <breakpoint-manager>
      <breakpoints>
        <line-breakpoint enabled="true" type="python-line">
          <url>file://$PROJECT_DIR$/test/test_add_contact.py</url>
          <line>5</line>
          <option name="timeStamp" value="2" />
        </line-breakpoint>
        <line-breakpoint enabled="true" type="python-line">
          <url>file://$PROJECT_DIR$/test/test_add_group.py</url>
          <line>4</line>
          <option name="timeStamp" value="3" />
        </line-breakpoint>
        <line-breakpoint enabled="true" type="python-line">
          <url>file://$PROJECT_DIR$/test/test_add_group.py</url>
          <line>8</line>
          <option name="timeStamp" value="4" />
        </line-breakpoint>
      </breakpoints>
      <option name="time" value="7" />
    </breakpoint-manager>
    <watches-manager>
      <configuration name="tests">
        <watch expression="len(wd.find_elements_by_name("selected[]"))" language="Python" />
      </configuration>
    </watches-manager>
  </component>
  <component name="editorHistoryManager">
    <entry file="file://$PROJECT_DIR$/test/test_delete_contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="6" column="0" selection-start-line="6" selection-start-column="0" selection-end-line="10" selection-end-column="194" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="13" column="0" selection-start-line="13" selection-start-column="0" selection-end-line="13" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/fixture/application.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="15" column="47" selection-start-line="15" selection-start-column="47" selection-end-line="15" selection-end-column="47" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/fixture/navigation.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="11" column="0" selection-start-line="11" selection-start-column="0" selection-end-line="11" selection-end-column="0" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_delete_group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="3" column="0" selection-start-line="3" selection-start-column="0" selection-end-line="3" selection-end-column="0" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/fixture/group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="31" column="31" selection-start-line="31" selection-start-column="31" selection-end-line="31" selection-end-column="31" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/conftest.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/fixture/contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="26" column="50" selection-start-line="26" selection-start-column="50" selection-end-line="26" selection-end-column="50" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/fixture/session.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="8" column="35" selection-start-line="8" selection-start-column="35" selection-end-line="8" selection-end-column="35" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/model/group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="8" column="28" selection-start-line="8" selection-start-column="28" selection-end-line="8" selection-end-column="28" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="2" column="0" selection-start-line="2" selection-start-column="0" selection-end-line="2" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/fixture/application.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="32" column="0" selection-start-line="32" selection-start-column="0" selection-end-line="32" selection-end-column="0" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/model/contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="32" column="36" selection-start-line="32" selection-start-column="36" selection-end-line="32" selection-end-column="36" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/model/group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="8" column="28" selection-start-line="8" selection-start-column="28" selection-end-line="8" selection-end-column="28" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="21" column="0" selection-start-line="21" selection-start-column="0" selection-end-line="21" selection-end-column="54" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/model/contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="32" column="36" selection-start-line="32" selection-start-column="36" selection-end-line="32" selection-end-column="36" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/model/group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="8" column="28" selection-start-line="8" selection-start-column="28" selection-end-line="8" selection-end-column="28" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/model/group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="8" column="28" selection-start-line="8" selection-start-column="28" selection-end-line="8" selection-end-column="28" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/model/group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="8" column="28" selection-start-line="8" selection-start-column="28" selection-end-line="8" selection-end-column="28" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/model/group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="8" column="28" selection-start-line="8" selection-start-column="28" selection-end-line="8" selection-end-column="28" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/model/group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="8" column="28" selection-start-line="8" selection-start-column="28" selection-end-line="8" selection-end-column="28" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/model/group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="8" column="28" selection-start-line="8" selection-start-column="28" selection-end-line="8" selection-end-column="28" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/env/Lib/site-packages/selenium/webdriver/remote/switch_to.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="46" column="42" selection-start-line="46" selection-start-column="42" selection-end-line="46" selection-end-column="42" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/env/Lib/site-packages/selenium/webdriver/common/alert.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.24835527">
          <caret line="66" column="8" selection-start-line="66" selection-start-column="8" selection-end-line="66" selection-end-column="15" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/model/contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.81085527">
          <caret line="29" column="29" selection-start-line="29" selection-start-column="29" selection-end-line="29" selection-end-column="29" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="20" column="0" selection-start-line="20" selection-start-column="0" selection-end-line="20" selection-end-column="0" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/model/group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="8" column="0" selection-start-line="8" selection-start-column="0" selection-end-line="8" selection-end-column="0" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/env/Lib/site-packages/_pytest/python.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="1180" column="0" selection-start-line="1180" selection-start-column="0" selection-end-line="1180" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/env/Lib/site-packages/_pytest/runner.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="89" column="0" selection-start-line="89" selection-start-column="0" selection-end-line="89" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/env/Lib/site-packages/_pytest/core.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="520" column="0" selection-start-line="520" selection-start-column="0" selection-end-line="520" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/fixture/session.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="22" column="51" selection-start-line="22" selection-start-column="51" selection-end-line="22" selection-end-column="51" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/1">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="30" column="8" selection-start-line="30" selection-start-column="8" selection-end-line="30" selection-end-column="58" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/fixture/contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="82" column="58" selection-start-line="82" selection-start-column="58" selection-end-line="82" selection-end-column="58" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_edit_group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.7269737">
          <caret line="26" column="0" selection-start-line="26" selection-start-column="0" selection-end-line="26" selection-end-column="0" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_delete_group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.4194079">
          <caret line="15" column="24" selection-start-line="15" selection-start-column="24" selection-end-line="15" selection-end-column="24" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_delete_contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="19" column="25" selection-start-line="19" selection-start-column="25" selection-end-line="19" selection-end-column="25" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_add_group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.1118421">
          <caret line="4" column="0" selection-start-line="4" selection-start-column="0" selection-end-line="4" selection-end-column="0" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/conftest.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.6430921">
          <caret line="24" column="18" selection-start-line="24" selection-start-column="18" selection-end-line="24" selection-end-column="18" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/test/test_edit_contact.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="50" column="19" selection-start-line="50" selection-start-column="19" selection-end-line="50" selection-end-column="19" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/fixture/group.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="-5.275862">
          <caret line="9" column="0" selection-start-line="9" selection-start-column="0" selection-end-line="9" selection-end-column="101" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/fixture/navigation.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0">
          <caret line="15" column="55" selection-start-line="15" selection-start-column="55" selection-end-line="15" selection-end-column="55" />
          <folding />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/fixture/application.py">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.16776316">
          <caret line="10" column="29" selection-start-line="10" selection-start-column="29" selection-end-line="10" selection-end-column="29" />
          <folding />
        </state>
      </provider>
    </entry>
  </component>
</project>


text:
import sqlite3
from flask import Flask, request, session, g, redirect, url_for, \
    abort, render_template, flash
from queries import *
from functools import wraps
from contextlib import closing
from wtforms import SelectField, PasswordField, validators
from flask_wtf import Form
from flask_wtf.file import FileField, FileRequired, FileAllowed
from os import urandom, path
import uuid
import pandas as pd

PERSON_COLS = (14, 0, 1 ,4, 2, 3, 8, 5, 7, 6, 9, 10, 11)

app = Flask(__name__)

if path.exists("deploy_conf.py"):
    app.config.from_pyfile("deploy_conf.py")
    print("Using deploy configuration...")
else:
    app.config.from_pyfile("config.py")
    print("Using mock configuration...")

# The forms
###########
rating_validator = validators.AnyOf(['0', '1', '2', '3', '4'],
    message="You forgot to select an option")

class LoginForm(Form):
    token = PasswordField('Enter your Token:', [validators.Required(),
    validators.AnyOf(app.config['USERS'].keys(), message="Invalid token!")])

class PersonForm(Form):
    pos = SelectField('What do YOU think is the position of the applicant?',
    [rating_validator], choices=[('100', 'Pick one..'), ('0', 'Undergrad'),
    ('1', 'M.Sc./Ph.D. student or health pro.'),
    ('2', 'Postdoc, Associate Prof. or M.D.'), ('3', 'Principal Investigator')])
    inst = SelectField('How do you rate the institution?', [rating_validator],
    choices=[('100', 'Pick one..'), ('0', 'dubious'), ('1', 'average'),
    ('2', 'national leader'), ('3', 'international leader')])
    dist = SelectField('How do you rate the travel distance?', [rating_validator],
    choices=[('100', 'Pick one..'), ('0', 'local'), ('1', 'national'),
    ('2', 'international')])
    topic = SelectField('How do you rate the research topic?',
    [rating_validator], choices=[('100', 'Pick one..'), ('0', '0 - bad'),
    ('1', '1 - average'), ('2', '2 - amazing')])

class AbstractForm(Form):
    abstract = SelectField('How do you rate the abstract(s)?', [rating_validator],
    choices=[('100', 'Pick one..'), ('0', '0 - insufficient'), ('1', '1 - barely acceptable'),
    ('2', '2 - acceptable'), ('3', '3 - pretty good'), ('4', '4 - amazing')])
    english = SelectField('How do you rate the quality of English?', [rating_validator],
    choices=[('100', 'Pick one..'), ('0', 'insufficient'), ('1', 'acceptable'),
    ('2', 'fluent')])

class ImportForm(Form):
    persons = FileField('Choose an applicant file', [FileAllowed(['.csv'])])
    posters = FileField('Choose a poster abstracts file', [FileAllowed(['.csv'])])
    talks = FileField('Choose a talk abstracts file', [FileAllowed(['.csv'])])
###########

# Utility functions
###########
def connect_db():
    return sqlite3.connect(app.config['DATABASE'])

def add_fakes(db, n, base_id=1):
    from faker import Faker
    fake = Faker()
    for i in range(n):
        vals = (str(base_id+i), fake.first_name(), fake.last_name(), fake.email(),
            'NA', fake.date(), fake.military_ship(), fake.company(), fake.state(),
            fake.country(), 'Ph.D.', fake.job(), fake.sentence(), fake.sentence(),
            fake.text(750), fake.name(), fake.company(), fake.sentence(),
            fake.text(450), fake.name(), fake.company())
        db.execute(insert_complete, vals)
    db.commit()

def init_db(n=0):
    with closing(connect_db()) as db:
        with app.open_resource('schema.sql', mode='r') as f:
            db.cursor().executescript(f.read())
        if n > 0: add_fakes(db, n)

def make_token(n, word=None):
    if word:
        return uuid.uuid5(uuid.NAMESPACE_DNS, word + app.config['SECRET_KEY']).hex[0:n]
    return uuid.uuid4().hex[0:n]

def tokenize(users):
    return {make_token(16, u[0]): u for u in users}

@app.before_request
def before_request():
    g.db = connect_db()

@app.teardown_request
def teardown_request(exception):
    db = getattr(g, 'db', None)
    if db is not None:
        db.close()

def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not 'user' in session:
            return redirect(url_for('login'))
        return f(*args, **kwargs)
    return decorated_function
#########3

# Routes
@app.route('/login', methods=['POST', 'GET'])
def login():
    form = LoginForm(request.form)
    if request.method == 'POST' and form.validate():
        token = form.token.data
        session['user'] = app.config['USERS'][token][0]
        session['role'] = app.config['USERS'][token][1]
        session['rated'] = 0
        session['p'] = None     # next applicant to review
        session['a'] = None     # next abstract to review
        flash('Thank you. Logging in...')
        return redirect(url_for('show_entries'))
    return render_template('login.html', form=form, n_user=len(app.config['USERS']))

@app.route('/')
@login_required
def show_entries():
    data = {}
    cur = g.db.execute(review_count, (session['user'],))
    data['nrev'] = cur.fetchone()[0]
    cur = g.db.execute("select count(*) from ratings")
    data['ntotrev'] = cur.fetchone()[0]
    cur = g.db.execute("select count(*) from abstracts")
    data['nabstotrev'] = cur.fetchone()[0]
    cur = g.db.execute(person_count)
    data['ntot'] = cur.fetchone()[0]
    cur = g.db.execute(abstract_count)
    data['nabstot'] = cur.fetchone()[0]
    cur = g.db.execute(abstract_rev_count, (session['user'],))
    data['nabsrev'] = cur.fetchone()[0]
    return render_template('index.html',user=session['user'],
        role=session['role'], **data)

@app.route('/logout')
def logout():
    session.pop('user', None)
    session.pop('role', None)
    session.pop('rated', None)
    flash('You were logged out')
    return redirect(url_for('login'))

@app.route('/applicants', methods=['GET', 'POST'])
@login_required
def rate_person():
    if request.method == 'GET':
        cur = g.db.execute(next_person, (session['user'],))
        session['p'] = cur.fetchone()
    form = PersonForm(request.form)
    if request.method == 'POST' and form.validate() and session['p']:
        g.db.execute(insert_person_rating, (session['p'][0], session['user'],
            form.pos.data, form.inst.data, form.dist.data, form.topic.data))
        g.db.commit()
        session['rated'] += 1
        return redirect(url_for('added', type='applicant'))
    return render_template('applicants.html', form=form, p=session['p'],
        user=session['user'], role=session['role'])

@app.route('/abstracts', methods=['GET', 'POST'])
@login_required
def rate_abstract():
    if session['role'] != 'all':
        return render_template('message.html', type='error', title='Nope...',
            message='You are not allowed to review abstracts :(',
            user=session['user'], role=session['role'])
    if request.method == 'GET':
        cur = g.db.execute(next_abstract, (session['user'],))
        session['a'] = cur.fetchone()
    form = AbstractForm(request.form)
    if request.method == 'POST' and form.validate() and session['a']:
        g.db.execute(insert_abstract_rating, (session['a'][0], session['user'],
            form.abstract.data, form.english.data))
        g.db.commit()
        session['rated'] += 1
        return redirect(url_for('added', type='abstract'))
    return render_template('abstracts.html', form=form, a=session['a'],
        user=session['user'], role=session['role'])

@app.route('/added/<type>')
@login_required
def added(type):
    return render_template('added.html', rated=session['rated'],
        user=session['user'], role=session['role'], type=type)

@app.route('/results')
@login_required
def results():
    persons = pd.read_sql("select * from persons", g.db)
    ratings = pd.read_sql(average_ratings, g.db)
    abstracts = pd.read_sql(average_abstracts, g.db)
    persons = pd.merge(persons, ratings, on='pid', how='left')
    persons = pd.merge(persons, abstracts, on='pid', how='left', suffixes=('_applicant', '_abstract'))

    persons["total"] = persons[['p_position', 'p_institution', 'p_distance',
        'p_topic', 'p_abstract']].sum(axis=1).fillna(0)
    persons = persons.sort_values(by="total", ascending=False)
    persons.to_csv('static/res.csv', encoding='utf-8')
    table = zip(range(1,persons.shape[0]+1), persons['first'] + ' ' + persons['last'],
        persons['institution'], persons['country'],
        persons['nrev_applicant'].fillna(0).astype(int).astype(str) +
        ' + ' + persons['nrev_abstract'].fillna(0).astype(int).astype(str),
        persons['total'].round(2))
    return render_template('results.html', table=table, user=session['user'],
        role=session['role'])

@app.route('/import', methods=['POST', 'GET'])
@login_required
def file_import():
    if session['role'] != 'all':
        return render_template('message.html', type='error', title='Nope...',
            message='You are not allowed to import data :(',
            user=session['user'], role=session['role'])
    form = ImportForm(request.form)
    if request.method == 'POST' and form.validate():
        try:
            p = pd.read_csv(request.files['persons'], skipinitialspace=True).fillna("NA")
            a_posters = pd.read_csv(request.files['posters'])
            a_talks = pd.read_csv(request.files['talks'])
            if p.shape[1] != 15:
                raise ValueError("Wrong numbers of columns in applicant data!")
            elif a_posters.shape[1] != 7:
                raise ValueError("Wrong numbers of columns in poster data!")
            elif a_talks.shape[1] != 8:
                raise ValueError("Wrong numbers of columns in talk data!")
        except BaseException as e:
            msg = 'Could not parse the files. Please ensure that the uploaded \
            files are CSV files that can be read by pandas. Error: ' + str(e)
            return render_template('message.html', type='error', title='Parse error',
                message=msg, user=session['user'], role=session['role'])
        p.ix[:, 4] = p.ix[:, 4].str.strip().str.lower()
        p.ix[:, 14] = p.ix[:, 14].astype('str')

        inserter = zip(*[p.ix[:,i] for i in PERSON_COLS])
        g.db.executemany(insert_person, inserter)
        g.db.commit()
        cur = g.db.execute(all_emails)
        emails = [e[0] for e in cur.fetchall()]
        a_posters['Email'] = a_posters['Email'].str.strip().str.lower()
        a_talks['Email'] = a_talks['Email'].str.strip().str.lower()
        a_posters['matched'] = a_posters['Email'].isin(emails)
        a_talks['matched'] = a_talks['Email'].isin(emails)

        # The weird order and columns is due to errors in the form
        # design which we can not alter anymore
        a = a_posters.loc[a_posters.matched]
        inserter = zip(a.ix[:,3], a.ix[:,4], a.ix[:,6], a.ix[:,5], a.ix[:,2])
        g.db.executemany(update_poster, inserter)
        a = a_talks.loc[a_talks.matched]
        inserter = zip(a.ix[:,3], a.ix[:,4], a.ix[:,5], a.ix[:,6], a.ix[:,2])
        g.db.executemany(update_talk, inserter)
        g.db.commit()
        cur = g.db.execute(person_count)
        n = cur.fetchone()[0]
        emails_not_found = a_posters.loc[a_posters.matched == False]['Email'].append(
            a_talks.loc[a_talks.matched == False]['Email'])
        emails_not_found = emails_not_found.unique()
        msg = '{} applicants in the database. Unmatched Emails ({}): {}'.format(
            n, len(emails_not_found), ', '.join(emails_not_found))
        return render_template('message.html', type='good', title='Added new data',
            message=msg, user=session['user'], role=session['role'])
    return render_template('import.html', form=form, user=session['user'],
        role=session['role'])

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=8000, debug=True)

redpajama_set_name: RedPajamaGithub


text:
require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'

class <%= class_name %>Test < Test::Unit::TestCase
  fixtures :<%= table_name %>

  # Replace this with your real tests.
  def test_truth
    assert_kind_of <%= class_name %>, <%= table_name %>(:first)
  end
end


text:
var types = require('../../types');
var errors = require('../../errors');

function encode(obj) {
    for (var name in types) {
        if (!types.hasOwnProperty(name)) continue;

        var type = types[name];
        if (type.matches && type.matches(obj) && type.toJSON) {
            return type.toJSON(obj, encode);
        }
    }
    errors.typeError("Cannot serialize JSON structure");
}

exports.name = "json_encode";
exports.call = function(obj) {
    return JSON.stringify(encode(obj));
};


text:
using namespace std;
using namespace Eigen;
using namespace drake;

using drake::math::autoDiffToGradientMatrix;
using drake::math::autoDiffToValueMatrix;
using drake::math::expmap2quat;
using drake::math::initializeAutoDiff;

pair<Vector4d, typename Gradient<Vector4d, 3>::type> expmap2quatWithGradient(
    const MatrixBase<Map<const Vector3d>>& expmap) {
  auto expmap_autodiff = initializeAutoDiff(expmap);
  auto quat_autodiff = expmap2quat(expmap_autodiff);
  return make_pair(autoDiffToValueMatrix(quat_autodiff),
                   autoDiffToGradientMatrix(quat_autodiff));
}

tuple<Vector4d, typename Gradient<Vector4d, 3>::type,
      typename Gradient<Vector4d, 3, 2>::type>
expmap2quatWithSecondDeriv(const MatrixBase<Map<const Vector3d>>& expmap) {
  auto expmap_autodiff = initializeAutoDiff(expmap);
  auto expmap_autodiff_second = initializeAutoDiff(expmap_autodiff);
  auto quat_autodiff_second = expmap2quat(expmap_autodiff_second);
  auto quat =
      autoDiffToValueMatrix(autoDiffToValueMatrix(quat_autodiff_second));
  auto dquat_autodiff = autoDiffToGradientMatrix(quat_autodiff_second);
  auto dquat = autoDiffToValueMatrix(dquat_autodiff);
  auto ddquat = autoDiffToGradientMatrix(dquat_autodiff);
  return make_tuple(quat, dquat, ddquat);
}

void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {
  if (nlhs == 1) {
    auto func_double = make_function(&expmap2quat<Map<const Vector3d>>);
    mexCallFunction(nlhs, plhs, nrhs, prhs, true, func_double);
  } else if (nlhs == 2) {
    auto func_gradient = make_function(&expmap2quatWithGradient);
    mexCallFunction(nlhs, plhs, nrhs, prhs, true, func_gradient);
  } else if (nlhs == 3) {
    auto func_second_deriv = make_function(&expmap2quatWithSecondDeriv);
    mexCallFunction(nlhs, plhs, nrhs, prhs, true, func_second_deriv);
  } else {
    throw std::runtime_error(
        "can't handle requested number of output arguments");
  }
}


text:
package net.nitroshare.android.transfer;

import android.content.Context;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.util.Log;

import net.nitroshare.android.R;
import net.nitroshare.android.discovery.Device;
import net.nitroshare.android.util.Settings;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

/**
 * Listen for new connections and create Transfers for them
 */
class TransferServer implements Runnable {

    private static final String TAG = "TransferServer";

    interface Listener {
        void onNewTransfer(Transfer transfer);
    }

    private Thread mThread = new Thread(this);
    private boolean mStop;

    private Context mContext;
    private Listener mListener;
    private TransferNotificationManager mTransferNotificationManager;
    private Settings mSettings;
    private Selector mSelector = Selector.open();

    private NsdManager.RegistrationListener mRegistrationListener =
            new NsdManager.RegistrationListener() {
        @Override
        public void onServiceRegistered(NsdServiceInfo serviceInfo) {
            Log.i(TAG, "service registered");
        }

        @Override
        public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
            Log.i(TAG, "service unregistered");
        }
        @Override
        public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
            Log.e(TAG, String.format("registration failed: %d", errorCode));
        }

        @Override
        public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
            Log.e(TAG, String.format("unregistration failed: %d", errorCode));
        }
    };

    /**
     * Create a new transfer server
     * @param context context for retrieving string resources
     * @param transferNotificationManager notification manager
     * @param listener callback for new transfers
     */
    TransferServer(Context context, TransferNotificationManager transferNotificationManager, Listener listener) throws IOException {
        mContext = context;
        mTransferNotificationManager = transferNotificationManager;
        mListener = listener;
        mSettings = new Settings(context);
    }

    /**
     * Start the server if it is not already running
     */
    void start() {
        if (!mThread.isAlive()) {
            mStop = false;
            mThread.start();
        }
    }

    /**
     * Stop the transfer server if it is running and wait for it to finish
     */
    void stop() {
        if (mThread.isAlive()) {
            mStop = true;
            mSelector.wakeup();
            try {
                mThread.join();
            } catch (InterruptedException e) {
                Log.e(TAG, e.getMessage());
            }
        }
    }

    // TODO: this method could use some refactoring

    @Override
    public void run() {
        Log.i(TAG, "starting server...");

        // Inform the notification manager that the server has started
        mTransferNotificationManager.startListening();

        NsdManager nsdManager = null;

        try {
            // Create a server and attempt to bind to a port
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.socket().bind(new InetSocketAddress(40818));
            serverSocketChannel.configureBlocking(false);

            Log.i(TAG, String.format("server bound to port %d",
                    serverSocketChannel.socket().getLocalPort()));

            // Register the service
            nsdManager = (NsdManager) mContext.getSystemService(Context.NSD_SERVICE);
            nsdManager.registerService(
                    new Device(
                            mSettings.getString(Settings.Key.DEVICE_NAME),
                            mSettings.getString(Settings.Key.DEVICE_UUID),
                            null,
                            40818
                    ).toServiceInfo(),
                    NsdManager.PROTOCOL_DNS_SD,
                    mRegistrationListener
            );

            // Register the server with the selector
            SelectionKey selectionKey = serverSocketChannel.register(mSelector,
                    SelectionKey.OP_ACCEPT);

            // Create Transfers as new connections come in
            while (true) {
                mSelector.select();
                if (mStop) {
                    break;
                }
                if (selectionKey.isAcceptable()) {
                    Log.i(TAG, "accepting incoming connection");
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    String unknownDeviceName = mContext.getString(
                            R.string.service_transfer_unknown_device);
                    mListener.onNewTransfer(
                            new Transfer(
                                    socketChannel,
                                    mSettings.getString(Settings.Key.TRANSFER_DIRECTORY),
                                    mSettings.getBoolean(Settings.Key.BEHAVIOR_OVERWRITE),
                                    unknownDeviceName
                            )
                    );
                }
            }

            // Close the server socket
            serverSocketChannel.close();

        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
        }

        // Unregister the service
        if (nsdManager != null) {
            nsdManager.unregisterService(mRegistrationListener);
        }

        // Inform the notification manager that the server has stopped
        mTransferNotificationManager.stopListening();

        Log.i(TAG, "server stopped");
    }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.reactnativefileintent" >
</manifest>


text:
//
// Copyright (c) Microsoft.  All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

namespace Microsoft.Azure.Commands.ApiManagement.ServiceManagement.Commands
{
    using Microsoft.Azure.Commands.ApiManagement.ServiceManagement.Models;
    using Microsoft.Azure.Commands.ApiManagement.ServiceManagement.Properties;
    using System;
    using System.Globalization;
    using System.Management.Automation;

    [Cmdlet(VerbsCommon.Remove, Constants.ApiManagementOpenIdConnectProvider)]
    [OutputType(typeof(bool))]
    public class RemoveAzureApiManagementOpenIdConnectProvider : AzureApiManagementCmdletBase
    {
        [Parameter(
            ValueFromPipelineByPropertyName = true,
            Mandatory = true,
            HelpMessage = "Instance of PsApiManagementContext. This parameter is required.")]
        [ValidateNotNullOrEmpty]
        public PsApiManagementContext Context { get; set; }

        [Parameter(
            ValueFromPipelineByPropertyName = true,
            Mandatory = true,
            HelpMessage = "Identifier of existing OpenID Connect Provider. This parameter is required.")]
        [ValidateNotNullOrEmpty]
        public String OpenIdConnectProviderId { get; set; }

        [Parameter(
            ValueFromPipelineByPropertyName = true,
            Mandatory = false,
            HelpMessage = "If specified will write true in case operation succeeds. This parameter is optional. Default value is false.")]
        public SwitchParameter PassThru { get; set; }

        [Parameter(
            ValueFromPipelineByPropertyName = true,
            Mandatory = false,
            HelpMessage = "Forces delete operation (prevents confirmation dialog). This parameter is optional. Default value is false.")]
        public SwitchParameter Force { get; set; }

        public override void ExecuteApiManagementCmdlet()
        {
            var actionDescription = string.Format(CultureInfo.CurrentCulture, Resources.OpenIdConnectProviderRemoveDescription, OpenIdConnectProviderId);
            var actionWarning = string.Format(CultureInfo.CurrentCulture, Resources.OpenIdConnectProviderRemoveWarning, OpenIdConnectProviderId);

            // Do nothing if force is not specified and user cancelled the operation
            if (!Force.IsPresent &&
                !ShouldProcess(
                    actionDescription,
                    actionWarning,
                    Resources.ShouldProcessCaption))
            {
                return;
            }

            Client.OpenIdConnectProviderRemove(Context, OpenIdConnectProviderId);

            if (PassThru.IsPresent)
            {
                WriteObject(true);
            }
        }
    }
}


text:
package com.google.cloud.notebooks.v1.samples;

// [START notebooks_v1_generated_notebookserviceclient_isinstanceupgradeable_async]
import com.google.api.core.ApiFuture;
import com.google.cloud.notebooks.v1.IsInstanceUpgradeableRequest;
import com.google.cloud.notebooks.v1.IsInstanceUpgradeableResponse;
import com.google.cloud.notebooks.v1.NotebookServiceClient;
import com.google.cloud.notebooks.v1.UpgradeType;

public class AsyncIsInstanceUpgradeable {

  public static void main(String[] args) throws Exception {
    asyncIsInstanceUpgradeable();
  }

  public static void asyncIsInstanceUpgradeable() throws Exception {
    // This snippet has been automatically generated and should be regarded as a code template only.
    // It will require modifications to work:
    // - It may require correct/in-range values for request initialization.
    // - It may require specifying regional endpoints when creating the service client as shown in
    // https://cloud.google.com/java/docs/setup#configure_endpoints_for_the_client_library
    try (NotebookServiceClient notebookServiceClient = NotebookServiceClient.create()) {
      IsInstanceUpgradeableRequest request =
          IsInstanceUpgradeableRequest.newBuilder()
              .setNotebookInstance("notebookInstance-544239728")
              .setType(UpgradeType.forNumber(0))
              .build();
      ApiFuture<IsInstanceUpgradeableResponse> future =
          notebookServiceClient.isInstanceUpgradeableCallable().futureCall(request);
      // Do something.
      IsInstanceUpgradeableResponse response = future.get();
    }
  }
}
// [END notebooks_v1_generated_notebookserviceclient_isinstanceupgradeable_async]


text:
require 'active_support/core_ext/hash'
require 'desk/api/modules/listable'
require 'desk/api/modules/creatable'
require 'desk/api/modules/deletable'
require 'desk/topic'

module Desk
  module Api
    class Topics

      include Desk::Api::Listable
      include Desk::Api::Creatable
      include Desk::Api::Deletable

      attr_reader :connection, :endpoint, :return_class

      def initialize(connection)
        @connection = connection
        @endpoint = "topics"
        @return_class = Desk::Topic
      end

    end
  end
end


text:
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.autofill_assistant;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.iterableWithSize;

import static org.chromium.base.test.util.CriteriaHelper.DEFAULT_POLLING_INTERVAL;
import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.checkElementExists;
import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.startAutofillAssistant;
import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.tapElement;
import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntil;
import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntilViewAssertionTrue;
import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntilViewMatchesCondition;
import static org.chromium.chrome.browser.autofill_assistant.MiniActionTestUtil.addClickSteps;
import static org.chromium.chrome.browser.autofill_assistant.ProtoTestUtil.toCssSelector;

import android.support.test.InstrumentationRegistry;
import android.util.Base64;

import androidx.test.filters.MediumTest;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantTestService.ScriptsReturnMode;
import org.chromium.chrome.browser.autofill_assistant.proto.ActionProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ChipProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ChipType;
import org.chromium.chrome.browser.autofill_assistant.proto.ConfigureUiStateProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ConfigureUiStateProto.OverlayBehavior;
import org.chromium.chrome.browser.autofill_assistant.proto.ElementConditionProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ElementConditionsProto;
import org.chromium.chrome.browser.autofill_assistant.proto.JsFlowProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ProcessedActionProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ProcessedActionStatusProto;
import org.chromium.chrome.browser.autofill_assistant.proto.PromptProto;
import org.chromium.chrome.browser.autofill_assistant.proto.PromptProto.Choice;
import org.chromium.chrome.browser.autofill_assistant.proto.ScriptPreconditionProto;
import org.chromium.chrome.browser.autofill_assistant.proto.SelectorProto;
import org.chromium.chrome.browser.autofill_assistant.proto.StopProto;
import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto;
import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto.PresentationProto;
import org.chromium.chrome.browser.autofill_assistant.proto.TellProto;
import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.components.autofill_assistant.AutofillAssistantPreferencesUtil;
import org.chromium.components.autofill_assistant.R;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Tests JS flows.
 */
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@RunWith(ChromeJUnit4ClassRunner.class)
public class JsFlowIntegrationTest {
    private static final String HTML_DIRECTORY = "/components/test/data/autofill_assistant/html/";
    private static final String TEST_PAGE = "autofill_assistant_target_website.html";
    private static final String MAIN_SCRIPT_PATH = "main_script";
    private static final String INTERRUPT_SCRIPT_PATH = "interrupt_script";
    private static final SupportedScriptProto TEST_SCRIPT =
            SupportedScriptProto.newBuilder()
                    .setPath(MAIN_SCRIPT_PATH)
                    .setPresentation(PresentationProto.newBuilder().setAutostart(true))
                    .build();

    @Rule
    public CustomTabActivityTestRule mTestRule = new CustomTabActivityTestRule();

    private String getTargetWebsiteUrl(String testPage) {
        return mTestRule.getTestServer().getURL(HTML_DIRECTORY + testPage);
    }

    private AutofillAssistantTestService runScript(AutofillAssistantTestScript script) {
        return runScript(Collections.singletonList(script));
    }

    private AutofillAssistantTestService runScript(List<AutofillAssistantTestScript> scripts) {
        AutofillAssistantTestService testService =
                new AutofillAssistantTestService(scripts, ScriptsReturnMode.ALL_AT_ONCE);
        startAutofillAssistant(mTestRule.getActivity(), testService);
        return testService;
    }

    @Before
    public void setUp() {
        AutofillAssistantPreferencesUtil.setInitialPreferences(true);
        mTestRule.startCustomTabActivityWithIntent(CustomTabsTestUtils.createMinimalCustomTabIntent(
                InstrumentationRegistry.getTargetContext(), getTargetWebsiteUrl(TEST_PAGE)));
    }

    private byte[] getActionBytes(ActionProto action) {
        switch (action.getActionInfoCase()) {
            case SELECT_OPTION:
                return action.getSelectOption().toByteArray();
            case NAVIGATE:
                return action.getNavigate().toByteArray();
            case PROMPT:
                return action.getPrompt().toByteArray();
            case TELL:
                return action.getTell().toByteArray();
            case SHOW_CAST:
                return action.getShowCast().toByteArray();
            case WAIT_FOR_DOM:
                return action.getWaitForDom().toByteArray();
            case USE_CARD:
                return action.getUseCard().toByteArray();
            case USE_ADDRESS:
                return action.getUseAddress().toByteArray();
            case UPLOAD_DOM:
                return action.getUploadDom().toByteArray();
            case SHOW_PROGRESS_BAR:
                return action.getShowProgressBar().toByteArray();
            case SHOW_DETAILS:
                return action.getShowDetails().toByteArray();
            case STOP:
                return action.getStop().toByteArray();
            case COLLECT_USER_DATA:
                return action.getCollectUserData().toByteArray();
            case SET_ATTRIBUTE:
                return action.getSetAttribute().toByteArray();
            case SHOW_INFO_BOX:
                return action.getShowInfoBox().toByteArray();
            case EXPECT_NAVIGATION:
                return action.getExpectNavigation().toByteArray();
            case WAIT_FOR_NAVIGATION:
                return action.getWaitForNavigation().toByteArray();
            case CONFIGURE_BOTTOM_SHEET:
                return action.getConfigureBottomSheet().toByteArray();
            case SHOW_FORM:
                return action.getShowForm().toByteArray();
            case POPUP_MESSAGE:
                return action.getPopupMessage().toByteArray();
            case WAIT_FOR_DOCUMENT:
                return action.getWaitForDocument().toByteArray();
            case SHOW_GENERIC_UI:
                return action.getShowGenericUi().toByteArray();
            case GENERATE_PASSWORD_FOR_FORM_FIELD:
                return action.getGeneratePasswordForFormField().toByteArray();
            case SAVE_GENERATED_PASSWORD:
                return action.getSaveGeneratedPassword().toByteArray();
            case CONFIGURE_UI_STATE:
                return action.getConfigureUiState().toByteArray();
            case PRESAVE_GENERATED_PASSWORD:
                return action.getPresaveGeneratedPassword().toByteArray();
            case GET_ELEMENT_STATUS:
                return action.getGetElementStatus().toByteArray();
            case SCROLL_INTO_VIEW:
                return action.getScrollIntoView().toByteArray();
            case WAIT_FOR_DOCUMENT_TO_BECOME_INTERACTIVE:
                return action.getWaitForDocumentToBecomeInteractive().toByteArray();
            case WAIT_FOR_DOCUMENT_TO_BECOME_COMPLETE:
                return action.getWaitForDocumentToBecomeComplete().toByteArray();
            case SEND_CLICK_EVENT:
                return action.getSendClickEvent().toByteArray();
            case SEND_TAP_EVENT:
                return action.getSendTapEvent().toByteArray();
            case JS_CLICK:
                return action.getJsClick().toByteArray();
            case SEND_KEYSTROKE_EVENTS:
                return action.getSendKeystrokeEvents().toByteArray();
            case SEND_CHANGE_EVENT:
                return action.getSendChangeEvent().toByteArray();
            case SET_ELEMENT_ATTRIBUTE:
                return action.getSetElementAttribute().toByteArray();
            case SELECT_FIELD_VALUE:
                return action.getSelectFieldValue().toByteArray();
            case FOCUS_FIELD:
                return action.getFocusField().toByteArray();
            case WAIT_FOR_ELEMENT_TO_BECOME_STABLE:
                return action.getWaitForElementToBecomeStable().toByteArray();
            case CHECK_ELEMENT_IS_ON_TOP:
                return action.getCheckElementIsOnTop().toByteArray();
            case RELEASE_ELEMENTS:
                return action.getReleaseElements().toByteArray();
            case DISPATCH_JS_EVENT:
                return action.getDispatchJsEvent().toByteArray();
            case SEND_KEY_EVENT:
                return action.getSendKeyEvent().toByteArray();
            case SELECT_OPTION_ELEMENT:
                return action.getSelectOptionElement().toByteArray();
            case CHECK_ELEMENT_TAG:
                return action.getCheckElementTag().toByteArray();
            case CHECK_OPTION_ELEMENT:
                return action.getCheckOptionElement().toByteArray();
            case SET_PERSISTENT_UI:
                return action.getSetPersistentUi().toByteArray();
            case CLEAR_PERSISTENT_UI:
                return action.getClearPersistentUi().toByteArray();
            case SCROLL_INTO_VIEW_IF_NEEDED:
                return action.getScrollIntoViewIfNeeded().toByteArray();
            case SCROLL_WINDOW:
                return action.getScrollWindow().toByteArray();
            case SCROLL_CONTAINER:
                return action.getScrollContainer().toByteArray();
            case SET_TOUCHABLE_AREA:
                return action.getSetTouchableArea().toByteArray();
            case DELETE_PASSWORD:
                return action.getDeletePassword().toByteArray();
            case EDIT_PASSWORD:
                return action.getEditPassword().toByteArray();
            case BLUR_FIELD:
                return action.getBlurField().toByteArray();
            case RESET_PENDING_CREDENTIALS:
                return action.getResetPendingCredentials().toByteArray();
            case SAVE_SUBMITTED_PASSWORD:
                return action.getSaveSubmittedPassword().toByteArray();
            case UPDATE_CLIENT_SETTINGS:
                return action.getUpdateClientSettings().toByteArray();
            case JS_FLOW:
                return action.getJsFlow().toByteArray();
            case EXECUTE_JS:
                return action.getExecuteJs().toByteArray();
            default:
                assert false : "Unhandled action case, please add above!";
                return null;
        }
    }

    /**
     * Returns a JS flow action that will execute all actions in {@code actions} consecutively.
     */
    private ActionProto toJsFlowAction(List<ActionProto> actions) {
        assert (!actions.isEmpty());
        StringBuilder jsFlow = new StringBuilder();
        for (int i = 0; i < actions.size(); i++) {
            jsFlow.append("[client_status, value] = await runNativeAction(")
                    .append(actions.get(i).getActionInfoCase().getNumber())
                    .append(", '")
                    .append(Base64.encodeToString(getActionBytes(actions.get(i)), Base64.NO_WRAP))
                    .append("');\nif (client_status != 2) { return {status:client_status}; }\n");
        }
        jsFlow.append("return {status:client_status};");
        return ActionProto.newBuilder()
                .setJsFlow(JsFlowProto.newBuilder().setJsFlow(jsFlow.toString()))
                .build();
    }

    @Test
    @MediumTest
    public void runSimpleJsFlowWithNativeActions() throws Exception {
        // Clicking #touch_area_one will make it disappear, which makes for a convenient test.
        ArrayList<ActionProto> nestedActions = new ArrayList<>();
        addClickSteps(toCssSelector("#touch_area_one"), nestedActions);

        ArrayList<ActionProto> list = new ArrayList<>();
        list.add(toJsFlowAction(nestedActions));
        list.add(ActionProto.newBuilder()
                         .setPrompt(PromptProto.newBuilder().addChoices(Choice.newBuilder().setChip(
                                 ChipProto.newBuilder()
                                         .setType(ChipType.HIGHLIGHTED_ACTION)
                                         .setText("After JS flow"))))
                         .build());

        Assert.assertTrue(checkElementExists(mTestRule.getWebContents(), "touch_area_one"));

        AutofillAssistantTestScript script = new AutofillAssistantTestScript(TEST_SCRIPT, list);
        runScript(script);

        waitUntilViewMatchesCondition(withText("After JS flow"), isCompletelyDisplayed());
        waitUntil(() -> !checkElementExists(mTestRule.getWebContents(), "touch_area_one"));
    }

    @Test
    @MediumTest
    public void runSimpleJsFlowWithReturnValue() throws Exception {
        ArrayList<ActionProto> list = new ArrayList<>();
        String jsFlow = "return {"
                + "status:3,"
                + "result:[[1,2], null, {enum:5}]"
                + "}";
        list.add(ActionProto.newBuilder()
                         .setJsFlow(JsFlowProto.newBuilder().setJsFlow(jsFlow))
                         .build());
        list.add(ActionProto.newBuilder()
                         .setPrompt(PromptProto.newBuilder().addChoices(Choice.newBuilder().setChip(
                                 ChipProto.newBuilder()
                                         .setType(ChipType.HIGHLIGHTED_ACTION)
                                         .setText("Should not run because JS flow returned "
                                                 + "OTHER_ACTION_STATUS != ACTION_APPLIED"))))
                         .build());

        AutofillAssistantTestScript script = new AutofillAssistantTestScript(TEST_SCRIPT, list);
        AutofillAssistantTestService testService = runScript(script);

        testService.waitUntilGetNextActions(1);
        List<ProcessedActionProto> processedActions = testService.getProcessedActions();
        assertThat(processedActions, iterableWithSize(1));
        assertThat(processedActions.get(0).getStatus(),
                is(ProcessedActionStatusProto.OTHER_ACTION_STATUS));
        // Note that the JS flow returns a JS object (no quotes around 'enum'), but the action
        // returns the JSON representation of that object (with quotes around 'enum').
        assertThat(processedActions.get(0).getJsFlowResult().getResultJson(),
                is("[[1,2],null,{\"enum\":5}]"));
    }

    @Test
    @MediumTest
    @DisabledTest(message = "crbug.com/1307549")
    public void stopFlowFromJs() throws Exception {
        ArrayList<ActionProto> nestedActions = new ArrayList<>();
        nestedActions.add(ActionProto.newBuilder()
                                  .setTell(TellProto.newBuilder().setMessage("Bye!"))
                                  .build());
        nestedActions.add(ActionProto.newBuilder().setStop(StopProto.newBuilder()).build());

        ArrayList<ActionProto> list = new ArrayList<>();
        list.add(ActionProto.newBuilder()
                         .setPrompt(PromptProto.newBuilder().addChoices(Choice.newBuilder().setChip(
                                 ChipProto.newBuilder()
                                         .setType(ChipType.HIGHLIGHTED_ACTION)
                                         .setText("Stop"))))
                         .build());
        list.add(toJsFlowAction(nestedActions));
        list.add(ActionProto.newBuilder()
                         .setPrompt(PromptProto.newBuilder().addChoices(Choice.newBuilder().setChip(
                                 ChipProto.newBuilder()
                                         .setType(ChipType.HIGHLIGHTED_ACTION)
                                         .setText("Should not run!"))))
                         .build());

        AutofillAssistantTestScript script = new AutofillAssistantTestScript(TEST_SCRIPT, list);
        runScript(script);

        waitUntilViewMatchesCondition(withText("Stop"), isCompletelyDisplayed());
        onView(withText("Stop")).perform(click());
        waitUntilViewAssertionTrue(
                withId(R.id.autofill_assistant), doesNotExist(), DEFAULT_POLLING_INTERVAL);
    }

    @Test
    @MediumTest
    @DisabledTest(message = "crbug.com/1307549")
    public void runInterruptDuringFlow() throws Exception {
        ArrayList<AutofillAssistantTestScript> scripts = new ArrayList<>();
        ArrayList<ActionProto> nestedActions = new ArrayList<>();
        nestedActions.add(
                ActionProto.newBuilder()
                        .setConfigureUiState(ConfigureUiStateProto.newBuilder().setOverlayBehavior(
                                OverlayBehavior.HIDDEN))
                        .build());

        nestedActions.add(
                ActionProto.newBuilder()
                        .setPrompt(PromptProto.newBuilder().setAllowInterrupt(true).addChoices(
                                PromptProto.Choice.newBuilder().setChip(
                                        ChipProto.newBuilder().setText("Continue"))))
                        .build());
        nestedActions.add(ActionProto.newBuilder()
                                  .setPrompt(PromptProto.newBuilder().addChoices(
                                          PromptProto.Choice.newBuilder().setChip(
                                                  ChipProto.newBuilder().setText("Finished"))))
                                  .build());

        // The main script runs the above actions as a JS flow, i.e., it contains only a single
        // action.
        AutofillAssistantTestScript mainScript = new AutofillAssistantTestScript(
                TEST_SCRIPT, Collections.singletonList(toJsFlowAction(nestedActions)));
        scripts.add(mainScript);

        ArrayList<ActionProto> interruptActionList = new ArrayList<>();
        SelectorProto touchAreaOne = toCssSelector("#touch_area_one");
        addClickSteps(touchAreaOne, interruptActionList);
        interruptActionList.add(
                ActionProto.newBuilder()
                        .setPrompt(PromptProto.newBuilder().addChoices(
                                PromptProto.Choice.newBuilder().setChip(
                                        ChipProto.newBuilder().setText("Interrupt"))))
                        .build());

        // The interrupt triggers when touch_area_one is present but touch_area_four is gone, so
        // that we can trigger it manually.
        SelectorProto touchAreaFour = toCssSelector("#touch_area_four");
        ScriptPreconditionProto interruptPrecondition =
                ScriptPreconditionProto.newBuilder()
                        .setElementCondition(ElementConditionProto.newBuilder().setAllOf(
                                ElementConditionsProto.newBuilder()
                                        .addConditions(ElementConditionProto.newBuilder().setNoneOf(
                                                ElementConditionsProto.newBuilder().addConditions(
                                                        ElementConditionProto.newBuilder().setMatch(
                                                                touchAreaFour))))
                                        .addConditions(ElementConditionProto.newBuilder().setMatch(
                                                touchAreaOne))))
                        .build();

        // The interrupt is also run as a JS flow.
        AutofillAssistantTestScript interruptScript = new AutofillAssistantTestScript(
                SupportedScriptProto.newBuilder()
                        .setPath(INTERRUPT_SCRIPT_PATH)
                        .setPresentation(
                                PresentationProto.newBuilder().setInterrupt(true).setPrecondition(
                                        interruptPrecondition))
                        .build(),
                Collections.singletonList(toJsFlowAction(interruptActionList)));
        scripts.add(interruptScript);

        runScript(scripts);

        waitUntilViewMatchesCondition(withText("Continue"), isDisplayed());

        // Tapping touch_area_four will make it disappear, which triggers the interrupt.
        tapElement(mTestRule, "touch_area_four");
        waitUntil(() -> !checkElementExists(mTestRule.getWebContents(), "touch_area_four"));

        // The interrupt should click on touch_area_one, making it disappear.
        waitUntilViewMatchesCondition(withText("Interrupt"), isDisplayed());
        waitUntil(() -> !checkElementExists(mTestRule.getWebContents(), "touch_area_one"));

        // Click the chip to end the interrupt and go back to the main script.
        onView(withText("Interrupt")).perform(click());

        // Once the interrupt is done, the prompt chip should appear again.
        waitUntilViewMatchesCondition(withText("Continue"), isDisplayed());

        // The flow should continue after the prompt finishes.
        onView(withText("Continue")).perform(click());
        waitUntilViewMatchesCondition(withText("Finished"), isDisplayed());
    }
}