def apply_import_ordering(xmldoc):
    compiler_settings = get_compiler_settings_directive(xmldoc)
    extends = get_extends_directive(xmldoc)
    implements = get_implements_directive(xmldoc)
    initial_block = [
        obj for obj in [compiler_settings, extends, implements]
        if obj is not None
    ]

    cheetah_imports = get_all_imports(xmldoc)
    # Remove all of the elements from the document
    for cheetah_import in cheetah_imports:
        cheetah_import.directive_element.remove_self()

    sorted_blocks = sort([
        cheetah_import.import_obj for cheetah_import in cheetah_imports
    ])

    element = lxml.etree.Element('Imports')
    element.text = '\n'.join(
        combine_import_objs(block) for block in sorted_blocks
    )
    xmldoc.insert(0, element)

    if initial_block:
        ws_element = lxml.etree.Element('Whitespace')
        ws_element.text = '\n'
        xmldoc.insert(0, ws_element)
        for directive in reversed(initial_block):
            directive.remove_self()
            xmldoc.insert(0, directive)

    return xmldoc.totext(encoding='unicode')
Beispiel #2
0
def apply_import_ordering(xmldoc):
    compiler_settings = get_compiler_settings_directive(xmldoc)
    extends = get_extends_directive(xmldoc)
    implements = get_implements_directive(xmldoc)
    initial_block = [
        obj for obj in [compiler_settings, extends, implements]
        if obj is not None
    ]

    cheetah_imports = get_all_imports(xmldoc)
    # Remove all of the elements from the document
    for cheetah_import in cheetah_imports:
        cheetah_import.directive_element.remove_self()

    sorted_blocks = sort(
        [cheetah_import.import_obj for cheetah_import in cheetah_imports])

    element = lxml.etree.Element('Imports')
    element.text = '\n'.join(
        combine_import_objs(block) for block in sorted_blocks)
    xmldoc.insert(0, element)

    if initial_block:
        ws_element = lxml.etree.Element('Whitespace')
        ws_element.text = '\n'
        xmldoc.insert(0, ws_element)
        for directive in reversed(initial_block):
            directive.remove_self()
            xmldoc.insert(0, directive)

    return xmldoc.totext(encoding='unicode')
Beispiel #3
0
def test_not_separate_not_import_before_from():
    ret = sort(IMPORTS, separate=False, import_before_from=False)
    assert ret == ((
        FromImport.from_str('from aspy import refactor_imports'),
        FromImport.from_str('from os import path'),
        ImportImport.from_str('import pyramid'),
        ImportImport.from_str('import sys'),
    ), )
def test_not_separate_not_import_before_from():
    ret = sort(IMPORTS, separate=False, import_before_from=False)
    assert ret == (
        (
            FromImport.from_str('from aspy import refactor_imports'),
            FromImport.from_str('from os import path'),
            ImportImport.from_str('import pyramid'),
            ImportImport.from_str('import sys'),
        ),
    )
Beispiel #5
0
def test_passes_through_kwargs_to_classify(in_tmpdir, no_empty_path):
    # Make a module
    in_tmpdir.join('my_module.py').ensure()

    imports = (
        ImportImport.from_str('import my_module'),
        ImportImport.from_str('import pyramid'),
    )
    # Without kwargs, my_module should get classified as application (in a
    # separate group).
    ret = sort(imports)
    assert ret == (
        (ImportImport.from_str('import pyramid'), ),
        (ImportImport.from_str('import my_module'), ),
    )
    # But when we put the application at a nonexistent directory
    # it'll be third party (and in the same group as pyramid)
    ret = sort(imports, application_directories=('dne', ))
    assert ret == (imports, )
def test_passes_through_kwargs_to_classify(in_tmpdir, no_empty_path):
    # Make a module
    in_tmpdir.join('my_module.py').ensure()

    imports = (
        ImportImport.from_str('import my_module'),
        ImportImport.from_str('import pyramid'),
    )
    # Without kwargs, my_module should get classified as application (in a
    # separate group).
    ret = sort(imports)
    assert ret == (
        (ImportImport.from_str('import pyramid'),),
        (ImportImport.from_str('import my_module'),),
    )
    # But when we put the application at a nonexistent directory
    # it'll be third party (and in the same group as pyramid)
    ret = sort(imports, application_directories=('dne',))
    assert ret == (imports,)
def test_separate_relative():
    ret = sort(RELATIVE_IMPORTS)
    assert ret == (
        (
            ImportImport.from_str('import sys'),
            FromImport.from_str('from os import path'),
        ),
        (ImportImport.from_str('import pyramid'), ),
        (
            FromImport.from_str('from .sort import sort'),
            FromImport.from_str('from aspy import refactor_imports'),
        ),
    )

    ret = sort(RELATIVE_IMPORTS, separate_relative=True)
    assert ret == ((
        ImportImport.from_str('import sys'),
        FromImport.from_str('from os import path'),
    ), (ImportImport.from_str('import pyramid'), ), (
        FromImport.from_str('from aspy import refactor_imports'), ),
                   (FromImport.from_str('from .sort import sort'), ))
def test_future_separate_block_non_separate():
    ret = sort(
        (
            FromImport.from_str('from __future__ import absolute_import'),
            ImportImport.from_str('import pyramid'),
        ),
        separate=False,
        import_before_from=True,
    )
    assert ret == (
        (FromImport.from_str('from __future__ import absolute_import'),),
        (ImportImport.from_str('import pyramid'),),
    )
Beispiel #9
0
def test_future_separate_block_non_separate():
    ret = sort(
        (
            FromImport.from_str('from __future__ import absolute_import'),
            ImportImport.from_str('import pyramid'),
        ),
        separate=False,
        import_before_from=True,
    )
    assert ret == (
        (FromImport.from_str('from __future__ import absolute_import'), ),
        (ImportImport.from_str('import pyramid'), ),
    )
Beispiel #10
0
def apply_import_sorting(partitions, **sort_kwargs):
    pre_import_code = []
    imports = []
    trash = []
    rest = []
    for partition in partitions:
        {
            CodeType.PRE_IMPORT_CODE: pre_import_code,
            CodeType.IMPORT: imports,
            CodeType.NON_CODE: trash,
            CodeType.CODE: rest,
        }[partition.code_type].append(partition)

    # Need to give an import a newline if it doesn't have one (needed for no
    # EOL)
    imports = [
        partition if partition.src.endswith('\n') else
        CodePartition(CodeType.IMPORT, partition.src + '\n')
        for partition in imports
    ]

    import_obj_to_partition = dict(
        (import_obj_from_str(partition.src), partition)
        for partition in imports
    )

    new_imports = []
    sorted_blocks = sort(import_obj_to_partition.keys(), **sort_kwargs)
    for block in sorted_blocks:
        for import_obj in block:
            new_imports.append(import_obj_to_partition[import_obj])
        new_imports.append(CodePartition(CodeType.NON_CODE, '\n'))
    # XXX: I want something like [x].join(...) (like str join) but for now
    # this works
    if new_imports:
        new_imports.pop()

    # There's the potential that we moved a bunch of whitespace onto the
    # beginning of the rest of the code.  To fix this, we're going to combine
    # all of that code, and then make sure there are two linebreaks to start
    restsrc = _partitions_to_src(rest)
    restsrc = restsrc.rstrip()
    if restsrc:
        rest = [
            CodePartition(CodeType.CODE, restsrc + '\n'),
        ]
    else:
        rest = []

    return pre_import_code + new_imports + rest
Beispiel #11
0
def apply_import_sorting(partitions, **sort_kwargs):
    pre_import_code = []
    imports = []
    trash = []
    rest = []
    for partition in partitions:
        {
            CodeType.PRE_IMPORT_CODE: pre_import_code,
            CodeType.IMPORT: imports,
            CodeType.NON_CODE: trash,
            CodeType.CODE: rest,
        }[partition.code_type].append(partition)

    # Need to give an import a newline if it doesn't have one (needed for no
    # EOL)
    imports = [
        partition if partition.src.endswith('\n') else CodePartition(
            CodeType.IMPORT, partition.src + '\n') for partition in imports
    ]

    import_obj_to_partition = dict(
        (import_obj_from_str(partition.src), partition)
        for partition in imports)

    new_imports = []
    sorted_blocks = sort(import_obj_to_partition.keys(), **sort_kwargs)
    for block in sorted_blocks:
        for import_obj in block:
            new_imports.append(import_obj_to_partition[import_obj])
        new_imports.append(CodePartition(CodeType.NON_CODE, '\n'))
    # XXX: I want something like [x].join(...) (like str join) but for now
    # this works
    if new_imports:
        new_imports.pop()

    # There's the potential that we moved a bunch of whitespace onto the
    # beginning of the rest of the code.  To fix this, we're going to combine
    # all of that code, and then make sure there are two linebreaks to start
    restsrc = _partitions_to_src(rest)
    restsrc = restsrc.rstrip()
    if restsrc:
        rest = [
            CodePartition(CodeType.CODE, restsrc + '\n'),
        ]
    else:
        rest = []

    return pre_import_code + new_imports + rest
Beispiel #12
0
def apply_import_sorting(partitions,
                         separate_relative=False,
                         separate_from_import=False,
                         **sort_kwargs):
    pre_import_code = []
    imports = []
    trash = []
    rest = []
    for partition in partitions:
        {
            CodeType.PRE_IMPORT_CODE: pre_import_code,
            CodeType.IMPORT: imports,
            CodeType.NON_CODE: trash,
            CodeType.CODE: rest,
        }[partition.code_type].append(partition)

    # Need to give an import a newline if it doesn't have one (needed for no
    # EOL)
    imports = [
        partition if partition.src.endswith('\n') else CodePartition(
            CodeType.IMPORT, partition.src + '\n') for partition in imports
    ]

    import_obj_to_partition = {
        import_obj_from_str(partition.src): partition
        for partition in imports
    }

    new_imports = []
    relative_imports = []

    def _import_type_switches(last_import_obj, import_obj):
        """Returns True if separate_from_import is True and  `import_obj` is
        :class:`aspy.refactor_imports.import_obj.FromImport`
        and ``last_import_obj`` is
        :class:`aspy.refactor_imports.import_obj.ImportImport`
        """
        return (separate_from_import and last_import_obj is not None
                and type(last_import_obj) is not type(import_obj))

    sorted_blocks = sort(import_obj_to_partition.keys(), **sort_kwargs)
    for block in sorted_blocks:
        last_import_obj = None

        for import_obj in block:
            if separate_relative and import_obj.is_explicit_relative:
                relative_imports.append(import_obj_to_partition[import_obj])
            else:
                if _import_type_switches(last_import_obj, import_obj):
                    new_imports.append(CodePartition(CodeType.NON_CODE, '\n'))

                last_import_obj = import_obj
                new_imports.append(import_obj_to_partition[import_obj])

        # There's an edge case if both --separate-relative and
        # --separate-from-import are passed where the first-party imports
        # will *all* be explicit relative imports and sorted into the special
        # block.  In this case, we don't want the first-party block to just
        # be a single newline.  See #23
        if last_import_obj is not None:
            new_imports.append(CodePartition(CodeType.NON_CODE, '\n'))

    if relative_imports:
        relative_imports.insert(0, CodePartition(CodeType.NON_CODE, '\n'))
    # XXX: I want something like [x].join(...) (like str join) but for now
    # this works
    if new_imports:
        new_imports.pop()

    # There's the potential that we moved a bunch of whitespace onto the
    # beginning of the rest of the code.  To fix this, we're going to combine
    # all of that code, and then make sure there are two linebreaks to start
    restsrc = _partitions_to_src(rest)
    restsrc = restsrc.rstrip()
    if restsrc:
        rest = [CodePartition(CodeType.CODE, restsrc + '\n')]
    else:
        rest = []

    return pre_import_code + new_imports + relative_imports + rest
def apply_import_sorting(
        partitions,
        separate_relative=False,
        separate_from_import=False,
        **sort_kwargs
):
    pre_import_code = []
    imports = []
    trash = []
    rest = []
    for partition in partitions:
        {
            CodeType.PRE_IMPORT_CODE: pre_import_code,
            CodeType.IMPORT: imports,
            CodeType.NON_CODE: trash,
            CodeType.CODE: rest,
        }[partition.code_type].append(partition)

    # Need to give an import a newline if it doesn't have one (needed for no
    # EOL)
    imports = [
        partition if partition.src.endswith('\n') else
        CodePartition(CodeType.IMPORT, partition.src + '\n')
        for partition in imports
    ]

    import_obj_to_partition = dict(
        (import_obj_from_str(partition.src), partition)
        for partition in imports
    )

    new_imports = []
    relative_imports = []

    def _import_type_switches(last_import_obj, import_obj):
        """Returns True if separate_from_import is True and  `import_obj` is
        :class:`aspy.refactor_imports.import_obj.FromImport`
        and ``last_import_obj`` is
        :class:`aspy.refactor_imports.import_obj.ImportImport`
        """
        return (
            separate_from_import and
            last_import_obj is not None and
            type(last_import_obj) is not type(import_obj)
        )

    sorted_blocks = sort(import_obj_to_partition.keys(), **sort_kwargs)
    for block in sorted_blocks:
        last_import_obj = None

        for import_obj in block:
            if separate_relative and import_obj.is_explicit_relative:
                relative_imports.append(import_obj_to_partition[import_obj])
            else:
                if _import_type_switches(last_import_obj, import_obj):
                    new_imports.append(CodePartition(CodeType.NON_CODE, '\n'))

                last_import_obj = import_obj
                new_imports.append(import_obj_to_partition[import_obj])

        # There's an edge case if both --separate-relative and
        # --separate-from-import are passed where the first-party imports
        # will *all* be explicit relative imports and sorted into the special
        # block.  In this case, we don't want the first-party block to just
        # be a single newline.  See #23
        if last_import_obj is not None:
            new_imports.append(CodePartition(CodeType.NON_CODE, '\n'))

    if relative_imports:
        relative_imports.insert(0, CodePartition(CodeType.NON_CODE, '\n'))
    # XXX: I want something like [x].join(...) (like str join) but for now
    # this works
    if new_imports:
        new_imports.pop()

    # There's the potential that we moved a bunch of whitespace onto the
    # beginning of the rest of the code.  To fix this, we're going to combine
    # all of that code, and then make sure there are two linebreaks to start
    restsrc = _partitions_to_src(rest)
    restsrc = restsrc.rstrip()
    if restsrc:
        rest = [
            CodePartition(CodeType.CODE, restsrc + '\n'),
        ]
    else:
        rest = []

    return pre_import_code + new_imports + relative_imports + rest