From 7546991f10eaf0e397456a1939a876040bb94d6f Mon Sep 17 00:00:00 2001 From: Maxim Vlah Date: Fri, 28 Mar 2025 18:09:40 +0100 Subject: [PATCH] fix: Copying all attributes of hybrid property When creating the hybrid-prop in the version class, we just copied the getter. Create the hybrid-prop properly --- sqlalchemy_history/builder.py | 9 ++++++++- tests/test_hybrid_property.py | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/sqlalchemy_history/builder.py b/sqlalchemy_history/builder.py index c63b243..41f8bae 100644 --- a/sqlalchemy_history/builder.py +++ b/sqlalchemy_history/builder.py @@ -234,5 +234,12 @@ def create_hybrid_properties(self, version_classes): setattr( versioned_target_class, key, - sa.ext.hybrid.hybrid_property(fget=prop.fget), + sa.ext.hybrid.hybrid_property( + fget=prop.fget, + expr=prop.expr, + fset=prop.fset, + fdel=prop.fdel, + custom_comparator=prop.custom_comparator, + update_expr=prop.update_expr, + ), ) diff --git a/tests/test_hybrid_property.py b/tests/test_hybrid_property.py index b1da835..9c9fc84 100644 --- a/tests/test_hybrid_property.py +++ b/tests/test_hybrid_property.py @@ -1,5 +1,6 @@ import datetime import sqlalchemy as sa +from sqlalchemy.orm import relationship from sqlalchemy_history.utils import version_class from tests import TestCase @@ -17,11 +18,34 @@ class Article(self.Model): description = sa.Column(sa.UnicodeText) publish = sa.Column(sa.DateTime, default=lambda: datetime.datetime.now(datetime.timezone.utc)) + author_id = sa.Column(sa.Integer, sa.ForeignKey("article_author.id"), nullable=False) + @sa.ext.hybrid.hybrid_property def time_from_publish(self): return datetime.datetime.today() - self.publish + @sa.ext.hybrid.hybrid_property + def author_name(self): + return self.author.name + + @author_name.expression + def author_name(cls): + return ( + sa.select(ArticleAuthor.name).where(ArticleAuthor.id == cls.author_id).scalar_subquery() + ) + + class ArticleAuthor(self.Model): + __tablename__ = "article_author" + __versioned__ = {} + + id = sa.Column(sa.Integer, autoincrement=True, primary_key=True) + name = sa.Column(sa.Unicode(255), nullable=False) + articles = relationship("Article", backref="author") + self.Article = Article def test_hybrid_property_mapping_for_versioned_class(self): version_class(self.Article).time_from_publish + + def test_version_class_hybrid_property_in_sql_expression(self): + sa.select(version_class(self.Article).author_name)