def create(directory_path, make_directory=False, name=None, icon=None, description=None, fix_problems=None): """Create a project skeleton in the given directory. Returns a Project instance even if creation fails or the directory doesn't exist, but in those cases the ``problems`` attribute of the Project will describe the problem. If the kapsel.yml already exists, this simply loads it. This will not prepare the project (create environments, etc.), use the separate prepare calls if you want to do that. Args: directory_path (str): directory to contain kapsel.yml make_directory (bool): True to create the directory if it doesn't exist name (str): Name of the new project or None to leave unset (uses directory name) icon (str): Icon for the new project or None to leave unset (uses no icon) description (str): Description for the new project or None to leave unset fix_problems (bool): True to always fix problems even if project file existed Returns: a Project instance """ if make_directory and not os.path.exists(directory_path): try: os.makedirs(directory_path) except (IOError, OSError): # py3=IOError, py2=OSError # allow project.problems to report the issue pass # do this first so Project constructor can load it _add_projectignore_if_none(directory_path) project = Project(directory_path) if name is not None: project.project_file.set_value('name', name) if icon is not None: project.project_file.set_value('icon', icon) if description is not None: project.project_file.set_value('description', description) # dirty the project with the above new values project.project_file.use_changes_without_saving() # if we're creating kapsel.yml, why not auto-fix any problems, # such as environment.yaml import. Obtuse to ask since there's # no existing kapsel.yml to mess up. if fix_problems is None: fix_problems = not os.path.exists(project.project_file.filename) if fix_problems: project.fix_problems_and_suggestions() if len(project.problems) == 0: # write out the kapsel.yml; note that this will try to create # the directory which we may not want... so only do it if # we're problem-free. project.project_file.save() return project
def do_test(dirname): io_loop = IOLoop() io_loop.make_current() events = [] def event_handler(event): events.append(event) project = Project(dirname) local_state_file = LocalStateFile.load_for_directory(dirname) context = ConfigurePrepareContext(dict(), local_state_file, 'default', UserConfigOverrides(), []) server = UIServer(project, _no_op_prepare(context), event_handler, io_loop) get_response = http_get(io_loop, server.url) print(repr(get_response)) post_response = http_post(io_loop, server.url, body="") print(repr(post_response)) server.unlisten() assert len(events) == 1 assert isinstance(events[0], UIServerDoneEvent)
def check(dirname): def mock_is_interactive(): return True monkeypatch.setattr( 'conda_kapsel.commands.console_utils.stdin_is_interactive', mock_is_interactive) def mock_console_input(prompt): return "c" monkeypatch.setattr( 'conda_kapsel.commands.console_utils.console_input', mock_console_input) def mock_system(): return "Windows" monkeypatch.setattr('platform.system', mock_system) args = Args(None, 'test', 'echo hello', directory=dirname) res = main(args) assert res == 0 project = Project(dirname) command = project.project_file.get_value(['commands', 'test']) assert len(command.keys()) == 2 assert command['windows'] == 'echo hello' assert command['env_spec'] == 'default'
def check_ask_type(dirname): def mock_is_interactive(): return True monkeypatch.setattr( 'conda_kapsel.commands.console_utils.stdin_is_interactive', mock_is_interactive) def mock_console_input(prompt): return "b" monkeypatch.setattr( 'conda_kapsel.commands.console_utils.console_input', mock_console_input) args = Args(None, 'test', 'file.py', directory=dirname) res = main(args) assert res == 0 project = Project(dirname) command = project.project_file.get_value(['commands', 'test']) assert len(command.keys()) == 2 assert command['bokeh_app'] == 'file.py' assert command['env_spec'] == 'default'
def _load_env_var_requirement(dirname, env_var): project = Project(dirname) for requirement in project.requirements: if isinstance(requirement, EnvVarRequirement) and requirement.env_var == env_var: return requirement assert [] == project.problems raise RuntimeError("No requirement for %s was in the project file, only %r" % (env_var, project.requirements))
def check(dirname): _monkeypatch_pwd(monkeypatch, dirname) code = _parse_args_and_run_subcommand(['conda-kapsel', 'remove-download', 'TEST_FILE']) project = Project(dirname) assert not project.downloads assert code == 1 out, err = capsys.readouterr() assert ("Download requirement: TEST_FILE not found.\n") == err assert '' == out
def check_guessing_notebook(dirname): args = Args(None, 'test', 'file.ipynb', directory=dirname) res = main(args) assert res == 0 project = Project(dirname) command = project.project_file.get_value(['commands', 'test']) assert command['notebook'] == 'file.ipynb' assert command['env_spec'] == 'default' assert len(command.keys()) == 2
def check(dirname): _monkeypatch_pwd(monkeypatch, dirname) code = _parse_args_and_run_subcommand(['conda-kapsel', 'remove-download', 'TEST_FILE']) project = Project(dirname) assert not project.downloads assert code == 0 out, err = capsys.readouterr() filename = os.path.join(dirname, 'foo') assert ("Removed downloaded file %s.\nRemoved TEST_FILE from the project file.\n" % filename) == out assert '' == err
def create(directory_path, make_directory=False, name=None, icon=None, description=None): """Create a project skeleton in the given directory. Returns a Project instance even if creation fails or the directory doesn't exist, but in those cases the ``problems`` attribute of the Project will describe the problem. If the kapsel.yml already exists, this simply loads it. This will not prepare the project (create environments, etc.), use the separate prepare calls if you want to do that. Args: directory_path (str): directory to contain kapsel.yml make_directory (bool): True to create the directory if it doesn't exist name (str): Name of the new project or None to leave unset (uses directory name) icon (str): Icon for the new project or None to leave unset (uses no icon) description (str): Description for the new project or None to leave unset Returns: a Project instance """ if make_directory and not os.path.exists(directory_path): try: os.makedirs(directory_path) except (IOError, OSError): # py3=IOError, py2=OSError # allow project.problems to report the issue pass # do this first so Project constructor can load it _add_projectignore_if_none(directory_path) project = Project(directory_path) if name is not None: project.project_file.set_value('name', name) if icon is not None: project.project_file.set_value('icon', icon) if description is not None: project.project_file.set_value('description', description) # write out the kapsel.yml; note that this will try to create # the directory which we may not want... so only do it if # we're problem-free. project.project_file.use_changes_without_saving() if len(project.problems) == 0: project.project_file.save() return project
def do_test(dirname): io_loop = IOLoop() io_loop.make_current() events = [] def event_handler(event): events.append(event) project = Project(dirname) local_state_file = LocalStateFile.load_for_directory(dirname) requirement = EnvVarRequirement(registry=project.plugin_registry, env_var="FOO") status = requirement.check_status(dict(), local_state_file, 'default', UserConfigOverrides()) context = ConfigurePrepareContext(dict(), local_state_file, 'default', UserConfigOverrides(), [status]) server = UIServer(project, _no_op_prepare(context), event_handler, io_loop) # do a get so that _requirements_by_id below exists get_response = http_get(io_loop, server.url) assert 200 == get_response.code req_id = list(server._application._requirements_by_id.keys())[0] if '%s' in name_template: name = name_template % req_id else: name = name_template encoder = MultipartEncoder({name: 'bloop'}) body = encoder.to_string() headers = {'Content-Type': encoder.content_type} post_response = http_post(io_loop, server.url, body=body, headers=headers) # we just ignore bad form names, because they are assumed # to be some sort of hostile thing. we shouldn't ever # generate them on purpose. assert 200 == post_response.code server.unlisten() assert len(events) == 1 assert isinstance(events[0], UIServerDoneEvent) out, err = capsys.readouterr() assert out == "" assert err == expected_err
def check(dirname): code = _parse_args_and_run_subcommand( ['conda-kapsel', 'remove-command', 'test', '--directory', dirname]) assert code == 0 project = Project(dirname) command = project.project_file.get_value(['commands', 'test']) assert command is None out, err = capsys.readouterr() assert out == "Removed the command 'test' from the project.\n" assert err == ''
def check(dirname): code = _parse_args_and_run_subcommand([ 'conda-kapsel', 'add-command', '--directory', dirname, '--env-spec', 'foo', '--type', 'notebook', 'test', 'file.ipynb' ]) assert code == 0 project = Project(dirname) command = project.project_file.get_value(['commands', 'test']) assert command['notebook'] == 'file.ipynb' assert command['env_spec'] == 'foo' assert len(command.keys()) == 2
def do_test(dirname): io_loop = IOLoop() io_loop.make_current() events = [] def event_handler(event): events.append(event) local_state_file = LocalStateFile.load_for_directory(dirname) value = local_state_file.get_value(['variables', 'FOO']) assert value is None project = Project(dirname) requirement = EnvVarRequirement(registry=project.plugin_registry, env_var="FOO") status = requirement.check_status(dict(), local_state_file, 'default', UserConfigOverrides()) context = ConfigurePrepareContext(dict(), local_state_file, 'default', UserConfigOverrides(), [status]) server = UIServer(project, _no_op_prepare(context), event_handler, io_loop) get_response = http_get(io_loop, server.url) print(repr(get_response)) soup = BeautifulSoup(get_response.body, _BEAUTIFUL_SOUP_BACKEND) field = soup.find_all("input", attrs={'type': 'text'})[0] assert 'name' in field.attrs encoder = MultipartEncoder({field['name']: 'bloop'}) body = encoder.to_string() headers = {'Content-Type': encoder.content_type} post_response = http_post(io_loop, server.url, body=body, headers=headers) print(repr(post_response)) server.unlisten() assert len(events) == 1 assert isinstance(events[0], UIServerDoneEvent) value = local_state_file.get_value(['variables', 'FOO']) assert 'bloop' == value
def check_list_not_empty(dirname): params = ['conda-kapsel', 'list-packages', '--directory', dirname] if env is not None: params.extend(['--env-spec', env]) code = _parse_args_and_run_subcommand(params) assert code == 0 out, err = capsys.readouterr() project = Project(dirname) assert project.default_env_spec_name == 'foo' expected_out = "Packages for environment '{}':\n{}".format( env or project.default_env_spec_name, expected_deps) assert out == expected_out
def check(dirname): env_var = conda_api.conda_prefix_variable() try: _push_fake_env_creator() project = Project(dirname) environ = minimal_environ() # we specify the command name but not the # env_spec_name but it should imply the proper env # spec name. result = prepare_without_interaction(project, environ=environ, command_name='hello') expected_path = project.env_specs['foo'].path(project.directory_path) assert result.environ[env_var] == expected_path finally: _pop_fake_env_creator()
def check(dirname): code = _parse_args_and_run_subcommand([ 'conda-kapsel', 'remove-command', 'file.ipynb', '--directory', dirname ]) assert code == 1 project = Project(dirname) assert 'file.ipynb' in project.commands command = project.commands['file.ipynb'] assert command is not None assert command.notebook == 'file.ipynb' out, err = capsys.readouterr() assert err == "Cannot remove auto-generated command: 'file.ipynb'.\n" assert out == ''
def load_project(dirname): """Load a Project, fixing it if needed and possible.""" project = Project(dirname) if console_utils.stdin_is_interactive(): fixed_any = False for problem in project.fixable_problems: print(problem.text) should_fix = console_utils.console_ask_yes_or_no( problem.fix_prompt, default=False) if should_fix: problem.fix(project) fixed_any = True if fixed_any: project.project_file.save() return project
def check(dirname): env_var = conda_api.conda_prefix_variable() try: _push_fake_env_creator() project = Project(dirname) environ = minimal_environ() result = prepare_without_interaction(project, environ=environ, env_spec_name='foo') expected_path = project.env_specs['foo'].path(project.directory_path) assert result.environ[env_var] == expected_path environ = minimal_environ() result = prepare_without_interaction(project, environ=environ, env_spec_name='bar') assert result expected_path = project.env_specs['bar'].path(project.directory_path) assert result.environ[env_var] == expected_path finally: _pop_fake_env_creator()
def check_ask_type(dirname): def mock_is_interactive(): return True monkeypatch.setattr( 'conda_kapsel.commands.console_utils.stdin_is_interactive', mock_is_interactive) calls = [] def mock_console_input(prompt): res = ['-', 'b'][len(calls)] calls.append(True) return res monkeypatch.setattr( 'conda_kapsel.commands.console_utils.console_input', mock_console_input) args = Args(None, 'test', 'file.py', directory=dirname) res = main(args) assert res == 0 assert len(calls) == 2 project = Project(dirname) command = project.project_file.get_value(['commands', 'test']) assert len(command.keys()) == 2 assert command['bokeh_app'] == 'file.py' assert command['env_spec'] == 'default' out, err = capsys.readouterr() assert out == ( "Please enter 'b', 'n', or 'c'.\n" + " A Bokeh app is the project-relative path to a Bokeh script or app directory.\n" + " A notebook file is the project-relative path to a .ipynb file.\n" " A command line is any command you might type at the command prompt.\n" "Added a command 'test' to the project. Run it with `conda-kapsel run test`.\n" )
def check(dirname): broken_project = Project(dirname) assert len(broken_project.fixable_problems) == 1 def mock_isatty_true(): return True # python 2 can throw a "readonly" error if you try to patch sys.stdin.isatty itself monkeypatch.setattr( 'conda_kapsel.commands.console_utils.stdin_is_interactive', mock_isatty_true) _monkeypatch_input(monkeypatch, ["y"]) project = load_project(dirname) assert project.problems == [] out, err = capsys.readouterr() assert out == ( "%s has an empty env_specs section.\nAdd an environment spec to kapsel.yml? " % os.path.join(dirname, DEFAULT_PROJECT_FILENAME)) assert err == ""