From 636823370ea11030998f61b8d7aa8998999e6fc3 Mon Sep 17 00:00:00 2001 From: yovel Date: Fri, 18 Oct 2024 20:08:02 +0300 Subject: [PATCH 1/2] feature: support sqlalchemy doc attribute in strawberry fields --- RELEASE.md | 4 ++++ src/strawberry_sqlalchemy_mapper/mapper.py | 12 ++++++---- tests/test_mapper.py | 28 +++++++++++++++++++++- 3 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 RELEASE.md diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000..3d63f11 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,4 @@ +Release type: patch + +Adding a new behavior were the mapper supports the SQLAlchemy `doc=XXX` +to be shown as the description of the fields generated in the GQL schema later on. \ No newline at end of file diff --git a/src/strawberry_sqlalchemy_mapper/mapper.py b/src/strawberry_sqlalchemy_mapper/mapper.py index 14c7b54..c12c52a 100644 --- a/src/strawberry_sqlalchemy_mapper/mapper.py +++ b/src/strawberry_sqlalchemy_mapper/mapper.py @@ -411,14 +411,14 @@ def _get_relationship_is_optional(self, relationship: RelationshipProperty) -> b return False def _add_annotation( - self, type_: Any, key: str, annotation: Any, generated_field_keys: List[str] + self, type_: Any, key: str, annotation: Any, generated_field_keys: List[str], field_description: str = None ) -> None: """ Add type annotation to the given type. """ type_.__annotations__[key] = annotation if not hasattr(type_, key): - setattr(type_, key, field()) + setattr(type_, key, field(description=field_description)) generated_field_keys.append(key) def _get_association_proxy_annotation( @@ -629,6 +629,7 @@ def _handle_columns( key, type_annotation, generated_field_keys, + field_description=column.doc ) def type( @@ -636,6 +637,7 @@ def type( model: Type[BaseModelType], make_interface=False, use_federation=False, + description: str=None, ) -> Callable[[Type[object]], Any]: """ Decorate a type with this to register it as a strawberry type @@ -820,13 +822,13 @@ def convert(type_: Any) -> Any: type_.__annotations__.update(old_annotations) if make_interface: - mapped_type = strawberry.interface(type_) + mapped_type = strawberry.interface(type_, description=description) self.mapped_interfaces[type_.__name__] = mapped_type elif use_federation: - mapped_type = strawberry.federation.type(type_) + mapped_type = strawberry.federation.type(type_, description=description) self.mapped_types[type_.__name__] = mapped_type else: - mapped_type = strawberry.type(type_) + mapped_type = strawberry.type(type_, description=description) self.mapped_types[type_.__name__] = mapped_type setattr( diff --git a/tests/test_mapper.py b/tests/test_mapper.py index a2c6d19..009d9c0 100644 --- a/tests/test_mapper.py +++ b/tests/test_mapper.py @@ -43,7 +43,7 @@ def employee_table(base): class Employee(base): __tablename__ = "employee" id = Column(Integer, autoincrement=True, primary_key=True) - name = Column(String, nullable=False) + name = Column(String, nullable=False, doc="The name of the employee") return Employee @@ -351,3 +351,29 @@ def departments(self) -> Department: } ''' assert str(schema) == textwrap.dedent(expected).strip() + +def test_mapper_support_description(mapper, employee_table): + """ + Test that the mapper supports the description attribute to be passed to the generated strawberry type in two forms: + 1. The type description is mapped to the strawberry.type description + 2. The SQLAlchemy column doc is mapped to strawberry field description + """ + EMPLOYEE_TYPE_DESCRIPTION = "This is a type to describe an employee" + tested_field_name, tested_field_description = ("name", "The name of the employee") + Employee = employee_table + + @mapper.type(Employee, description=EMPLOYEE_TYPE_DESCRIPTION) + class Employee: + pass + + mapper.finalize() + additional_type = list(mapper.mapped_types.values()) + assert len(additional_type) == 1 + mapped_employee_type = additional_type[0] + assert mapped_employee_type.__strawberry_definition__.description == EMPLOYEE_TYPE_DESCRIPTION + mapped_employee_type_fields = mapped_employee_type.__strawberry_definition__.fields + assert len(mapped_employee_type_fields) > 0 + relevant_employee_field = next(field for field in mapped_employee_type_fields if field.name == tested_field_name) + assert relevant_employee_field is not None + assert relevant_employee_field.description == tested_field_description + From 46cb8c08dfa3259bc59cfe29e49d23043f0367e2 Mon Sep 17 00:00:00 2001 From: yovel Date: Fri, 18 Oct 2024 20:17:40 +0300 Subject: [PATCH 2/2] Fixing sourcery-ai comments --- RELEASE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 3d63f11..7db7320 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,4 +1,4 @@ Release type: patch -Adding a new behavior were the mapper supports the SQLAlchemy `doc=XXX` -to be shown as the description of the fields generated in the GQL schema later on. \ No newline at end of file +Adding a new behavior where the mapper supports the SQLAlchemy `doc=XXX` +to be shown as the description of the fields generated in the GQL schema later on. \ No newline at end of file