{"id":18098283,"url":"https://github.com/miki725/importanize","last_synced_at":"2025-08-19T14:32:37.292Z","repository":{"id":20163814,"uuid":"23434469","full_name":"miki725/importanize","owner":"miki725","description":"Utility for organizing Python imports using PEP8 or custom rules","archived":false,"fork":false,"pushed_at":"2022-11-02T17:55:08.000Z","size":348,"stargazers_count":66,"open_issues_count":6,"forks_count":17,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-12-09T08:45:57.218Z","etag":null,"topics":["developer-tools","importanize","python","python-imports","python3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/miki725.png","metadata":{"files":{"readme":"README.rst","changelog":"HISTORY.rst","contributing":"CONTRIBUTING.rst","funding":null,"license":"LICENSE.rst","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-28T16:09:47.000Z","updated_at":"2024-03-05T18:56:23.000Z","dependencies_parsed_at":"2022-08-31T01:33:29.320Z","dependency_job_id":null,"html_url":"https://github.com/miki725/importanize","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miki725%2Fimportanize","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miki725%2Fimportanize/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miki725%2Fimportanize/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miki725%2Fimportanize/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/miki725","download_url":"https://codeload.github.com/miki725/importanize/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229885865,"owners_count":18139383,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["developer-tools","importanize","python","python-imports","python3"],"created_at":"2024-10-31T20:09:20.789Z","updated_at":"2024-12-19T01:06:35.115Z","avatar_url":"https://github.com/miki725.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"=============================\nImportanize (import organize)\n=============================\n\n.. image:: https://badge.fury.io/py/importanize.svg\n    :target: http://badge.fury.io/py/importanize\n\n.. image:: https://drone.miki725.com/api/badges/miki725/importanize/status.svg\n    :target: https://drone.miki725.com/miki725/importanize\n\n.. image:: https://codecov.io/gh/miki725/importanize/branch/master/graph/badge.svg\n    :target: https://codecov.io/gh/miki725/importanize\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n    :target: https://github.com/psf/black\n\nUtility for organizing Python imports using PEP8 or custom rules\n\n* Free software: MIT license\n* GitHub: https://github.com/miki725/importanize\n\nInstalling\n----------\n\nYou can install ``importanize`` using pip:\n\n.. code-block:: bash\n\n    pip install importanize\n\nWhy?\n----\n\nI think imports are important in Python. There are some tools to reformat code\n(`black \u003chttps://black.readthedocs.io/en/stable/\u003e`_ is amazing). However they\nusually dont organize imports very well following PEP8 or custom rules. Top\nimport organizers are `isort \u003chttp://isort.readthedocs.org/en/latest/\u003e`_ and\n`zimports \u003chttps://github.com/sqlalchemyorg/zimports\u003e`_. ``importanize`` is\nsimilar to them in a sense that it too organizes imports using either PEP8\nor custom rules except it also preserves any comments surrounding imports.\nIn addition it supports some nifty features like full pipe support (yes you\ncan run ``:'\u003c,'\u003e!importanize`` - your welcome my fellow ``vim`` users :D) or\nit can natively output a diff between original and organized file(s).\n\nExample\n-------\n\nBefore\n++++++\n\n.. code-block:: python\n\n    $ cat tests/test_data/input_readme.py\n    from __future__ import unicode_literals, print_function\n    import os.path as ospath  # ospath is great\n    from package.subpackage.module.submodule import CONSTANT, Klass, foo, bar, rainbows\n    # UTC all the things\n    import datetime # pytz\n    from .module import foo, bar  # baz\n    from ..othermodule import rainbows\n\nAfter\n+++++\n\n.. code-block:: python\n\n    $ cat tests/test_data/input_readme.py | importanize\n    from __future__ import print_function, unicode_literals\n    # UTC all the things\n    import datetime  # pytz\n    from os import path as ospath  # ospath is great\n\n    from package.subpackage.module.submodule import (\n        CONSTANT,\n        Klass,\n        bar,\n        foo,\n        rainbows,\n    )\n\n    from ..othermodule import rainbows\n    from .module import bar, foo  # baz⏎\n\n``importanize`` did:\n\n* alphabetical sort, even inside import line (look at ``__future__``)\n* normalized ``import .. as ..`` into ``from .. import .. as ..``\n* broke long import (\u003e80 chars) which has more than one import\n  into multiple lines\n* reordered some imports (e.g. local imports ``..`` should be before ``.``)\n\nUsing\n-----\n\nUsing ``importanize`` is super easy. Just run:\n\n.. code-block:: bash\n\n    importanize file_to_organize.py\n\nThat will re-format all imports in the given file.\nAs part of the default configuration, ``importanize`` will try\nit's best to organize imports to follow PEP8 however that is a rather\nchallenging task, since it is difficult to determine all import groups\nas suggested by `PEP8 \u003chttp://legacy.python.org/dev/peps/pep-0008/#imports\u003e`_:\n\n1) standard library imports\n2) related third party imports\n3) local application/library specific imports\n\nConfiguration\n-------------\n\nTo help ``importanize`` distinguish between different import groups in most\ncases it would be recommended to use custom config file:\n\n.. code-block:: bash\n\n    importanize file_to_organize.py --config=config.json\n\nAlternatively ``importanize`` attempts to find configuration in a couple of\ndefault files:\n\n* ``.importanizerc``\n* ``importanize.ini``\n* ``importanize.json``\n* ``setup.cfg``\n* ``tox.ini``\n\nAs a matter of fact you can see the config file for the importanize\nrepository itself at\n`setup.cfg \u003chttps://github.com/miki725/importanize/blob/master/setup.cfg\u003e`_.\n\nAdditionally multiple configurations are supported within a single repository\nvia sub-configurations.\nSimply place any of supported config files (see above) within a sub-folder and\nall imports will be reconfigured under that folder with the subconfiguration.\n\nConfiguration Options\n+++++++++++++++++++++\n\n:``groups``:\n    List of import groups.\n    ``importanize`` will use these group definitions\n    to organize imports and will output import groups in the same order\n    as defined. Supported group types are:\n\n    * ``stdlib`` - standard library imports including ``__future__``\n    * ``sitepackages`` - imports coming from the ``site-packages`` directory\n    * ``local`` - local imports which start with ``\".\"``.\n      for example ``from .foo import bar``\n    * ``packages`` - if this group is specified, additional key ``packages``\n      is required within import group definition which should list\n      all Python packages (root level) which should be included in that group:\n\n      .. code-block:: ini\n\n          [importanize]\n          groups=\n            packages:foo,bar\n\n      or:\n\n      .. code-block:: json\n\n          {\n            \"type\": \"packages\",\n            \"packages\": [\"foo\", \"bar\"]\n          }\n\n    * ``remaining`` - all remaining imports which did not satisfy requirements\n      of all other groups will go to this group.\n\n    Can only be specified in configuration file.\n\n:``formatter``:\n    Select how to format long multiline imports.\n    Supported formatters:\n\n    * ``grouped`` (default):\n\n      .. code-block:: python\n\n          from package.subpackage.module.submodule import (\n              CONSTANT,\n              Klass,\n              bar,\n              foo,\n              rainbows,\n          )\n\n    * ``inline-grouped``:\n\n      .. code-block:: python\n\n          from package.subpackage.module.submodule import (CONSTANT,\n                                                           Klass,\n                                                           bar,\n                                                           foo,\n                                                           rainbows)\n\n    * ``lines``:\n\n      .. code-block:: python\n\n          from package.subpackage.module.submodule import CONSTANT\n          from package.subpackage.module.submodule import Klass\n          from package.subpackage.module.submodule import bar\n          from package.subpackage.module.submodule import foo\n          from package.subpackage.module.submodule import rainbows\n\n    Can be specified in CLI with ``-f`` or ``--formatter`` parameter:\n\n    .. code-block:: bash\n\n        importanize --formatter=grouped\n\n:``length``:\n    Line length after which the formatter will split imports.\n\n    Can be specified in CLI with ``-l`` or ``--length`` parameter:\n\n    .. code-block:: bash\n\n        importanize --length=120\n\n:``exclude``:\n    List of glob patterns of files which should be excluded from organizing:\n\n    .. code-block:: ini\n\n        [importanize]\n        exclude=\n          path/to/file\n          path/to/files/ignore_*.py\n\n    or:\n\n    .. code-block:: json\n\n        {\n          \"exclude\": [\n            \"path/to/file\",\n            \"path/to/files/ignore_*.py\"\n          ]\n        }\n\n    Can only be specified in configuration file.\n\n:``after_imports_normalize_new_lines``:\n    Boolean whether to adjust number of new lines after imports. By\n    default this option is enabled. Enabling this option will disable\n    ``after_imports_new_lines``.\n\n    Can only be specified in configuration file.\n\n:``after_imports_new_lines``:\n    Number of lines to be included after imports.\n\n    Can only be specified in configuration file.\n\n:``add_imports``:\n    List of imports to add to every file:\n\n    .. code-block:: ini\n\n        [importanize]\n        add_imports=\n          from __future__ import absolute_import, print_function, unicode_literals\n\n    or:\n\n    .. code-block:: json\n\n        {\n          \"add_imports\": [\n            \"from __future__ import absolute_import, print_function, unicode_literals\"\n          ]\n        }\n\n    Can only be specified in configuration file.\n\n    Note that this option is ignored when input is provided via ``stdin`` pipe.\n    This is on purpose to allow to importanize selected text in editors such as\n    ``vim``.\n\n    .. code-block:: bash\n\n        cat test.py | importanize\n\n:``allow_plugins``:\n    Whether to allow plugins:\n\n    .. code-block:: ini\n\n        [importanize]\n        allow_plugins=True\n\n    or:\n\n    .. code-block:: json\n\n        {\n            \"allow_plugins\": true\n        }\n\n    Can also be specified with ``--plugins/--no-plugins`` parameter.\n\n    .. code-block:: bash\n\n        importanize --no-plugins\n\n    Note that this configuration is only global and is not honored in\n    subconfigurations.\n\n:``plugins``:\n    If plugins are allowed, which plugins to use. If not specified\n    all by default enabled plugins will be used.\n\n    .. code-block:: ini\n\n        [importanize]\n        plugins=\n            unused_imports\n\n    or:\n\n    .. code-block:: json\n\n        {\n            \"plugins\": [\"unused_imports\"]\n        }\n\n    Note that this configuration is only global and is not honored in\n    subconfigurations.\n\nTo view all additional run-time options you can use ``--help`` parameter:\n\n.. code-block:: bash\n\n    importanize --help\n\nDefault Configuration\n+++++++++++++++++++++\n\nAs mentioned previously default configuration attempts to mimic PEP8.\nSpecific configuration is:\n\n.. code-block:: ini\n\n    [importanize]\n    groups=\n      stdlib\n      sitepackages\n      remainder\n      local\n\nConfiguration Styles\n++++++++++++++++++++\n\nConfiguration file can either be ``ini`` or ``json`` file. Previously ``json``\nwas the only supported style however since ``ini`` is easier to read and can\nbe combined with other configurations like ``flake8`` in ``setup.cfg``, going\nforward it is the preferred configuration format.\nThe following configurations are identical:\n\n.. code-block:: ini\n\n    [importanize]\n    formatter=grouped\n    groups=\n      stdlib\n      sitepackages\n      remainder\n      packages:my_favorite_package,least_favorite_package\n      local\n\nand:\n\n.. code-block:: json\n\n    {\n      \"formatter\": \"grouped\",\n      \"groups\": [\n        {\"type\": \"stdlib\"},\n        {\"type\": \"sitepackages\"},\n        {\"type\": \"remainder\"},\n        {\"type\": \"packages\",\n         \"packages\": [\"my_favorite_package\", \"least_favorite_package\"]},\n        {\"type\": \"local\"}\n      ]\n    }\n\nCI Mode\n-------\n\nSometimes it is useful to check if imports are already organized in a file:\n\n.. code-block:: bash\n\n    importanize --ci\n\nDiff\n----\n\nIt is possible to directly see the diff between original and organized file\n\n.. code-block:: diff\n\n    $ importanize --print --diff --no-subconfig --no-plugins tests/test_data/input_readme_diff.py\n    --- original/tests/test_data/input_readme_diff.py\n    +++ importanized/tests/test_data/input_readme_diff.py\n    @@ -1 +1,9 @@\n    -from package.subpackage.module.submodule import CONSTANT, Klass, foo, bar, rainbows\n    +from __future__ import absolute_import, print_function, unicode_literals\n    +\n    +from package.subpackage.module.submodule import (\n    +    CONSTANT,\n    +    Klass,\n    +    bar,\n    +    foo,\n    +    rainbows,\n    +)\n\nList All Imports\n----------------\n\nAll found imports can be aggregated with ``--list`` parameter:\n\n.. code-block:: bash\n\n    $ importanize --list .\n    stdlib\n    ------\n    from __future__ import absolute_import, print_function, unicode_literals\n    import abc\n    ...\n\n    sitepackages\n    ------------\n    import click\n    ...\n\n    remainder\n    ---------\n\n    packages\n    --------\n    import importanize\n    ...\n\n    local\n    -----\n    ...\n\nPipe Support\n------------\n\nPipes for both ``stdin`` and ``stdout`` are supported and are auto-detected:\n\n.. code-block:: python\n\n    $ cat tests/test_data/input_readme_diff.py | importanize\n    from package.subpackage.module.submodule import (\n        CONSTANT,\n        Klass,\n        bar,\n        foo,\n        rainbows,\n    )\n\n.. code-block:: python\n\n    $ importanize --no-header --no-subconfig --no-plugins tests/test_data/input_readme_diff.py | cat\n    from __future__ import absolute_import, print_function, unicode_literals\n\n    from package.subpackage.module.submodule import (\n        CONSTANT,\n        Klass,\n        bar,\n        foo,\n        rainbows,\n    )\n\nAs mentioned above note that ``stdin`` did not honor ``add_imports`` which\nallows to use importanize on selected lines in editors such as ``vim``.\nTo facilitate that feature even further, if selected lines are not module\nlevel (e.g. inside function), any whitespace prefix will be honored:\n\n.. code-block:: python\n\n    $ python -c \"print('    import sys\\n    import os')\" | importanize\n        import os\n        import sys\n\nJust in case pipes are incorrectly detected auto-detection can be disabled\nwith ``--no-auto-pipe`` which will require to explicitly use ``--print``,\n``--no-header`` and/or ``-`` file path:\n\n.. code-block:: python\n\n    $ cat tests/test_data/input_readme_diff.py | importanize --no-auto-pipe --print -\n    from package.subpackage.module.submodule import (\n        CONSTANT,\n        Klass,\n        bar,\n        foo,\n        rainbows,\n    )\n\nPre-Commit\n----------\n\nImportanize integrates with pre-commit_. You can use the following config\n\n.. code-block:: yaml\n\n    repos:\n    - repo: https://github.com/miki725/importanize/\n      rev: 'master'\n      hooks:\n      - id: importanize\n        args: [--verbose]\n\nTesting\n-------\n\nTo run the tests you need to install testing requirements first:\n\n.. code-block:: bash\n\n    make install\n\nThen to run tests, you can use ``nosetests`` or simply use Makefile command:\n\n.. code-block:: bash\n\n    nosetests -sv\n    # or\n    make test\n\n.. _pre-commit: https://pre-commit.com/\n\nPlugins\n-------\n\nThere is rudimentarry support for plugins. Currently plugin interface is\nlimited but allows for some useful operations. Plugins can be dynamically\nregistered via `pluggy \u003chttps://pluggy.readthedocs.io/en/latest/\u003e`_ however\n``importanize`` ships with some bundled-in plugins at ``importanize/contrib``.\n\nTo create a plugin simply implement ``ImportanizePlugin`` class.\nNote that example below does not implement all supported methods.\n\n.. code-block:: python\n\n    from importanize.plugins import ImportanizePlugin, hookimpl\n\n    class MyPlugin(ImportanizePlugin):\n        version = '0.1'\n        @hookimpl\n        def should_include_statement(self, group, statement):\n            return True\n\n    plugin = MyPlugin()\n\nThen register the plugin in ``setup.py``:\n\n.. code-block:: python\n\n    setup(\n        ...\n        entry_points={\n            \"importanize\": [\"my_plugin = my_plugin:plugin\"],\n        },\n    )\n\nAll installed plugins are listed as part of ``importanize --version`` command.\n\nBundled Plugins\n+++++++++++++++\n\nUnused Imports\n~~~~~~~~~~~~~~\n\nUses ``pyflakes`` to remove unused imports:\n\n.. code-block:: bash\n\n    $ importanize tests/test_data/input_unused_imports.py --print --diff --no-subconfig\n    --- original/tests/test_data/input_unused_imports.py\n    +++ importanized/tests/test_data/input_unused_imports.py\n    @@ -1,5 +1,5 @@\n    +from __future__ import absolute_import, print_function, unicode_literals\n     import os\n    -import sys\n\n\n     os.path.exists('.')\n\nThis plugin is enabled by default. To disable removing unused imports you can\neither:\n\n* disable all plugins via ``allow_plugins``:\n\n  .. code-block:: ini\n\n      allow_plugins=false\n\n* disable ``unused_imports`` specific plugin by omitting it from ``plugins``\n  configuration:\n\n  .. code-block:: ini\n\n      plugins=\n        # other plugins except unused_imports\n\n* add ``# noqa`` comment to unused imports to not remove them\n\nSeparate Libraries\n~~~~~~~~~~~~~~~~~~\n\nSplits all libraries into independant blocks within import groups:\n\n.. code-block:: bash\n\n    $ importanize tests/test_data/input_separate_libs.py --print --diff --no-subconfig -c tests/test_data/subconfig/separate_libs.ini\n    --- original/tests/test_data/input_separate_libs.py\n    +++ importanized/tests/test_data/input_separate_libs.py\n    @@ -2,6 +2,7 @@\n     import sys\n\n     import click\n    +\n     import pluggy\n\n     from . import foo\n\nThis plugin is not enabled by default. To enable add ``separate_libs`` to\n``plugins`` configuration:\n\n.. code-block:: ini\n\n    plugins=\n      separate_libs\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmiki725%2Fimportanize","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmiki725%2Fimportanize","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmiki725%2Fimportanize/lists"}