From 92b5b1811dd098ec2d43bca692db18e38af9557d Mon Sep 17 00:00:00 2001 From: Christoph Deil Date: Wed, 26 Aug 2026 13:47:05 +0200 Subject: [PATCH] fix: keep Version importable in slim installs --- roboflow/core/version.py | 40 +++++++++++++++++++++++++++++++-------- tests/test_slim_compat.py | 5 +++++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/roboflow/core/version.py b/roboflow/core/version.py index dee2cce2..8a2f6966 100644 --- a/roboflow/core/version.py +++ b/roboflow/core/version.py @@ -27,17 +27,9 @@ UNIVERSE_URL, ) from roboflow.core.dataset import Dataset -from roboflow.models.classification import ClassificationModel -from roboflow.models.instance_segmentation import InstanceSegmentationModel -from roboflow.models.keypoint_detection import KeypointDetectionModel -from roboflow.models.object_detection import ObjectDetectionModel -from roboflow.models.semantic_segmentation import SemanticSegmentationModel -from roboflow.models.vlm import VLMModel from roboflow.util.annotations import amend_data_yaml from roboflow.util.general import extract_zip, write_line -from roboflow.util.model_processor import package_custom_weights_interactive, validate_model_type_for_project from roboflow.util.train_recipe import fold_epochs_into_recipe -from roboflow.util.versions import get_model_format, get_wrong_dependencies_versions if TYPE_CHECKING: import numpy as np @@ -103,6 +95,8 @@ def __init__( if not has_model: self.model = None elif self.type == TYPE_OBJECT_DETECTION: + from roboflow.models.object_detection import ObjectDetectionModel + self.model = ObjectDetectionModel( self.__api_key, self.id, @@ -113,6 +107,8 @@ def __init__( preprocessing=self.preprocessing, ) elif self.type == TYPE_CLASSICATION: + from roboflow.models.classification import ClassificationModel + self.model = ClassificationModel( self.__api_key, self.id, @@ -123,6 +119,8 @@ def __init__( preprocessing=self.preprocessing, ) elif self.type == TYPE_INSTANCE_SEGMENTATION: + from roboflow.models.instance_segmentation import InstanceSegmentationModel + self.model = InstanceSegmentationModel( self.__api_key, self.id, @@ -131,10 +129,16 @@ def __init__( local=local, ) elif self.type == TYPE_SEMANTIC_SEGMENTATION: + from roboflow.models.semantic_segmentation import SemanticSegmentationModel + self.model = SemanticSegmentationModel(self.__api_key, self.id) elif self.type == TYPE_KEYPOINT_DETECTION: + from roboflow.models.keypoint_detection import KeypointDetectionModel + self.model = KeypointDetectionModel(self.__api_key, self.id, version=version_without_workspace) elif self.type == TYPE_TEXT_IMAGE_PAIRS: + from roboflow.models.vlm import VLMModel + self.model = VLMModel( self.__api_key, self.id, @@ -300,6 +304,8 @@ def create_training(self, speed=None, model_type=None, checkpoint=None, epochs=N self.__wait_if_generating() if model_type: + from roboflow.util.versions import get_model_format + train_model_format = get_model_format(model_type) if train_model_format not in self.exports: self.export(train_model_format) @@ -486,6 +492,8 @@ def train( self.__wait_if_generating() + from roboflow.util.versions import get_model_format + train_model_format = get_model_format(model_type) if train_model_format not in self.exports: self.export(train_model_format) @@ -609,6 +617,8 @@ def live_plot(epochs, mAP, loss, title=""): if not getattr(self, "_model", None): if self.type == TYPE_OBJECT_DETECTION: + from roboflow.models.object_detection import ObjectDetectionModel + self.model = ObjectDetectionModel( self.__api_key, self.id, @@ -618,6 +628,8 @@ def live_plot(epochs, mAP, loss, title=""): preprocessing=self.preprocessing, ) elif self.type == TYPE_CLASSICATION: + from roboflow.models.classification import ClassificationModel + self.model = ClassificationModel( self.__api_key, self.id, @@ -627,6 +639,8 @@ def live_plot(epochs, mAP, loss, title=""): preprocessing=self.preprocessing, ) elif self.type == TYPE_INSTANCE_SEGMENTATION: + from roboflow.models.instance_segmentation import InstanceSegmentationModel + self.model = InstanceSegmentationModel( self.__api_key, self.id, @@ -634,8 +648,12 @@ def live_plot(epochs, mAP, loss, title=""): preprocessing=self.preprocessing, ) elif self.type == TYPE_SEMANTIC_SEGMENTATION: + from roboflow.models.semantic_segmentation import SemanticSegmentationModel + self.model = SemanticSegmentationModel(self.__api_key, self.id) elif self.type == TYPE_KEYPOINT_DETECTION: + from roboflow.models.keypoint_detection import KeypointDetectionModel + self.model = KeypointDetectionModel(self.__api_key, self.id, version=self.version) else: raise ValueError(f"Unsupported model type: {self.type}") @@ -653,12 +671,16 @@ def deploy(self, model_type: str, model_path: str, filename: str = "weights/best model_path (str): File path to the model weights to be uploaded. filename (str, optional): The name of the weights file. Defaults to "weights/best.pt". """ + from roboflow.util.model_processor import package_custom_weights_interactive + bundle = package_custom_weights_interactive(model_type, model_path, filename, build_dir=model_path) self._validate_against_project_type(bundle.model_type) self._upload_zip(bundle.model_type, model_path, bundle.archive_path.name) def _validate_against_project_type(self, model_type: str) -> None: + from roboflow.util.model_processor import validate_model_type_for_project + validate_model_type_for_project(model_type, self.type, self.project) def _upload_zip(self, model_type: str, model_path: str, model_file_name: str): @@ -818,6 +840,8 @@ def data_yaml_callback(content: dict) -> dict: content["train"] = location + content["train"].lstrip("..") content["val"] = location + content["val"].lstrip("..") try: + from roboflow.util.versions import get_wrong_dependencies_versions + # get_wrong_dependencies_versions raises exception if ultralytics is not installed at all # noqa: E501 // docs if format == "yolov8" and not get_wrong_dependencies_versions( dependencies_versions=[("ultralytics", "==", "8.0.196")] diff --git a/tests/test_slim_compat.py b/tests/test_slim_compat.py index 972eeacf..33f7fab6 100644 --- a/tests/test_slim_compat.py +++ b/tests/test_slim_compat.py @@ -38,6 +38,11 @@ def test_import_rfapi(self): self.assertTrue(issubclass(RoboflowError, Exception)) + def test_import_version(self): + from roboflow.core.version import Version + + self.assertTrue(callable(Version)) + def test_import_cli(self): from roboflow.cli import app