python-rootpath


Namepython-rootpath JSON
Version 0.1.3 PyPI version JSON
download
home_pagehttps://github.com/grimen/python-python-rootpath
SummaryPython project/package root path detection.
upload_time2025-10-29 11:23:28
maintainerNone
docs_urlNone
authorJonas Grimfelt
requires_pythonNone
licenseMIT
keywords python utlity common root rootpath root-path detect autodetect auto-detect project-root project-root-path package-root package-root-path
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
# `rootpath` [![PyPI version](https://badge.fury.io/py/rootpath.svg)](https://badge.fury.io/py/rootpath) [![Build Status](https://travis-ci.com/grimen/python-rootpath.svg?branch=master)](https://travis-ci.com/grimen/python-rootpath) [![Coverage Status](https://codecov.io/gh/grimen/python-rootpath/branch/master/graph/badge.svg)](https://codecov.io/gh/grimen/python-rootpath)

*Python project/package root path detection.*


## Introduction

Auto-magic project/package root path detection - from a child module file for Python libraries/projects.

It does this by detecting typical package/project root files/folders (e.g. `.git`, `requirements.txt`, etc.), but it can also be overriden easily if needed.

As a little bonus it exposes an optional helper for adding root path to the Python load path (`sys.path`) for resolving Python module import hell (which is terribly broken by design).


## Install

Install using **pip**:

```sh
pip install rootpath
```


## Use: Basic

Detect a project/package root path:

**1.** Assuming we have a **python** library/application project...

```
/home/me/projects
    └── py-foo
            └── foo
                └── utils
                    └── __init__.py
                    └── baz.py
                    └── say.py
                └── __init__.py
                └── bar.py
            README.md
            requirements.txt
            setup.py
```

`foo/bar.py` - top level package module

```python
import rootpath

def bar():
    path = rootpath.detect()

    assert path == '/home/me/projects/py-foo'

    print('---')
    print('FILE:', __file__)
    print('ROOT:', path)
    print('---')

if __name__ == '__main__':
    bar()
```

`foo/utils/baz.py` - nested level package module (dependency)

```python
import rootpath

def baz():
    path = rootpath.detect()

    assert path == '/home/me/projects/py-foo'

    print('---')
    print('FILE:', __file__)
    print('ROOT:', path)
    print('---')

if __name__ == '__main__':
    baz()
```

`foo/utils/say.py` - nested level package module (dependency)

```python
import rootpath

def say():
    print('---')
    print('SAY: {0}'.format(rootpath.detect()))
    print('---')

if __name__ == '__main__':
    say()
```

**2.** Let's run the files individually - they should both with successful assertions and output accurately detected root paths...

```sh
$ cd /home/me/projects/py-foo

$ python ./foo/bar.py

---
FILE: /home/me/projects/py-foo/foo/bar.py
ROOT: /home/me/projects/py-foo
---

$ python ./foo/utils/baz.py

---
FILE: /home/me/projects/py-foo/foo/utils/baz.py
ROOT: /home/me/projects/py-foo
---

$ python ./foo/utils/say.py

---
SAY: /home/me/projects/py-foo
---

```


## Use: Painless Python module imports

Using the above example code project as a reference, as and example to enable painless Python module imports:

**1.** Let's make use of the load path helper in the higher order modules...

`foo/bar.py`

```python
import rootpath

# 1. prepends root path to `sys.path`
rootpath.append()

# 2. will import correctly without errors no matter if imported/executed from same path or any other system path - which is not true for the native Python 3 relative import
import foo.utils.say as say

def bar():
    say()

if __name__ == '__main__':
    bar()
```

`foo/utils/baz.py`

```python
import rootpath

# 1. prepends root path to `sys.path`
rootpath.append()

# 2. will import correctly without errors no matter if imported/executed from same path or any other system path - which is not true for the native Python 3 relative import
import foo.utils.say as say

def baz():
    hello()

if __name__ == '__main__':
    baz()
```

**2.** Let's run the files individually - `say` module should be imported correctly without any errors from any module path namespace...

```sh
$ cd /home/me/projects/py-foo

$ python ./foo/bar.py

---
SAY: /home/me/projects/py-foo
---

$ python ./foo/utils/baz.py

---
SAY: /home/me/projects/py-foo
---

$ python ./foo/utils/say.py

---
SAY: /home/me/projects/py-foo
---

$ cd /home/me/projects/py-foo/foo

$ python ./bar.py
---
SAY: /home/me/projects/py-foo
---

$ python ./utils/baz.py
---
SAY: /home/me/projects/py-foo
---

$ python ./utils/say.py

---
SAY: /home/me/projects/py-foo
---

$ cd /home/me/projects/py-foo/foo/utils

$ python ./utils/baz.py

---
SAY: /home/me/projects/py-foo
---

$ python ./utils/say.py

---
SAY: /home/me/projects/py-foo
---
```

## Change Root Detection Pattern
As stated earlier, the detection of the package/project's root directory
is done by searching for typical package files (e.g. `.git`,
`requirements.txt`, etc.).

To override this behavior and have `rootpath` use a different file for
root detection, set the `pattern` kwarg to the desired filename.

### Example: Pipfile Root Detection
```
rootpath(pattern='Pipfile')
```

## Development

### Dependencies

This project separates runtime and development dependencies:

- **Runtime dependencies** (included in deployed package): `requirements.txt`
- **Development dependencies** (only for development/testing): `requirements-dev.txt`

### Setup Development Environment

Install development dependencies:

```sh
pip install -r requirements-dev.txt
```

### Running Tests

Run tests using:

```sh
make test
```

Or using tox for multiple Python versions:

```sh
tox
```

### Building for Deployment

The deployed package only includes runtime dependencies from `requirements.txt`. Development dependencies like testing tools, coverage, linting, etc. are excluded from the deployed package automatically.

## About

This project was mainly initiated - in lack of well tested and reliable existing alternatives - to be used at our work at **[Markable.ai](https://markable.ai)** to have common code conventions between various programming environments where **Python** (research, CV, AI) is heavily used.


## License

Released under the MIT license.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/grimen/python-python-rootpath",
    "name": "python-rootpath",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "python, utlity, common, root, rootpath, root-path, detect, autodetect, auto-detect, project-root, project-root-path, package-root, package-root-path",
    "author": "Jonas Grimfelt",
    "author_email": "grimen@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/e5/65/1fabccc41d613022246ca0e9e949e1f7118f6b8212501ca81f710484a3f5/python_rootpath-0.1.3.tar.gz",
    "platform": null,
    "description": "\n# `rootpath` [![PyPI version](https://badge.fury.io/py/rootpath.svg)](https://badge.fury.io/py/rootpath) [![Build Status](https://travis-ci.com/grimen/python-rootpath.svg?branch=master)](https://travis-ci.com/grimen/python-rootpath) [![Coverage Status](https://codecov.io/gh/grimen/python-rootpath/branch/master/graph/badge.svg)](https://codecov.io/gh/grimen/python-rootpath)\n\n*Python project/package root path detection.*\n\n\n## Introduction\n\nAuto-magic project/package root path detection - from a child module file for Python libraries/projects.\n\nIt does this by detecting typical package/project root files/folders (e.g. `.git`, `requirements.txt`, etc.), but it can also be overriden easily if needed.\n\nAs a little bonus it exposes an optional helper for adding root path to the Python load path (`sys.path`) for resolving Python module import hell (which is terribly broken by design).\n\n\n## Install\n\nInstall using **pip**:\n\n```sh\npip install rootpath\n```\n\n\n## Use: Basic\n\nDetect a project/package root path:\n\n**1.** Assuming we have a **python** library/application project...\n\n```\n/home/me/projects\n    \u2514\u2500\u2500 py-foo\n            \u2514\u2500\u2500 foo\n                \u2514\u2500\u2500 utils\n                    \u2514\u2500\u2500 __init__.py\n                    \u2514\u2500\u2500 baz.py\n                    \u2514\u2500\u2500 say.py\n                \u2514\u2500\u2500 __init__.py\n                \u2514\u2500\u2500 bar.py\n            README.md\n            requirements.txt\n            setup.py\n```\n\n`foo/bar.py` - top level package module\n\n```python\nimport rootpath\n\ndef bar():\n    path = rootpath.detect()\n\n    assert path == '/home/me/projects/py-foo'\n\n    print('---')\n    print('FILE:', __file__)\n    print('ROOT:', path)\n    print('---')\n\nif __name__ == '__main__':\n    bar()\n```\n\n`foo/utils/baz.py` - nested level package module (dependency)\n\n```python\nimport rootpath\n\ndef baz():\n    path = rootpath.detect()\n\n    assert path == '/home/me/projects/py-foo'\n\n    print('---')\n    print('FILE:', __file__)\n    print('ROOT:', path)\n    print('---')\n\nif __name__ == '__main__':\n    baz()\n```\n\n`foo/utils/say.py` - nested level package module (dependency)\n\n```python\nimport rootpath\n\ndef say():\n    print('---')\n    print('SAY: {0}'.format(rootpath.detect()))\n    print('---')\n\nif __name__ == '__main__':\n    say()\n```\n\n**2.** Let's run the files individually - they should both with successful assertions and output accurately detected root paths...\n\n```sh\n$ cd /home/me/projects/py-foo\n\n$ python ./foo/bar.py\n\n---\nFILE: /home/me/projects/py-foo/foo/bar.py\nROOT: /home/me/projects/py-foo\n---\n\n$ python ./foo/utils/baz.py\n\n---\nFILE: /home/me/projects/py-foo/foo/utils/baz.py\nROOT: /home/me/projects/py-foo\n---\n\n$ python ./foo/utils/say.py\n\n---\nSAY: /home/me/projects/py-foo\n---\n\n```\n\n\n## Use: Painless Python module imports\n\nUsing the above example code project as a reference, as and example to enable painless Python module imports:\n\n**1.** Let's make use of the load path helper in the higher order modules...\n\n`foo/bar.py`\n\n```python\nimport rootpath\n\n# 1. prepends root path to `sys.path`\nrootpath.append()\n\n# 2. will import correctly without errors no matter if imported/executed from same path or any other system path - which is not true for the native Python 3 relative import\nimport foo.utils.say as say\n\ndef bar():\n    say()\n\nif __name__ == '__main__':\n    bar()\n```\n\n`foo/utils/baz.py`\n\n```python\nimport rootpath\n\n# 1. prepends root path to `sys.path`\nrootpath.append()\n\n# 2. will import correctly without errors no matter if imported/executed from same path or any other system path - which is not true for the native Python 3 relative import\nimport foo.utils.say as say\n\ndef baz():\n    hello()\n\nif __name__ == '__main__':\n    baz()\n```\n\n**2.** Let's run the files individually - `say` module should be imported correctly without any errors from any module path namespace...\n\n```sh\n$ cd /home/me/projects/py-foo\n\n$ python ./foo/bar.py\n\n---\nSAY: /home/me/projects/py-foo\n---\n\n$ python ./foo/utils/baz.py\n\n---\nSAY: /home/me/projects/py-foo\n---\n\n$ python ./foo/utils/say.py\n\n---\nSAY: /home/me/projects/py-foo\n---\n\n$ cd /home/me/projects/py-foo/foo\n\n$ python ./bar.py\n---\nSAY: /home/me/projects/py-foo\n---\n\n$ python ./utils/baz.py\n---\nSAY: /home/me/projects/py-foo\n---\n\n$ python ./utils/say.py\n\n---\nSAY: /home/me/projects/py-foo\n---\n\n$ cd /home/me/projects/py-foo/foo/utils\n\n$ python ./utils/baz.py\n\n---\nSAY: /home/me/projects/py-foo\n---\n\n$ python ./utils/say.py\n\n---\nSAY: /home/me/projects/py-foo\n---\n```\n\n## Change Root Detection Pattern\nAs stated earlier, the detection of the package/project's root directory\nis done by searching for typical package files (e.g. `.git`,\n`requirements.txt`, etc.).\n\nTo override this behavior and have `rootpath` use a different file for\nroot detection, set the `pattern` kwarg to the desired filename.\n\n### Example: Pipfile Root Detection\n```\nrootpath(pattern='Pipfile')\n```\n\n## Development\n\n### Dependencies\n\nThis project separates runtime and development dependencies:\n\n- **Runtime dependencies** (included in deployed package): `requirements.txt`\n- **Development dependencies** (only for development/testing): `requirements-dev.txt`\n\n### Setup Development Environment\n\nInstall development dependencies:\n\n```sh\npip install -r requirements-dev.txt\n```\n\n### Running Tests\n\nRun tests using:\n\n```sh\nmake test\n```\n\nOr using tox for multiple Python versions:\n\n```sh\ntox\n```\n\n### Building for Deployment\n\nThe deployed package only includes runtime dependencies from `requirements.txt`. Development dependencies like testing tools, coverage, linting, etc. are excluded from the deployed package automatically.\n\n## About\n\nThis project was mainly initiated - in lack of well tested and reliable existing alternatives - to be used at our work at **[Markable.ai](https://markable.ai)** to have common code conventions between various programming environments where **Python** (research, CV, AI) is heavily used.\n\n\n## License\n\nReleased under the MIT license.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python project/package root path detection.",
    "version": "0.1.3",
    "project_urls": {
        "Download": "https://github.com/grimen/python-python-rootpath",
        "Homepage": "https://github.com/grimen/python-python-rootpath",
        "bugs": "https://github.com/grimen/python-python-rootpath/issues",
        "repository": "https://github.com/grimen/python-python-rootpath"
    },
    "split_keywords": [
        "python",
        " utlity",
        " common",
        " root",
        " rootpath",
        " root-path",
        " detect",
        " autodetect",
        " auto-detect",
        " project-root",
        " project-root-path",
        " package-root",
        " package-root-path"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "bb70d48186ce00a02b08be20d3208b5736c4a29a51796bebd9d9a00f1cbfe802",
                "md5": "4f1c4ebe98f4c5972b72f2f3149feb59",
                "sha256": "8df7ad3db49fc3268e664c4a918a29e52193a2d95c4e227bfa66bcfc40b235de"
            },
            "downloads": -1,
            "filename": "python_rootpath-0.1.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4f1c4ebe98f4c5972b72f2f3149feb59",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 15877,
            "upload_time": "2025-10-29T11:23:27",
            "upload_time_iso_8601": "2025-10-29T11:23:27.671008Z",
            "url": "https://files.pythonhosted.org/packages/bb/70/d48186ce00a02b08be20d3208b5736c4a29a51796bebd9d9a00f1cbfe802/python_rootpath-0.1.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e5651fabccc41d613022246ca0e9e949e1f7118f6b8212501ca81f710484a3f5",
                "md5": "ce58d2c121fd7e0b8adc0bbe4295a786",
                "sha256": "bfcb561f085f71ed279c54e3f11203ed10cdefc29f57d2042ba35818989c2cce"
            },
            "downloads": -1,
            "filename": "python_rootpath-0.1.3.tar.gz",
            "has_sig": false,
            "md5_digest": "ce58d2c121fd7e0b8adc0bbe4295a786",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 13200,
            "upload_time": "2025-10-29T11:23:28",
            "upload_time_iso_8601": "2025-10-29T11:23:28.945427Z",
            "url": "https://files.pythonhosted.org/packages/e5/65/1fabccc41d613022246ca0e9e949e1f7118f6b8212501ca81f710484a3f5/python_rootpath-0.1.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-29 11:23:28",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "grimen",
    "github_project": "python-python-rootpath",
    "github_not_found": true,
    "lcname": "python-rootpath"
}
        
Elapsed time: 0.74063s