def _load_service_requirement(dirname): project = Project(dirname) assert [] == project.problems for req in project.requirements(project.default_env_spec_name): if isinstance(req, ServiceRequirement): return req raise RuntimeError("no ServiceRequirement found")
def _load_env_var_requirement(dirname, env_var): project = Project(dirname) for requirement in project.requirements(project.default_env_spec_name): 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( ['anaconda-project', 'remove-download', 'TEST_FILE']) project = Project(dirname) assert not project.downloads(project.default_env_spec_name) assert code == 1 out, err = capsys.readouterr() assert ("Download requirement: TEST_FILE not found.\n") == err assert '' == out
def check(dirname): _monkeypatch_pwd(monkeypatch, dirname) code = _parse_args_and_run_subcommand( ['anaconda-project', 'remove-download', 'TEST_FILE']) project = Project(dirname) assert not project.downloads(project.default_env_spec_name) 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 check(dirname): def mock_is_interactive(): return True monkeypatch.setattr('anaconda_project.internal.cli.console_utils.stdin_is_interactive', mock_is_interactive) def mock_console_input(prompt): return "c" monkeypatch.setattr('anaconda_project.internal.cli.console_utils.console_input', mock_console_input) def mock_system(): return "Linux" 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['unix'] == 'echo hello' assert command['env_spec'] == 'default'
def prepare_project_scoped_env_not_attempted(dirname): project = Project(dirname) environ = minimal_environ(PROJECT_DIR=dirname) result = prepare_without_interaction(project, environ=environ, mode=provide.PROVIDE_MODE_CHECK) assert not result # expected_env_path = os.path.join(dirname, "envs", "default") bootstrap_env_path = os.path.join(dirname, "envs", "bootstrap-env") for err in [ ('missing requirement to run this project: ' + 'The project needs a Conda bootstrap environment containing all required packages.' ), " '%s' doesn't look like it contains a Conda environment yet." % bootstrap_env_path, ]: assert err in result.errors # unprepare should not have anything to do status = unprepare(project, result) assert status assert status.errors == [] # todo: would be good to understand the different message got with a "normal" env assert status.status_description == ("Success.")
def check_ask_type(dirname): def mock_is_interactive(): return True monkeypatch.setattr('anaconda_project.internal.cli.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('anaconda_project.internal.cli.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 `anaconda-project run test`.\n")
def check_ask_type(dirname): def mock_is_interactive(): return True monkeypatch.setattr( 'anaconda_project.internal.cli.console_utils.stdin_is_interactive', mock_is_interactive) def mock_console_input(prompt): return "b" monkeypatch.setattr( 'anaconda_project.internal.cli.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 check(dirname): envs_dir = os.path.join(dirname, "envs") project = Project(dirname) environ = minimal_environ(PROJECT_DIR=dirname) stage = prepare_in_stages(project, environ=environ) prepare_context = stage.configure() status = _conda_env_status(prepare_context) req = status.requirement provider = status.provider # check initial config config = provider.read_config(req, prepare_context.environ, prepare_context.local_state_file, prepare_context.default_env_spec_name, prepare_context.overrides) assert dict(env_name='default', source='project', value=os.path.join(envs_dir, 'default')) == config # set inherited mode config['source'] = 'inherited' provider.set_config_values_as_strings( req, prepare_context.environ, prepare_context.local_state_file, prepare_context.default_env_spec_name, prepare_context.overrides, config) config = provider.read_config(req, prepare_context.environ, prepare_context.local_state_file, prepare_context.default_env_spec_name, prepare_context.overrides) assert dict(env_name='default', source='inherited', value=os.environ.get(req.env_var)) == config # disable inherited mode again config['source'] = 'project' config['env_name'] = 'default' provider.set_config_values_as_strings( req, prepare_context.environ, prepare_context.local_state_file, prepare_context.default_env_spec_name, prepare_context.overrides, config) config = provider.read_config(req, prepare_context.environ, prepare_context.local_state_file, prepare_context.default_env_spec_name, prepare_context.overrides) assert dict(env_name='default', source='project', value=os.path.join(envs_dir, 'default')) == config
def check(dirname): envs_dir = os.path.join(dirname, "envs") project = Project(dirname) environ = minimal_environ(PROJECT_DIR=dirname) stage = prepare_in_stages(project, environ=environ) prepare_context = stage.configure() status = _conda_bootstrap_env_status(prepare_context) req = status.requirement provider = status.provider config = provider.read_config(req, prepare_context.environ, prepare_context.local_state_file, prepare_context.default_env_spec_name, prepare_context.overrides) assert dict(env_name='bootstrap-env', source='project', value=os.path.join(envs_dir, 'bootstrap-env')) == config config['env_name'] = 'bar' provider.set_config_values_as_strings(req, prepare_context.environ, prepare_context.local_state_file, prepare_context.default_env_spec_name, prepare_context.overrides, config) config = provider.read_config(req, prepare_context.environ, prepare_context.local_state_file, prepare_context.default_env_spec_name, prepare_context.overrides) assert dict(env_name='bar', source='project', value=os.path.join(envs_dir, 'bar')) == config assert os.path.join(envs_dir, 'bar') == prepare_context.local_state_file.get_value(['variables', req.env_var])
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.errors == [] 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 unprepare_empty(dirname): project = Project(dirname) environ = minimal_environ() result = prepare_without_interaction(project, environ=environ) assert result.errors == [] assert result status = unprepare(project, result) assert status.errors == [] assert status
def prepare_empty(dirname): project = Project(dirname) environ = minimal_environ() result = prepare_without_interaction(project, environ=environ) assert result.errors == [] assert result assert dict(PROJECT_DIR=project.directory_path) == strip_environ(result.environ) assert dict() == strip_environ(environ) assert result.command_exec_info is None
def unprepare_nothing(dirname): project = Project(dirname) environ = minimal_environ() result = prepare_without_interaction(project, environ=environ) assert result.errors == [] assert result status = unprepare(project, result, whitelist=[]) assert status.errors == [] assert status assert status.status_description == 'Nothing to clean up.'
def load_project(dirname): """Load a Project, fixing it if needed and possible.""" project = Project(dirname, frontend=CliFrontend()) if console_utils.stdin_is_interactive(): had_fixable = len(project.fixable_problems) > 0 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) else: problem.no_fix(project) # both fix() and no_fix() can modify project_file, if no changes # were made this is a no-op. if had_fixable: project.save() return project
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): code = _parse_args_and_run_subcommand(['anaconda-project', '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 check(dirname): code = _parse_args_and_run_subcommand(['anaconda-project', '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(['anaconda-project', 'add-command', '--directory', dirname, '--supports-http-options', '--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'] == 'default' assert command['supports_http_options'] is True assert len(command.keys()) == 3
def load_project(dirname): """Load a Project, fixing it if needed and possible.""" project = Project(dirname, frontend=CliFrontend(), must_exist=True) # No sense in engaging the user if we cannot achieve a fixed state. if project.unfixable_problems: return project if console_utils.stdin_is_interactive(): regressions = 0 problems = project.fixable_problems while problems and regressions < 3: # Instead of looping through the problems in the list, we # fix only the first one and refresh the list. This allows # us to detect when fixing one problem impacts another, # positively or negatively. problem = problems[0] print(problem.text) should_fix = console_utils.console_ask_yes_or_no(problem.fix_prompt, default=False) if not should_fix: break problem.fix(project) project.use_changes_without_saving() o_problems, problems = problems, project.fixable_problems # If the number of problems doesn't decrease as a result of # fixing a problem, it suggests some sort of negative cycle. # We can't reliably detect a cycle, so instead we simply let # this happen 3 times before we give up. regressions += (len(problems) >= len(o_problems)) if not problems: project.save() return project
def check(dirname): broken_project = Project(dirname) assert len(broken_project.fixable_problems) == 1 _monkeypatch_input(monkeypatch, ["n"]) project = load_project(dirname) first_line = "%s: The env_specs section is missing." % DEFAULT_PROJECT_FILENAME assert project.problems == [first_line] out, err = capsys.readouterr() assert out == "%s\nAdd an environment spec to anaconda-project.yml? " % first_line assert err == ""
def prepare_project_scoped_env(dirname): project = Project(dirname) fake_old_path = "foo" + os.pathsep + "bar" environ = dict(PROJECT_DIR=dirname, PATH=fake_old_path) result = prepare_without_interaction(project, environ=environ) assert result expected_env = os.path.join(dirname, "envs", "bootstrap-env") if platform.system() == 'Windows': expected_new_path = expected_env + os.pathsep + os.path.join( expected_env, script_dir) + os.pathsep + os.path.join( expected_env, "Library", "bin") + os.pathsep + "foo" + os.pathsep + "bar" else: expected_new_path = os.path.join( expected_env, script_dir) + os.pathsep + "foo" + os.pathsep + "bar" expected = dict(PROJECT_DIR=project.directory_path, PATH=expected_new_path, BOOTSTRAP_ENV_PREFIX=expected_env) conda_api.environ_set_prefix(expected, expected_env) expected == result.environ assert os.path.exists(os.path.join(expected_env, "conda-meta")) conda_meta_mtime = os.path.getmtime( os.path.join(expected_env, "conda-meta")) # bare minimum bootstrap-env env shouldn't include these # (contrast with the test later where we list them in # requirements) installed = conda_api.installed(expected_env) assert 'ipython' not in installed assert 'numpy' not in installed # Prepare it again should no-op (use the already-existing environment) environ = dict(PROJECT_DIR=dirname, PATH=fake_old_path) result = prepare_without_interaction(project, environ=environ) assert result expected = dict(PROJECT_DIR=project.directory_path, PATH=expected_new_path) conda_api.environ_set_prefix(expected, expected_env) assert conda_meta_mtime == os.path.getmtime( os.path.join(expected_env, "conda-meta")) # Now unprepare status = unprepare(project, result) assert status # todo: this differs from standard CondaEnvProvider assert status.status_description == 'Success.' assert status.errors == [] assert not os.path.exists(expected_env)
def project_no_dedicated_env(*args, **kwargs): """Get a project that won't create envs/default as long as there's an env already.""" if len(args) > 0: dirname = args[0] elif 'directory_path' in kwargs: dirname = kwargs['directory_path'] else: raise RuntimeError("no directory_path for Project") project_dir_disable_dedicated_env(dirname) project = Project(*args, **kwargs) return project
def prepare_project_scoped_env_fails(dirname): project = Project(dirname) environ = minimal_environ(PROJECT_DIR=dirname) result = prepare_without_interaction(project, environ=environ) assert not result assert 'CONDA_DEFAULT_ENV' not in result.environ assert 'CONDA_ENV_PATH' not in result.environ # unprepare should not have anything to do status = unprepare(project, result) assert status assert status.errors == [] assert status.status_description == "Nothing to clean up for environment 'default'."
def check_list_not_empty(dirname): params = ['anaconda-project', '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): project = Project(dirname) environ = minimal_environ() result = prepare_without_interaction(project, environ=environ) assert result # now mimmick an unpacked project packed_file = os.path.join(dirname, 'envs', 'default', 'conda-meta', '.packed') with open(packed_file, 'wt') as f: f.write(conda_api.current_platform()) # without a functional conda-unpack script it will rebuild the env result = prepare_without_interaction(project, environ=environ) assert result assert not os.path.exists(packed_file)
def clone_readonly_and_prepare(dirname): with _readonly_env(env_name='default', packages=('python=3.7', )) as ro_prefix: readonly = conda_api.installed(ro_prefix) assert 'python' in readonly assert 'requests' not in readonly ro_envs = os.path.dirname(ro_prefix) environ = minimal_environ( PROJECT_DIR=dirname, ANACONDA_PROJECT_ENVS_PATH=':{}'.format(ro_envs)) monkeypatch.setattr('os.environ', environ) project = Project(dirname) result = prepare_without_interaction(project) assert result.failed assert ' Conda environment is missing packages: requests and the environment is read-only' in result.errors
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 prepare_project_scoped_env_with_packages(dirname): project = Project(dirname) environ = minimal_environ(PROJECT_DIR=dirname) result = prepare_without_interaction(project, environ=environ, env_spec_name='bootstrap-env') assert result envs_dir = os.path.join(dirname, "envs") env_name = 'bootstrap-env' prefix = os.path.join(envs_dir, env_name) installed = conda_api.installed(prefix) assert 'bokeh' not in installed deps = ['ipython', 'numpy', 'pip'] for pkg in deps: assert pkg in installed deps += ['bokeh'] # Preparing it again with new packages added should add those project.project_file.set_value('packages', deps) project.project_file.save() environ = minimal_environ(PROJECT_DIR=dirname) result = prepare_without_interaction(project, environ=environ) assert result prefix = result.environ[conda_env_var] installed = conda_api.installed(prefix) for pkg in deps: assert pkg in installed installed_pip = pip_api.installed(prefix) assert 'flake8' in installed_pip # Preparing it again with a bogus package should fail deps = project.project_file.get_value('packages') project.project_file.set_value(['packages'], deps + ['boguspackage']) project.project_file.save() environ = minimal_environ(PROJECT_DIR=dirname) result = prepare_without_interaction(project, environ=environ) assert not result