Convert relative imports to absolute

Overview

Build Status Coverage pre-commit.ci status

absolufy-imports

A tool and pre-commit hook to automatically convert relative imports to absolute.

demo

Installation

$ pip install absolufy-imports

Usage as a pre-commit hook (recommended)

See pre-commit for instructions

Sample .pre-commit-config.yaml:

-   repo: https://github.com/MarcoGorelli/absolufy-imports
    rev: v0.3.0
    hooks:
    -   id: absolufy-imports

Command-line example

$ cat mypackage/myfile.py
from . import __version__
$ absolufy-imports mypackage/myfile.py
$ cat mypackage/myfile.py
from mypackage import __version__

Configuration

Application directories

If your package follows the popular ./src layout, you can pass your application directories via --application-directories, e.g.

$ cat src/mypackage/myfile.py
from . import __version__
$ absolufy-imports src/mypackage/myfile.py --application-directories src
$ cat src/mypackage/myfile.py
from mypackage import __version__

Multiple application directories should be comma-separated, e.g. --application-directories .:src. This is the same as in reorder-python-imports.

Only use relative imports

Use the --never flag, e.g.

$ cat mypackage/myfile.py
from mypackage import __version__
$ absolufy-imports mypackage/myfile.py --never
$ cat mypackage/myfile.py
from . import __version__

Keep submodules relative

Use the --keep-submodules-relative flag. By default, submodules are considered to be the first level of the directory. E.g. if you have

├── mypackage
│   ├── library1
│   │   ├── foo.py
│   │   └── subdirectory
│   │       ├── bar.py
│   │       └── baz.py
│   └── library2
│       └── qux.py

and

$ cat mypackage/library1/subdirectory/bar.py
from mypackage.library1.subdirectory import baz
from mypackage.library1 import foo
from mypackage.library2 import qux

then you will get

$ absolufy-imports mypackage/library1/subdirectory/bar.py --keep-submodules-relative
$ cat mypackage/library1/subdirectory/bar.py
from . import baz
from .. import foo
from mypackage.library2 import qux

To specify a custom list of submodules, you can use the --submodules flag, e.g.

$ absolufy-imports mypackage/library1/subdirectory/bar.py \
  --keep-submodules-relative \
  --submodules '{".": ["mypackage.library1", "mypackage.library2"]}'

Note that they need to be in json format, and the keys should be the application directories.

See also

Check out pyupgrade, which I learned a lot from when writing this.

Comments
  • Packages and Python built-in imports are not supported when the project has somewhere a folder with the same name

    Packages and Python built-in imports are not supported when the project has somewhere a folder with the same name

    Bugs:

    # Original (correct) import
    from collections.abc import Iterable
    
    # Changed automatically to a wrong
    from ..abc import Iterable
    
    # Original (correct) import
    from google.cloud import vision
    
    # Changed automatically to a wrong
    from .cloud import vision
    

    Project structure:

    project/
        src/
            collections/
                foo/
                bar/
            google/
                spam/
                eggs/
    

    As you see, if a sub-directory matches 3rd-party package or Python module, the 'absolufy-imports' makes mistakes.

    Possible solutions

    • Check that import is a 3rd-party package. Do not make such imports relative.
    • Another possible solution is to allow to ignore manually specific names. For example, I will ignore names "collections" and "google".
    bug help wanted 
    opened by AIGeneratedUsername 7
  • feat: using just the package name as input convert relative paths to …

    feat: using just the package name as input convert relative paths to …

    …absolute import paths

    Using the below command you just need to specify the package name on which: absolufy-imports - will walk and convert relative import paths to absolute import python paths.

    $ absolufy-imports --package your_package_name
    

    No need to specify the module using this command.

    The issue I found was that absolufy-imports didn't converted from from ..n2_module import func3 to from package.n2.n2_module import func3 as it should, the import was converted to from n2.n2_module import func3.

    The changes don't affect the current setup.

    package.zip

    opened by ClimenteA 6
  • Can't parse files with BOM

    Can't parse files with BOM

    absolufy-imports 0.3.0 cannot parse a python file with a BOM.

    For example, download bom.py.txt and rename it bom.py (this is a necessary step on GitHub as only *.txt files can be attached), move it into an example project (e.g. src), see the following:

    $ cat src/bom.py
    import sys
    $ file src/bom.py	
    src/bom.py: UTF-8 Unicode (with BOM) text
    $ python src/bom.py
    $ absolufy-imports src/bom.py
    Traceback (most recent call last):
      File "/tmp/py310/bin/absolufy-imports", line 8, in <module>
        sys.exit(main())
      File "/tmp/py310/lib/python3.10/site-packages/absolufy_imports.py", line 208, in main
        absolute_imports(
      File "/tmp/py310/lib/python3.10/site-packages/absolufy_imports.py", line 151, in absolute_imports
        tree = ast.parse(txt)
      File "/opt/python-3.10.0/lib/python3.10/ast.py", line 50, in parse
        return compile(source, filename, mode, flags,
      File "<unknown>", line 1
        import sys
        ^
    SyntaxError: invalid non-printable character U+FEFF
    

    Perhaps a better message could help? Or try to compare these two uses reading the source file, the last with encoding='utf-8-sig':

    $ python -c "from ast import parse; from pathlib import Path; parse(Path('src/bom.py').read_text())"
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/opt/python-3.10.0/lib/python3.10/ast.py", line 50, in parse
        return compile(source, filename, mode, flags,
      File "<unknown>", line 1
        import sys
        ^
    SyntaxError: invalid non-printable character U+FEFF
    $ python -c "from ast import parse; from pathlib import Path; parse(Path('src/bom.py').read_text(encoding='utf-8-sig'))"
    $ 
    
    opened by mwtoews 5
  • --keep-relative-imports in __init__.py files only

    --keep-relative-imports in __init__.py files only

    Hello Marco,

    Thank you for great tool. It very helps me to keep source clean.

    I have a question and\or suggestion. Is it possible to add command-line argument to make keep-submodules-relative works on init.py files only?

    It is very common to use init.py file as a facade to classes and functions from the module, and abosolute imports are quiet annoying here:

    # my_application/package/another_package/__init__.py
    from .foo import bar
    from .foo1 import bar1
    

    vs

    # my_application/package/another_package/__init__.py
    from my_application.package.another_package.foo import bar
    from my_application.package.another_package.foo1 import bar1
    
    opened by Zagrebelin 4
  • It doesn't work on the cuda-python repo

    It doesn't work on the cuda-python repo

    https://github.com/NVIDIA/cuda-python/issues/38

    I did

    (cython) nyck33@nyck33-IdeaPad-Gaming-3-15ACH6:~/Documents/cuda-start-dec2022/cuda-python/examples/0_Introduction$ python clock_nvrtc_test.py
    Traceback (most recent call last):
      File "/home/nyck33/Documents/cuda-start-dec2022/cuda-python/examples/0_Introduction/clock_nvrtc_test.py", line 10, in <module>
        from examples.common import common
    ModuleNotFoundError: No module named 'examples'
    (cython) nyck33@nyck33-IdeaPad-Gaming-3-15ACH6:~/Documents/cuda-start-dec2022/cuda-python/examples/0_Introduction$ ls
    clock_nvrtc_test.py  simpleCubemapTexture_test.py  simpleZeroCopy_test.py     vectorAddDrv_test.py
    __init__.py          simpleP2P_test.py             systemWideAtomics_test.py  vectorAddMMAP_test.py
    (cython) nyck33@nyck33-IdeaPad-Gaming-3-15ACH6:~/Documents/cuda-start-dec2022/cuda-python/examples/0_Introduction$ absolufy-imports clock_nvrtc_test.py
    (cython) nyck33@nyck33-IdeaPad-Gaming-3-15ACH6:~/Documents/cuda-start-dec2022/cuda-python/examples/0_Introduction$ absolufy-imports clock_nvrtc_test.py
    (cython) nyck33@nyck33-IdeaPad-Gaming-3-15ACH6:~/Documents/cuda-start-dec2022/cuda-python/examples/0_Introduction$ python clock_nvrtc_test.py
    Traceback (most recent call last):
      File "/home/nyck33/Documents/cuda-start-dec2022/cuda-python/examples/0_Introduction/clock_nvrtc_test.py", line 10, in <module>
        from examples.common import common
    ModuleNotFoundError: No module named 'examples'
    (cython) nyck33@nyck33-IdeaPad-Gaming-3-15ACH6:~/Documents/cuda-start-dec2022/cuda-python/examples/0_Introduction$ 
    
    opened by nyck33 3
  • Provide directory or package as input

    Provide directory or package as input

    Hello!

    Awesome project - I was very happy when found it, and this is a really time saver :)

    I have a Django project with a following structure:

    server
    ├── Dockerfile
    ├── action_requests (package)
    ├── config (package)
    ├── manage.py
    ├── persons (package)
    
    

    While using this amazing tool I faced with a problem when I tried to pass a whole directory of project to absolufy-imports and this caused problems:

    ▶ absolufy-imports server
    Traceback (most recent call last):
      File "/Users/artinnok/Library/Caches/pypoetry/virtualenvs/backend-6XZmvTyF-py3.9/bin/absolufy-imports", line 8, in <module>
        sys.exit(main())
      File "/Users/artinnok/Library/Caches/pypoetry/virtualenvs/backend-6XZmvTyF-py3.9/lib/python3.9/site-packages/absolufy_imports.py", line 208, in main
        absolute_imports(
      File "/Users/artinnok/Library/Caches/pypoetry/virtualenvs/backend-6XZmvTyF-py3.9/lib/python3.9/site-packages/absolufy_imports.py", line 149, in absolute_imports
        with open(file, encoding='utf-8') as fd:
    IsADirectoryError: [Errno 21] Is a directory: 'server'
    

    Then I tried to do the same with package action_requests inside server project and faced with same issue.

    In every package I have about 15-20 Python files and it is tedious to run absolufy-imports on every file of package :((( Is it possible to add support for folders / packages in future?

    Thanks for great tool.

    P.S. I think this will force me to write something like a bash-wrapper around absolufy-imports :((

    enhancement help wanted good first issue 
    opened by artinnok 2
  • Add option to just

    Add option to just "absolufy" level-up imports

    At Astropy we are considering adopting absolute imports (https://github.com/astropy/astropy/issues/14021) but may not be ready to go all in. An option to only absolufy level-up imports, like from ..import <> would be greatly appreciated!

    opened by nstarman 1
  • Feature: Add `--depth N` for controlling relative depth when absolufying

    Feature: Add `--depth N` for controlling relative depth when absolufying

    Hello, @MarcoGorelli Thank you for the project, very cool! 👍

    We would like to suggest this feature which will provide a fine-grained control for absolufying imports.

    Feature:

    • add --depth N option (default to 0, normal behavior)

    For example:

    • with --depth 1 you can specify to absolufy from .. import X and to keep from . import X. --depth 1 meaning we keep at least 1 level of relative import
      • Keep from . or from .foo
      • Absolufy: from .. or from .foo.bar

    This setting allows (for example) to build architectures of packages using only 1 level of relative imports.

    We are opened to suggestions so don't hesitate to request any change.

    opened by folkvir 1
  • Define an authorized level of relativity

    Define an authorized level of relativity

    I would love to use your module but it is lacking something essential IMO: allow relative imports inside the same folder, i.e, allow from .a import b but not allow from ..a import b.

    Most people find it more legible to reference siblings files relatively as you can see/list them. However, as soon as the import to parent folders, it becomes very difficult to read, specially from ............a import b

    maybe we could add a relative_level: int to the settings, with

    • 0 meaning replace all relative imports
    • 1 meaning keep only single dot (ex from .a import b)
    • 2 meaning keep up to two dots (ex from ..a import b)
    • etc...
    opened by anis-campos 1
  • Enable linting of stub files (`.pyi`) in pre-commit hook

    Enable linting of stub files (`.pyi`) in pre-commit hook

    opened by Apakottur 4
Owner
Marco Gorelli
@pandas-dev
Marco Gorelli
Tool for automatically reordering python imports. Similar to isort but uses static analysis more.

reorder_python_imports Tool for automatically reordering python imports. Similar to isort but uses static analysis more. Installation pip install reor

Anthony Sottile 589 Dec 26, 2022
Tools for improving Python imports

imptools Tools for improving Python imports. Installation pip3 install imptools Overview Detailed docs import_path Import a module from any path on th

Danijar Hafner 7 Aug 7, 2022
Utilities for refactoring imports in python-like syntax.

aspy.refactor_imports Utilities for refactoring imports in python-like syntax. Installation pip install aspy.refactor_imports Examples aspy.refactor_i

Anthony Sottile 20 Nov 1, 2022
Tool for pinpointing circular imports in Python. Find cyclic imports in any project

Pycycle: Find and fix circular imports in python projects Pycycle is an experimental project that aims to help python developers fix their circular de

Vadim Kravcenko 311 Dec 15, 2022
VSCode extension to sort and refactor python imports using reorder-python-imports.

reorder-python-imports VSCode extension to sort and refactor python imports using reorder-python-imports. Unlike other import organizers, reorder-pyth

Ryan Butler 3 Aug 26, 2022
Python avatar generator for absolute nerds

pagan Welcome to the Python Avatar Generator for Absolute Nerds. Current version: 0.4.3 View the change history here. Remember those good old days whe

David Bothe 280 Dec 16, 2022
Absolute solvation free energy calculations with OpenFF and OpenMM

ABsolute SOLVantion Free Energy Calculations The absolv framework aims to offer a simple API for computing the change in free energy when transferring

null 7 Dec 7, 2022
QLUSTER is a relative orbit design tool for formation flying satellite missions and space rendezvous scenarios

QLUSTER is a relative orbit design tool for formation flying satellite missions and space rendezvous scenarios, that I wrote in Python 3 for my own research and visualisation. It is currently unfinished (95%) but the core algorithm and app works. Here's an example snippet of the GUI where four deputy satellites are orbiting a single chief in LEO.

Samuel Low 9 Aug 23, 2022
Relative Positional Encoding for Transformers with Linear Complexity

Stochastic Positional Encoding (SPE) This is the source code repository for the ICML 2021 paper Relative Positional Encoding for Transformers with Lin

Antoine Liutkus 48 Nov 16, 2022
Fast and robust certifiable relative pose estimation

Fast and Robust Relative Pose Estimation for Calibrated Cameras This repository contains the code for the relative pose estimation between two central

null 42 Dec 6, 2022
Relative Uncertainty Learning for Facial Expression Recognition

Relative Uncertainty Learning for Facial Expression Recognition The official implementation of the following paper at NeurIPS2021: Title: Relative Unc

null 35 Dec 28, 2022
This is a python based command line Network Scanner utility, which input as an argument for the exact IP address or the relative IP Address range you wish to do the Network Scan for and returns all the available IP addresses with their MAC addresses on your current Network.

This is a python based command line Network Scanner utility, which input as an argument for the exact IP address or the relative IP Address range you wish to do the Network Scan for and returns all the available IP addresses with their MAC addresses on your current Network.

Abhinandan Khurana 1 Feb 9, 2022
Relative Human dataset, CVPR 2022

Relative Human (RH) contains multi-person in-the-wild RGB images with rich human annotations, including: Depth layers (DLs): relative depth relationsh

Yu Sun 112 Dec 2, 2022
A Python utility / library to sort imports.

Read Latest Documentation - Browse GitHub Code Repository isort your imports, so you don't have to. isort is a Python utility / library to sort import

Python Code Quality Authority 5.5k Jan 6, 2023
Removes unused imports and unused variables as reported by pyflakes

autoflake Introduction autoflake removes unused imports and unused variables from Python code. It makes use of pyflakes to do this. By default, autofl

Steven Myint 678 Jan 4, 2023
pipreqs - Generate pip requirements.txt file based on imports of any project. Looking for maintainers to move this project forward.

pipreqs - Generate requirements.txt file for any project based on imports Installation pip install pipreqs Usage Usage: pipreqs [options] <path>

Vadim Kravcenko 4.8k Dec 31, 2022
isort is a Python utility / library to sort imports alphabetically, and automatically separated into sections and by type.

isort is a Python utility / library to sort imports alphabetically, and automatically separated into sections and by type. It provides a command line utility, Python library and plugins for various editors to quickly sort all your imports.

Python Code Quality Authority 5.5k Jan 8, 2023
Group imports from Windows binaries

importsort This is a tool that I use to group imports from Windows binaries. Sometimes, you have a gigantic folder full of executables, and you want t

【☆ ゆう ☆ 】 15 Aug 27, 2022
Playing with python imports and inducing those pesky errors.

super-duper-python-imports In this repository we are playing with python imports and inducing those pesky ImportErrors. File Organization project │

James Kelsey 2 Oct 14, 2021