Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enhance] Support for installing minimal runtime dependencies #1362

Merged
merged 13 commits into from
Oct 8, 2023
Merged
31 changes: 31 additions & 0 deletions .circleci/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,33 @@ jobs:
name: Run unit tests
command: pytest tests/test_config tests/test_registry tests/test_fileio tests/test_logging tests/test_utils --ignore=tests/test_utils/test_dl_utils

build_lite:
parameters:
# The python version must match available image tags in
# https://circleci.com/developer/images/image/cimg/python
python:
type: string
default: "3.7.4"
docker:
- image: cimg/python:<< parameters.python >>
resource_class: large
steps:
- checkout
- run:
name: Upgrade pip
command: |
pip install pip --upgrade
pip --version
- run:
name: Build MMEngine from source
command: MMENGINE_LITE=1 pip install -e . -v
- run:
name: Install unit tests dependencies
command: pip install -r requirements/tests_lite.txt
- run:
name: Run unit tests
command: pytest tests/test_config tests/test_registry tests/test_logging tests/test_utils --ignore=tests/test_utils/test_dl_utils

build_cpu:
parameters:
# The python version must match available image tags in
Expand Down Expand Up @@ -217,6 +244,10 @@ workflows:
branches:
ignore:
- main
- build_lite:
name: build lite
requires:
- lint
- build_without_torch:
name: build without torch
requires:
Expand Down
9 changes: 9 additions & 0 deletions docs/en/get_started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@

## Install MMEngine

:::{note}
If you only want to use the fileio, registry, and config modules in MMEngine, you can set the `MMENGINE_LITE` environment variable, which will only install the few third-party library dependencies that are necessary (e.g., it will not install opencv, matplotlib):

```bash
MMENGINE_LITE=1 pip install mmengine
```

:::

### Install with mim

[mim](https://github.com/open-mmlab/mim) is a package management tool for OpenMMLab projects, which can be used to install the OpenMMLab project easily.
Expand Down
9 changes: 9 additions & 0 deletions docs/zh_cn/get_started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@

## 安装 MMEngine

:::{note}
如果你只想使用 MMEngine 中的 fileio、registry 和 config 模块,你可以设置 `MMENGINE_LITE` 环境变量,它只会安装必须的几个第三方库依赖(例如不会安装 opencv、matplotlib):

```bash
MMENGINE_LITE=1 pip install mmengine
```

:::

### 使用 mim 安装

[mim](https://github.com/open-mmlab/mim) 是 OpenMMLab 项目的包管理工具,使用它可以很方便地安装 OpenMMLab 项目。
Expand Down
7 changes: 7 additions & 0 deletions requirements/runtime_lite.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
addict
numpy
pyyaml
regex;sys_platform=='win32'
rich
termcolor
yapf
2 changes: 2 additions & 0 deletions requirements/tests_lite.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
parameterized
pytest
32 changes: 18 additions & 14 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import re
from setuptools import find_packages, setup # type: ignore

Expand Down Expand Up @@ -106,20 +107,23 @@ def gen_packages_items():
return packages


install_requires = parse_requirements()
try:
# OpenCV installed via conda.
import cv2 # NOQA: F401
major, minor, *rest = cv2.__version__.split('.')
if int(major) < 3:
raise RuntimeError(
f'OpenCV >=3 is required but {cv2.__version__} is installed')
except ImportError:
# If first not installed install second package
CHOOSE_INSTALL_REQUIRES = [('opencv-python-headless>=3',
'opencv-python>=3')]
for main, secondary in CHOOSE_INSTALL_REQUIRES:
install_requires.append(choose_requirement(main, secondary))
if int(os.getenv('MMENGINE_LITE', '0')) == 1:
install_requires = parse_requirements('requirements/runtime_lite.txt')
else:
install_requires = parse_requirements()
try:
# OpenCV installed via conda.
import cv2 # NOQA: F401
major, minor, *rest = cv2.__version__.split('.')
if int(major) < 3:
raise RuntimeError(
f'OpenCV >=3 is required but {cv2.__version__} is installed')
except ImportError:
# If first not installed install second package
CHOOSE_INSTALL_REQUIRES = [('opencv-python-headless>=3',
'opencv-python>=3')]
for main, secondary in CHOOSE_INSTALL_REQUIRES:
install_requires.append(choose_requirement(main, secondary))

setup(
name='mmengine',
Expand Down
2 changes: 2 additions & 0 deletions tests/test_logging/test_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from mmengine.logging import MMLogger, print_log
from mmengine.logging.logger import _get_device_id
from mmengine.utils import is_installed


class TestLogger:
Expand Down Expand Up @@ -237,6 +238,7 @@ def test_file_handlers(self, tmp_path):
MMLogger._instance_dict.clear()


@pytest.mark.skipif(not is_installed('torch'), reason='tests requires torch')
@patch('torch.cuda.device_count', lambda: 4)
def test_get_device_id():

Expand Down
8 changes: 3 additions & 5 deletions tests/test_registry/test_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from mmengine.config import Config, ConfigDict # type: ignore
from mmengine.registry import (DefaultScope, Registry, build_from_cfg,
build_model_from_cfg)
from mmengine.utils import ManagerMixin
from mmengine.utils import ManagerMixin, is_installed


class TestRegistry:
Expand Down Expand Up @@ -637,11 +637,9 @@ def __init__(self, name):
Visualizer.get_current_instance()


@pytest.mark.skipif(not is_installed('torch'), reason='tests requires torch')
def test_build_model_from_cfg():
try:
import torch.nn as nn
except ImportError:
pytest.skip('require torch')
import torch.nn as nn

BACKBONES = Registry('backbone', build_func=build_model_from_cfg)

Expand Down
15 changes: 9 additions & 6 deletions tests/test_utils/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

import numpy as np
import pytest
import torch

from mmengine import MMLogger
from mmengine.utils import is_installed
# yapf: disable
from mmengine.utils.misc import (apply_to, concat_list, deprecated_api_warning,
deprecated_function, get_object_from_string,
Expand Down Expand Up @@ -290,7 +290,10 @@ def deprecated_demo1():
assert expected_docstring.strip(' ') == deprecated_demo1.__doc__


@pytest.mark.skipif(not is_installed('torch'), reason='tests requires torch')
def test_apply_to():
import torch

# Test only apply `+1` to int object.
data = dict(a=1, b=2.0)
result = apply_to(data, lambda x: isinstance(x, int), lambda x: x + 1)
Expand Down Expand Up @@ -332,9 +335,9 @@ def test_apply_to():

def test_locate():
assert get_object_from_string('a.b.c') is None
model_module = import_module('mmengine.model')
assert get_object_from_string('mmengine.model') is model_module
config_module = import_module('mmengine.config')
assert get_object_from_string('mmengine.config') is config_module
assert get_object_from_string(
'mmengine.model.BaseModel') is model_module.BaseModel
assert get_object_from_string('mmengine.model.BaseModel.forward') is \
model_module.BaseModel.forward
'mmengine.config.Config') is config_module.Config
assert get_object_from_string('mmengine.config.Config.fromfile') is \
config_module.Config.fromfile