def test_extras_with_io_error(monkeypatch):
    def mock_codecs_open(*args, **kwargs):
        raise IOError("Nope")

    monkeypatch.setattr('codecs.open', mock_codecs_open)
    errors = []
    extras = notebook_analyzer.extras("blah", errors)
    assert [] != errors
    assert extras is None
    assert 'Failed to read or parse' in errors[0]
def add_command(project,
                name,
                command_type,
                command,
                env_spec_name=None,
                supports_http_options=None):
    """Add a command to anaconda-project.yml.

    Returns a ``Status`` subtype (it won't be a
    ``RequirementStatus`` as with some other functions, just a
    plain status).

    Args:
       project (Project): the project
       name (str): name of the command
       command_type (str): choice of `bokeh_app`, `notebook`, `unix` or `windows` command
       command (str): the command line or filename itself
       env_spec_name (str): env spec to use with this command
       supports_http_options (bool): None for leave it alone, otherwise true or false

    Returns:
       a ``Status`` instance
    """
    if command_type not in ALL_COMMAND_TYPES:
        raise ValueError("Invalid command type " + command_type +
                         " choose from " + repr(ALL_COMMAND_TYPES))

    name = name.strip()

    failed = project.problems_status()
    if failed is not None:
        return failed

    command_dict = project.project_file.get_value(['commands', name])
    if command_dict is None:
        command_dict = dict()
        project.project_file.set_value(['commands', name], command_dict)

    command_dict[command_type] = command

    if env_spec_name is None:
        if 'env_spec' not in command_dict:
            # make it explicit for clarity
            command_dict['env_spec'] = project.default_env_spec_name
        # if env_spec is set, leave it alone; this way people can
        # modify commands via command line without specifying the
        # env_spec every time.
    else:
        command_dict['env_spec'] = env_spec_name

    if supports_http_options is not None:
        assert isinstance(supports_http_options, bool)
        command_dict['supports_http_options'] = supports_http_options

    if command_type == 'notebook':
        notebook_file = os.path.join(project.directory_path, command)
        errors = []
        # TODO missing notebook should be an error caught before here
        if os.path.isfile(notebook_file):
            extras = notebook_analyzer.extras(notebook_file, errors)
        else:
            extras = {}
        if len(errors) > 0:
            failed = SimpleStatus(success=False,
                                  description="Unable to add the command.",
                                  errors=errors)
            return failed
        command_dict.update(extras)

    project.project_file.use_changes_without_saving()

    failed = project.problems_status(description="Unable to add the command.")
    if failed is not None:
        # reset, maybe someone added conflicting command line types or something
        project.project_file.load()
        return failed
    else:
        project.project_file.save()
        return SimpleStatus(success=True,
                            description="Command added to project file.")
 def check(filename):
     errors = []
     extras = notebook_analyzer.extras(filename, errors)
     assert [] == errors
     assert extras == {}
 def check(filename):
     errors = []
     extras = notebook_analyzer.extras(filename, errors)
     assert [] == errors
     assert extras == {'registers_fusion_function': True}