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')
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')
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'), ), )
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'),), )
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'), ), )
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
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
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