diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index b837a633f..ec232dcfc 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -195,31 +195,3 @@ jobs: # Make sure wheels are not included in the Rust cache - name: Delete wheels run: rm -rf target/wheels - pydantic1x: - timeout-minutes: 30 - runs-on: "ubuntu-24.04" - defaults: - run: - shell: bash - working-directory: python - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - lfs: true - - name: Install dependencies - run: | - sudo apt update - sudo apt install -y protobuf-compiler - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.10" - - name: Install lancedb - run: | - pip install "pydantic<2" - pip install pyarrow==16 - pip install --extra-index-url https://pypi.fury.io/lance-format/ --extra-index-url https://pypi.fury.io/lancedb/ -e .[tests] - pip install tantivy - - name: Run tests - run: pytest -m "not slow and not s3_test" -x -v --durations=30 python/tests diff --git a/python/pyproject.toml b/python/pyproject.toml index b6fe79b9c..f5517fe2b 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -8,7 +8,7 @@ dependencies = [ "overrides>=0.7; python_version<'3.12'", "packaging", "pyarrow>=16", - "pydantic>=1.10", + "pydantic>=2", "tqdm>=4.27.0", "lance-namespace>=0.3.2" ] diff --git a/python/python/lancedb/pydantic.py b/python/python/lancedb/pydantic.py index 653ea3333..9496aebdd 100644 --- a/python/python/lancedb/pydantic.py +++ b/python/python/lancedb/pydantic.py @@ -141,14 +141,6 @@ def Vector( raise TypeError("A list of numbers or numpy.ndarray is needed") return cls(v) - if PYDANTIC_VERSION.major < 2: - - @classmethod - def __modify_schema__(cls, field_schema: Dict[str, Any]): - field_schema["items"] = {"type": "number"} - field_schema["maxItems"] = dim - field_schema["minItems"] = dim - return FixedSizeList @@ -226,26 +218,14 @@ def MultiVector( def __get_validators__(cls) -> Generator[Callable, None, None]: yield cls.validate - # For pydantic v1 @classmethod - def validate(cls, v): - if not isinstance(v, (list, range)): - raise TypeError("A list of vectors is needed") - for vec in v: - if not isinstance(vec, (list, range, np.ndarray)) or len(vec) != dim: - raise TypeError(f"Each vector must be a list of {dim} numbers") - return cls(v) - - if PYDANTIC_VERSION.major < 2: - - @classmethod - def __modify_schema__(cls, field_schema: Dict[str, Any]): - field_schema["items"] = { - "type": "array", - "items": {"type": "number"}, - "minItems": dim, - "maxItems": dim, - } + def __modify_schema__(cls, field_schema: Dict[str, Any]): + field_schema["items"] = { + "type": "array", + "items": {"type": "number"}, + "minItems": dim, + "maxItems": dim, + } return MultiVectorList @@ -281,20 +261,10 @@ def _py_type_to_arrow_type(py_type: Type[Any], field: FieldInfo) -> pa.DataType: ) -if PYDANTIC_VERSION.major < 2: - - def _pydantic_model_to_fields(model: pydantic.BaseModel) -> List[pa.Field]: - return [ - _pydantic_to_field(name, field) for name, field in model.__fields__.items() - ] - -else: - - def _pydantic_model_to_fields(model: pydantic.BaseModel) -> List[pa.Field]: - return [ - _pydantic_to_field(name, field) - for name, field in model.model_fields.items() - ] +def _pydantic_model_to_fields(model: pydantic.BaseModel) -> List[pa.Field]: + return [ + _pydantic_to_field(name, field) for name, field in model.model_fields.items() + ] def _pydantic_type_to_arrow_type(tp: Any, field: FieldInfo) -> pa.DataType: @@ -334,7 +304,7 @@ def _unwrap_optional_annotation(annotation: Any) -> Any | None: non_none = [arg for arg in args if arg is not type(None)] if len(non_none) == 1 and len(non_none) != len(args): return non_none[0] - elif sys.version_info >= (3, 10) and isinstance(annotation, types.UnionType): + elif isinstance(annotation, types.UnionType): args = annotation.__args__ non_none = [arg for arg in args if arg is not type(None)] if len(non_none) == 1 and len(non_none) != len(args): @@ -367,7 +337,7 @@ def is_nullable(field: FieldInfo) -> bool: if origin == Union: if any(typ is type(None) for typ in args): return True - elif sys.version_info >= (3, 10) and isinstance(field.annotation, types.UnionType): + elif isinstance(field.annotation, types.UnionType): args = field.annotation.__args__ for typ in args: if typ is type(None): @@ -474,8 +444,6 @@ class LanceModel(pydantic.BaseModel): @classmethod def safe_get_fields(cls): - if PYDANTIC_VERSION.major < 2: - return cls.__fields__ return cls.model_fields @classmethod @@ -518,18 +486,8 @@ def get_extras(field_info: FieldInfo, key: str) -> Any: return (field_info.field_info.extra or {}).get("json_schema_extra", {}).get(key) -if PYDANTIC_VERSION.major < 2: - - def model_to_dict(model: pydantic.BaseModel) -> Dict[str, Any]: - """ - Convert a Pydantic model to a dictionary. - """ - return model.dict() - -else: - - def model_to_dict(model: pydantic.BaseModel) -> Dict[str, Any]: - """ - Convert a Pydantic model to a dictionary. - """ - return model.model_dump() +def model_to_dict(model: pydantic.BaseModel) -> Dict[str, Any]: + """ + Convert a Pydantic model to a dictionary. + """ + return model.model_dump()