From 6ed09ac4fcb6a0f3d111e26ecebf6766143426ca Mon Sep 17 00:00:00 2001 From: Robert Segal Date: Tue, 28 Apr 2026 12:47:34 -0600 Subject: [PATCH] refactor: MPT-20684 introduce shared base models for file-like resources AI Generated. Extract FileResourceModel as a shared base for fields common to attachments, documents, media, and term variants (name, type, size, description, content_type). Add AttachmentModel, DocumentModel, MediaModel, and TermVariantModel as specialized subclasses that layer on the fields unique to each resource family. Migrate the corresponding resource classes across billing, catalog, commerce, helpdesk, integration, and program domains to inherit from the new base models, removing duplicated field declarations while keeping resource-specific fields (parent references, audit, language, revision, etc.) on the subclasses. Update unit tests to match the new convention where missing optional fields default to None instead of raising AttributeError, add inherited-field fixtures in tests/unit/conftest.py, and add dedicated test files for each new base model under tests/unit/models/. --- mpt_api_client/models/__init__.py | 19 +++++- mpt_api_client/models/attachment_model.py | 5 ++ mpt_api_client/models/document_model.py | 15 +++++ mpt_api_client/models/file_resource_model.py | 19 ++++++ mpt_api_client/models/media_model.py | 17 ++++++ mpt_api_client/models/term_variant_model.py | 19 ++++++ .../billing/credit_memo_attachments.py | 6 +- .../billing/custom_ledger_attachments.py | 6 +- .../resources/billing/invoice_attachments.py | 6 +- .../resources/billing/journal_attachments.py | 6 +- .../resources/billing/ledger_attachments.py | 6 +- .../billing/statement_attachments.py | 6 +- .../catalog/pricing_policy_attachments.py | 20 ++----- .../catalog/product_term_variants.py | 28 ++------- .../resources/catalog/products_documents.py | 26 ++------ .../resources/catalog/products_media.py | 26 ++------ .../resources/helpdesk/chat_attachments.py | 32 +++++----- .../integration/extension_documents.py | 28 ++------- .../resources/integration/extension_media.py | 28 ++------- .../integration/extension_term_variants.py | 30 ++-------- .../program/enrollments_attachments.py | 14 +---- .../resources/program/programs_documents.py | 24 ++------ .../resources/program/programs_media.py | 26 ++------ .../program/programs_terms_variant.py | 28 ++------- .../chats/attachment/test_async_attachment.py | 10 ++-- .../chats/attachment/test_sync_attachment.py | 10 ++-- tests/unit/conftest.py | 60 +++++++++++++++++++ tests/unit/models/test_attachment_model.py | 42 +++++++++++++ tests/unit/models/test_document_model.py | 47 +++++++++++++++ tests/unit/models/test_file_resource_model.py | 42 +++++++++++++ tests/unit/models/test_media_model.py | 49 +++++++++++++++ tests/unit/models/test_term_variant_model.py | 51 ++++++++++++++++ .../billing/test_credit_memo_attachments.py | 18 ++++++ .../billing/test_custom_ledger_attachments.py | 18 ++++++ .../billing/test_invoice_attachments.py | 18 ++++++ .../billing/test_journal_attachments.py | 18 ++++++ .../billing/test_ledger_attachments.py | 18 ++++++ .../billing/test_statement_attachments.py | 18 ++++++ .../test_pricing_policy_attachments.py | 13 ++-- .../catalog/test_product_term_variants.py | 23 +++++-- .../catalog/test_products_documents.py | 22 +++++-- .../resources/catalog/test_products_media.py | 22 +++++-- .../integration/test_extension_documents.py | 21 ++++++- .../integration/test_extension_media.py | 6 ++ .../test_extension_term_variants.py | 8 +++ .../program/test_programs_documents.py | 21 +++++-- .../resources/program/test_programs_media.py | 25 +++++--- .../program/test_programs_terms_variant.py | 28 +++++---- 48 files changed, 729 insertions(+), 319 deletions(-) create mode 100644 mpt_api_client/models/attachment_model.py create mode 100644 mpt_api_client/models/document_model.py create mode 100644 mpt_api_client/models/file_resource_model.py create mode 100644 mpt_api_client/models/media_model.py create mode 100644 mpt_api_client/models/term_variant_model.py create mode 100644 tests/unit/models/test_attachment_model.py create mode 100644 tests/unit/models/test_document_model.py create mode 100644 tests/unit/models/test_file_resource_model.py create mode 100644 tests/unit/models/test_media_model.py create mode 100644 tests/unit/models/test_term_variant_model.py diff --git a/mpt_api_client/models/__init__.py b/mpt_api_client/models/__init__.py index 8c29ac9c..0c6be133 100644 --- a/mpt_api_client/models/__init__.py +++ b/mpt_api_client/models/__init__.py @@ -1,6 +1,23 @@ +from mpt_api_client.models.attachment_model import AttachmentModel +from mpt_api_client.models.document_model import DocumentModel from mpt_api_client.models.file_model import FileModel +from mpt_api_client.models.file_resource_model import FileResourceModel +from mpt_api_client.models.media_model import MediaModel from mpt_api_client.models.meta import Meta, Pagination from mpt_api_client.models.model import Model, ResourceData from mpt_api_client.models.model_collection import ModelCollection +from mpt_api_client.models.term_variant_model import TermVariantModel -__all__ = ["FileModel", "Meta", "Model", "ModelCollection", "Pagination", "ResourceData"] # noqa: WPS410 +__all__ = [ # noqa: WPS410 + "AttachmentModel", + "DocumentModel", + "FileModel", + "FileResourceModel", + "MediaModel", + "Meta", + "Model", + "ModelCollection", + "Pagination", + "ResourceData", + "TermVariantModel", +] diff --git a/mpt_api_client/models/attachment_model.py b/mpt_api_client/models/attachment_model.py new file mode 100644 index 00000000..30727007 --- /dev/null +++ b/mpt_api_client/models/attachment_model.py @@ -0,0 +1,5 @@ +from mpt_api_client.models.file_resource_model import FileResourceModel + + +class AttachmentModel(FileResourceModel): + """Base model for attachment resources. Inherits fields from FileResourceModel.""" diff --git a/mpt_api_client/models/document_model.py b/mpt_api_client/models/document_model.py new file mode 100644 index 00000000..86b801f5 --- /dev/null +++ b/mpt_api_client/models/document_model.py @@ -0,0 +1,15 @@ +from mpt_api_client.models.file_resource_model import FileResourceModel + + +class DocumentModel(FileResourceModel): + """Base model for document resources. + + Attributes: + status: Document status. + filename: Original file name. + url: URL to access the document. + """ + + status: str | None = None + filename: str | None = None + url: str | None = None diff --git a/mpt_api_client/models/file_resource_model.py b/mpt_api_client/models/file_resource_model.py new file mode 100644 index 00000000..4b798451 --- /dev/null +++ b/mpt_api_client/models/file_resource_model.py @@ -0,0 +1,19 @@ +from mpt_api_client.models.model import Model + + +class FileResourceModel(Model): + """Base model for file-like resources (attachments, documents, media, term variants). + + Attributes: + name: Resource name. + type: Resource type. + size: File size in bytes. + description: Resource description. + content_type: MIME content type. + """ + + name: str | None = None + type: str | None = None + size: int | None = None + description: str | None = None + content_type: str | None = None diff --git a/mpt_api_client/models/media_model.py b/mpt_api_client/models/media_model.py new file mode 100644 index 00000000..5e2405d5 --- /dev/null +++ b/mpt_api_client/models/media_model.py @@ -0,0 +1,17 @@ +from mpt_api_client.models.file_resource_model import FileResourceModel + + +class MediaModel(FileResourceModel): + """Base model for media resources. + + Attributes: + status: Media status. + filename: Original file name. + display_order: Display order of the media item. + url: URL to access the media file. + """ + + status: str | None = None + filename: str | None = None + display_order: int | None = None + url: str | None = None diff --git a/mpt_api_client/models/term_variant_model.py b/mpt_api_client/models/term_variant_model.py new file mode 100644 index 00000000..d3b598c0 --- /dev/null +++ b/mpt_api_client/models/term_variant_model.py @@ -0,0 +1,19 @@ +from mpt_api_client.models.file_resource_model import FileResourceModel + + +class TermVariantModel(FileResourceModel): + """Base model for term variant resources. + + Attributes: + asset_url: URL to the variant asset. + language_code: Language code for this variant. + status: Variant status. + filename: Original file name. + file_id: Identifier of the uploaded file. + """ + + asset_url: str | None = None + language_code: str | None = None + status: str | None = None + filename: str | None = None + file_id: str | None = None diff --git a/mpt_api_client/resources/billing/credit_memo_attachments.py b/mpt_api_client/resources/billing/credit_memo_attachments.py index ed194f90..cfd5bd7e 100644 --- a/mpt_api_client/resources/billing/credit_memo_attachments.py +++ b/mpt_api_client/resources/billing/credit_memo_attachments.py @@ -3,12 +3,12 @@ AsyncCollectionMixin, CollectionMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import AttachmentModel from mpt_api_client.resources.billing.mixins import AsyncAttachmentMixin, AttachmentMixin -class CreditMemoAttachment(Model): - """Credit Memo Attachment resource.""" +class CreditMemoAttachment(AttachmentModel): + """Credit Memo Attachment resource. Inherits fields from AttachmentModel.""" class CreditMemoAttachmentsServiceConfig: diff --git a/mpt_api_client/resources/billing/custom_ledger_attachments.py b/mpt_api_client/resources/billing/custom_ledger_attachments.py index 59d42389..e9549f42 100644 --- a/mpt_api_client/resources/billing/custom_ledger_attachments.py +++ b/mpt_api_client/resources/billing/custom_ledger_attachments.py @@ -3,12 +3,12 @@ AsyncCollectionMixin, CollectionMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import AttachmentModel from mpt_api_client.resources.billing.mixins import AsyncAttachmentMixin, AttachmentMixin -class CustomLedgerAttachment(Model): - """Custom Ledger Attachment resource.""" +class CustomLedgerAttachment(AttachmentModel): + """Custom Ledger Attachment resource. Inherits fields from AttachmentModel.""" class CustomLedgerAttachmentsServiceConfig: diff --git a/mpt_api_client/resources/billing/invoice_attachments.py b/mpt_api_client/resources/billing/invoice_attachments.py index 49650037..bb19dc6f 100644 --- a/mpt_api_client/resources/billing/invoice_attachments.py +++ b/mpt_api_client/resources/billing/invoice_attachments.py @@ -3,12 +3,12 @@ AsyncCollectionMixin, CollectionMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import AttachmentModel from mpt_api_client.resources.billing.mixins import AsyncAttachmentMixin, AttachmentMixin -class InvoiceAttachment(Model): - """Invoice Attachment resource.""" +class InvoiceAttachment(AttachmentModel): + """Invoice Attachment resource. Inherits fields from AttachmentModel.""" class InvoiceAttachmentsServiceConfig: diff --git a/mpt_api_client/resources/billing/journal_attachments.py b/mpt_api_client/resources/billing/journal_attachments.py index e1ebafd6..8af263df 100644 --- a/mpt_api_client/resources/billing/journal_attachments.py +++ b/mpt_api_client/resources/billing/journal_attachments.py @@ -3,12 +3,12 @@ AsyncCollectionMixin, CollectionMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import AttachmentModel from mpt_api_client.resources.billing.mixins import AsyncAttachmentMixin, AttachmentMixin -class JournalAttachment(Model): - """Journal Attachment resource.""" +class JournalAttachment(AttachmentModel): + """Journal Attachment resource. Inherits fields from AttachmentModel.""" class JournalAttachmentsServiceConfig: diff --git a/mpt_api_client/resources/billing/ledger_attachments.py b/mpt_api_client/resources/billing/ledger_attachments.py index e88144c5..46eba03b 100644 --- a/mpt_api_client/resources/billing/ledger_attachments.py +++ b/mpt_api_client/resources/billing/ledger_attachments.py @@ -3,12 +3,12 @@ AsyncCollectionMixin, CollectionMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import AttachmentModel from mpt_api_client.resources.billing.mixins import AsyncAttachmentMixin, AttachmentMixin -class LedgerAttachment(Model): - """Ledger Attachment resource.""" +class LedgerAttachment(AttachmentModel): + """Ledger Attachment resource. Inherits fields from AttachmentModel.""" class LedgerAttachmentsServiceConfig: diff --git a/mpt_api_client/resources/billing/statement_attachments.py b/mpt_api_client/resources/billing/statement_attachments.py index c3ab9dae..f2c13fb7 100644 --- a/mpt_api_client/resources/billing/statement_attachments.py +++ b/mpt_api_client/resources/billing/statement_attachments.py @@ -3,12 +3,12 @@ AsyncCollectionMixin, CollectionMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import AttachmentModel from mpt_api_client.resources.billing.mixins import AsyncAttachmentMixin, AttachmentMixin -class StatementAttachment(Model): - """Statement Attachment resource.""" +class StatementAttachment(AttachmentModel): + """Statement Attachment resource. Inherits fields from AttachmentModel.""" class StatementAttachmentsServiceConfig: diff --git a/mpt_api_client/resources/catalog/pricing_policy_attachments.py b/mpt_api_client/resources/catalog/pricing_policy_attachments.py index c414b3c7..18d0d2ae 100644 --- a/mpt_api_client/resources/catalog/pricing_policy_attachments.py +++ b/mpt_api_client/resources/catalog/pricing_policy_attachments.py @@ -9,32 +9,22 @@ DownloadFileMixin, ModifiableResourceMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import AttachmentModel from mpt_api_client.models.model import BaseModel -class PricingPolicyAttachment(Model): +class PricingPolicyAttachment(AttachmentModel): """Pricing Policy Attachment resource. Attributes: - name: Attachment name. - type: Attachment type. - size: File size in bytes. - description: Attachment description. file_name: Original file name. - content_type: MIME content type of the attachment. status: Attachment status. audit: Audit information (created, updated events). """ - name: str | None - type: str | None - size: int | None - description: str | None - file_name: str | None - content_type: str | None - status: str | None - audit: BaseModel | None + file_name: str | None = None + status: str | None = None + audit: BaseModel | None = None class PricingPolicyAttachmentsServiceConfig: diff --git a/mpt_api_client/resources/catalog/product_term_variants.py b/mpt_api_client/resources/catalog/product_term_variants.py index caa4e0e0..831bb489 100644 --- a/mpt_api_client/resources/catalog/product_term_variants.py +++ b/mpt_api_client/resources/catalog/product_term_variants.py @@ -9,7 +9,7 @@ DownloadFileMixin, ModifiableResourceMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import TermVariantModel from mpt_api_client.models.model import BaseModel from mpt_api_client.resources.mixins import ( AsyncPublishableMixin, @@ -19,36 +19,16 @@ ) -class TermVariant(Model): +class TermVariant(TermVariantModel): """Term variant resource. Attributes: - type: Variant type. - asset_url: URL to the term variant asset. - language_code: Language code for this variant. - name: Variant name. - description: Variant description. - status: Variant status. - filename: Original file name. - size: File size in bytes. - content_type: MIME content type of the file. terms_and_conditions: Reference to the parent terms and conditions. - file_id: Identifier of the uploaded file. audit: Audit information (created, updated events). """ - type: str | None - asset_url: str | None - language_code: str | None - name: str | None - description: str | None - status: str | None - filename: str | None - size: int | None - content_type: str | None - terms_and_conditions: BaseModel | None - file_id: str | None - audit: BaseModel | None + terms_and_conditions: BaseModel | None = None + audit: BaseModel | None = None class TermVariantServiceConfig: diff --git a/mpt_api_client/resources/catalog/products_documents.py b/mpt_api_client/resources/catalog/products_documents.py index adf2b7ea..54645268 100644 --- a/mpt_api_client/resources/catalog/products_documents.py +++ b/mpt_api_client/resources/catalog/products_documents.py @@ -5,7 +5,7 @@ CollectionMixin, ModifiableResourceMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import DocumentModel from mpt_api_client.models.model import BaseModel from mpt_api_client.resources.mixins import ( AsyncDocumentMixin, @@ -15,34 +15,18 @@ ) -class Document(Model): +class Document(DocumentModel): """Document resource. Attributes: - name: Document name. - type: Document type. - description: Document description. - status: Document status. - filename: Original file name. - size: File size in bytes. - content_type: MIME content type of the document. - url: URL to access the document. language: Language code of the document. product: Reference to the product. audit: Audit information (created, updated events). """ - name: str | None - type: str | None - description: str | None - status: str | None - filename: str | None - size: int | None - content_type: str | None - url: str | None - language: str | None - product: BaseModel | None - audit: BaseModel | None + language: str | None = None + product: BaseModel | None = None + audit: BaseModel | None = None class DocumentServiceConfig: diff --git a/mpt_api_client/resources/catalog/products_media.py b/mpt_api_client/resources/catalog/products_media.py index 39993098..f57234c9 100644 --- a/mpt_api_client/resources/catalog/products_media.py +++ b/mpt_api_client/resources/catalog/products_media.py @@ -5,7 +5,7 @@ CollectionMixin, ModifiableResourceMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import MediaModel from mpt_api_client.models.model import BaseModel from mpt_api_client.resources.mixins import ( AsyncMediaMixin, @@ -15,34 +15,16 @@ ) -class Media(Model): +class Media(MediaModel): """Media resource. Attributes: - name: Media name. - type: Media type. - description: Media description. - status: Media status. - filename: Original file name. - size: File size in bytes. - content_type: MIME content type of the media file. - display_order: Display order of the media item. - url: URL to access the media file. product: Reference to the product. audit: Audit information (created, updated events). """ - name: str | None - type: str | None - description: str | None - status: str | None - filename: str | None - size: int | None - content_type: str | None - display_order: int | None - url: str | None - product: BaseModel | None - audit: BaseModel | None + product: BaseModel | None = None + audit: BaseModel | None = None class MediaServiceConfig: diff --git a/mpt_api_client/resources/helpdesk/chat_attachments.py b/mpt_api_client/resources/helpdesk/chat_attachments.py index f5e6c78f..4493c84f 100644 --- a/mpt_api_client/resources/helpdesk/chat_attachments.py +++ b/mpt_api_client/resources/helpdesk/chat_attachments.py @@ -1,42 +1,38 @@ from mpt_api_client.http import AsyncService, Service, mixins -from mpt_api_client.models import Model - - -class ChatAttachment(Model): - """Helpdesk Chat Attachment resource.""" +from mpt_api_client.models import AttachmentModel class ChatAttachmentsServiceConfig: """Helpdesk Chat Attachments service configuration.""" _endpoint = "/public/v1/helpdesk/chats/{chat_id}/attachments" - _model_class = ChatAttachment + _model_class = AttachmentModel _collection_key = "data" _upload_file_key = "file" _upload_data_key = "attachment" class ChatAttachmentsService( - mixins.CreateFileMixin[ChatAttachment], - mixins.UpdateMixin[ChatAttachment], - mixins.DownloadFileMixin[ChatAttachment], + mixins.CreateFileMixin[AttachmentModel], + mixins.UpdateMixin[AttachmentModel], + mixins.DownloadFileMixin[AttachmentModel], mixins.DeleteMixin, - mixins.GetMixin[ChatAttachment], - mixins.CollectionMixin[ChatAttachment], - Service[ChatAttachment], + mixins.GetMixin[AttachmentModel], + mixins.CollectionMixin[AttachmentModel], + Service[AttachmentModel], ChatAttachmentsServiceConfig, ): """Helpdesk Chat Attachments service.""" class AsyncChatAttachmentsService( - mixins.AsyncCreateFileMixin[ChatAttachment], - mixins.AsyncUpdateMixin[ChatAttachment], - mixins.AsyncDownloadFileMixin[ChatAttachment], + mixins.AsyncCreateFileMixin[AttachmentModel], + mixins.AsyncUpdateMixin[AttachmentModel], + mixins.AsyncDownloadFileMixin[AttachmentModel], mixins.AsyncDeleteMixin, - mixins.AsyncGetMixin[ChatAttachment], - mixins.AsyncCollectionMixin[ChatAttachment], - AsyncService[ChatAttachment], + mixins.AsyncGetMixin[AttachmentModel], + mixins.AsyncCollectionMixin[AttachmentModel], + AsyncService[AttachmentModel], ChatAttachmentsServiceConfig, ): """Async Helpdesk Chat Attachments service.""" diff --git a/mpt_api_client/resources/integration/extension_documents.py b/mpt_api_client/resources/integration/extension_documents.py index 96931a67..dc95d884 100644 --- a/mpt_api_client/resources/integration/extension_documents.py +++ b/mpt_api_client/resources/integration/extension_documents.py @@ -9,41 +9,25 @@ DownloadFileMixin, ModifiableResourceMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import DocumentModel from mpt_api_client.models.model import BaseModel from mpt_api_client.resources.mixins import AsyncPublishableMixin, PublishableMixin -class ExtensionDocument(Model): +class ExtensionDocument(DocumentModel): """Extension Document resource. Attributes: - name: Document name. revision: Revision number. - type: Document type (Online or File). - description: Document description. - status: Document status (Draft, Published, Unpublished, Deleted). - filename: Original file name. - size: File size in bytes. - content_type: MIME content type. - url: URL to access the document. language: Language code. extension: Reference to the extension. audit: Audit information (created, updated, published, unpublished). """ - name: str | None - revision: int | None - type: str | None - description: str | None - status: str | None - filename: str | None - size: int | None - content_type: str | None - url: str | None - language: str | None - extension: BaseModel | None - audit: BaseModel | None + revision: int | None = None + language: str | None = None + extension: BaseModel | None = None + audit: BaseModel | None = None class ExtensionDocumentsServiceConfig: diff --git a/mpt_api_client/resources/integration/extension_media.py b/mpt_api_client/resources/integration/extension_media.py index 5f304bfb..1ec2812e 100644 --- a/mpt_api_client/resources/integration/extension_media.py +++ b/mpt_api_client/resources/integration/extension_media.py @@ -11,42 +11,24 @@ DownloadFileMixin, ModifiableResourceMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import MediaModel from mpt_api_client.models.model import BaseModel from mpt_api_client.resources.integration.mixins import AsyncMediaMixin, MediaMixin from mpt_api_client.resources.mixins import AsyncPublishableMixin, PublishableMixin -class ExtensionMedia(Model): +class ExtensionMedia(MediaModel): """Extension Media resource. Attributes: - name: Media name. revision: Revision number. - type: Media type (Video or Image). - description: Media description. - status: Media status (Draft, Published, Unpublished, Deleted). - filename: Original file name. - size: File size in bytes. - content_type: MIME content type. - display_order: Display order. - url: URL to access the media. extension: Reference to the extension. audit: Audit information (created, updated, published, unpublished). """ - name: str | None - revision: int | None - type: str | None - description: str | None - status: str | None - filename: str | None - size: int | None - content_type: str | None - display_order: int | None - url: str | None - extension: BaseModel | None - audit: BaseModel | None + revision: int | None = None + extension: BaseModel | None = None + audit: BaseModel | None = None class ExtensionMediaServiceConfig: diff --git a/mpt_api_client/resources/integration/extension_term_variants.py b/mpt_api_client/resources/integration/extension_term_variants.py index 3e2be48f..96a1b5f3 100644 --- a/mpt_api_client/resources/integration/extension_term_variants.py +++ b/mpt_api_client/resources/integration/extension_term_variants.py @@ -7,7 +7,7 @@ CreateFileMixin, ModifiableResourceMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import TermVariantModel from mpt_api_client.models.model import BaseModel from mpt_api_client.resources.mixins import ( AsyncPublishableMixin, @@ -15,38 +15,18 @@ ) -class ExtensionTermVariant(Model): +class ExtensionTermVariant(TermVariantModel): """Extension Term Variant resource. Attributes: - name: Variant name. revision: Revision number. - type: Variant type (Online or File). - asset_url: URL to the variant asset for Online type. - language_code: Language code for this variant. - description: Variant description. - status: Variant status (Draft, Published, Unpublished, Deleted). - filename: Original file name for File type. - size: File size in bytes for File type. - content_type: MIME content type of the file. term: Reference to the parent term. - file_id: Identifier of the uploaded file. audit: Audit information (created, updated, published, unpublished). """ - name: str | None - revision: int | None - type: str | None - asset_url: str | None - language_code: str | None - description: str | None - status: str | None - filename: str | None - size: int | None - content_type: str | None - term: BaseModel | None - file_id: str | None - audit: BaseModel | None + revision: int | None = None + term: BaseModel | None = None + audit: BaseModel | None = None class ExtensionTermVariantsServiceConfig: diff --git a/mpt_api_client/resources/program/enrollments_attachments.py b/mpt_api_client/resources/program/enrollments_attachments.py index e285b83a..6ade868b 100644 --- a/mpt_api_client/resources/program/enrollments_attachments.py +++ b/mpt_api_client/resources/program/enrollments_attachments.py @@ -3,31 +3,21 @@ AsyncCollectionMixin, CollectionMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import AttachmentModel from mpt_api_client.models.model import BaseModel from mpt_api_client.resources.mixins.attachment_mixin import AsyncAttachmentMixin, AttachmentMixin -class EnrollmentAttachment(Model): +class EnrollmentAttachment(AttachmentModel): """Enrollment Attachment resource. Attributes: - name: The name of the attachment. - description: The description of the attachment. - type: The type of the attachment. filename: The filename of the attachment. - size: The size of the attachment in bytes. - content_type: The content type of the attachment. enrollment: The enrollment associated with the attachment. audit: The audit information for the attachment. """ - name: str | None = None - description: str | None = None - type: str | None = None filename: str | None = None - size: int | None = None - content_type: str | None = None enrollment: BaseModel | None = None audit: BaseModel | None = None diff --git a/mpt_api_client/resources/program/programs_documents.py b/mpt_api_client/resources/program/programs_documents.py index a434a1d5..488272cb 100644 --- a/mpt_api_client/resources/program/programs_documents.py +++ b/mpt_api_client/resources/program/programs_documents.py @@ -5,37 +5,21 @@ CollectionMixin, ModifiableResourceMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import DocumentModel from mpt_api_client.models.model import BaseModel from mpt_api_client.resources.mixins import AsyncDocumentMixin, DocumentMixin -class Document(Model): +class Document(DocumentModel): """Document resource. Attributes: - name: Document name. - type: Document type. - description: Document description. - status: Document status. - filename: Original file name. - size: File size in bytes. - content_type: MIME content type of the document. - url: URL to access the document. program: Reference to the program. audit: Audit information (created, updated events). """ - name: str | None - type: str | None - description: str | None - status: str | None - filename: str | None - size: int | None - content_type: str | None - url: str | None - program: BaseModel | None - audit: BaseModel | None + program: BaseModel | None = None + audit: BaseModel | None = None class DocumentServiceConfig: diff --git a/mpt_api_client/resources/program/programs_media.py b/mpt_api_client/resources/program/programs_media.py index ad8e9c10..5dfb25b1 100644 --- a/mpt_api_client/resources/program/programs_media.py +++ b/mpt_api_client/resources/program/programs_media.py @@ -5,39 +5,21 @@ CollectionMixin, ModifiableResourceMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import MediaModel from mpt_api_client.models.model import BaseModel from mpt_api_client.resources.mixins import AsyncMediaMixin, MediaMixin -class Media(Model): +class Media(MediaModel): """Media resource. Attributes: - name: Media name. - type: Media type. - description: Media description. - status: Media status. - filename: Original file name. - size: File size in bytes. - content_type: MIME content type of the media file. - display_order: Display order of the media item. - url: URL to access the media file. program: Reference to the program. audit: Audit information (created, updated events). """ - name: str | None - type: str | None - description: str | None - status: str | None - filename: str | None - size: int | None - content_type: str | None - display_order: int | None - url: str | None - program: BaseModel | None - audit: BaseModel | None + program: BaseModel | None = None + audit: BaseModel | None = None class MediaServiceConfig: diff --git a/mpt_api_client/resources/program/programs_terms_variant.py b/mpt_api_client/resources/program/programs_terms_variant.py index f826b3e7..5f2d80f2 100644 --- a/mpt_api_client/resources/program/programs_terms_variant.py +++ b/mpt_api_client/resources/program/programs_terms_variant.py @@ -9,41 +9,21 @@ DownloadFileMixin, ModifiableResourceMixin, ) -from mpt_api_client.models import Model +from mpt_api_client.models import TermVariantModel from mpt_api_client.models.model import BaseModel from mpt_api_client.resources.mixins import AsyncPublishableMixin, PublishableMixin -class TermVariant(Model): +class TermVariant(TermVariantModel): """Term variant resource. Attributes: - name: The name of the term variant. - type: The type of the term variant. - asset_url: The URL of the asset. - language_code: The language code of the term variant. - description: The description of the term variant. - status: The status of the term variant. - filename: The filename of the term variant. - size: The size of the term variant. - content_type: The content type of the term variant. program_terms_and_conditions: The associated program terms and conditions. - file_id: The ID of the file. audit: The audit information. """ - name: str | None - type: str | None - asset_url: str | None - language_code: str | None - description: str | None - status: str | None - filename: str | None - size: int | None - content_type: str | None - program_terms_and_conditions: BaseModel | None - file_id: str | None - audit: BaseModel | None + program_terms_and_conditions: BaseModel | None = None + audit: BaseModel | None = None class TermVariantServiceConfig: diff --git a/tests/e2e/helpdesk/chats/attachment/test_async_attachment.py b/tests/e2e/helpdesk/chats/attachment/test_async_attachment.py index f9fa6169..3cc25bca 100644 --- a/tests/e2e/helpdesk/chats/attachment/test_async_attachment.py +++ b/tests/e2e/helpdesk/chats/attachment/test_async_attachment.py @@ -3,7 +3,7 @@ import pytest from mpt_api_client.exceptions import MPTAPIError -from mpt_api_client.resources.helpdesk.chat_attachments import ChatAttachment +from mpt_api_client.models import AttachmentModel pytestmark = [pytest.mark.flaky] @@ -12,18 +12,18 @@ async def test_list_chat_attachments(async_chat_attachments_service, async_creat result = await async_chat_attachments_service.fetch_page(limit=1) assert len(result) > 0 - assert all(isinstance(attachment, ChatAttachment) for attachment in result) + assert all(isinstance(attachment, AttachmentModel) for attachment in result) def test_create_chat_attachment(async_created_chat_attachment, chat_attachment_data): # noqa: AAA01 - assert isinstance(async_created_chat_attachment, ChatAttachment) + assert isinstance(async_created_chat_attachment, AttachmentModel) assert async_created_chat_attachment.to_dict().get("name") == chat_attachment_data["name"] async def test_get_chat_attachment(async_chat_attachments_service, async_created_chat_attachment): result = await async_chat_attachments_service.get(async_created_chat_attachment.id) - assert isinstance(result, ChatAttachment) + assert isinstance(result, AttachmentModel) async def test_update_chat_attachment( @@ -36,7 +36,7 @@ async def test_update_chat_attachment( {"name": updated_name, "description": updated_name}, ) - assert isinstance(result, ChatAttachment) + assert isinstance(result, AttachmentModel) assert result.to_dict().get("name") == updated_name diff --git a/tests/e2e/helpdesk/chats/attachment/test_sync_attachment.py b/tests/e2e/helpdesk/chats/attachment/test_sync_attachment.py index 22b18dd3..63ebc9a4 100644 --- a/tests/e2e/helpdesk/chats/attachment/test_sync_attachment.py +++ b/tests/e2e/helpdesk/chats/attachment/test_sync_attachment.py @@ -3,7 +3,7 @@ import pytest from mpt_api_client.exceptions import MPTAPIError -from mpt_api_client.resources.helpdesk.chat_attachments import ChatAttachment +from mpt_api_client.models import AttachmentModel pytestmark = [pytest.mark.flaky] @@ -12,18 +12,18 @@ def test_list_chat_attachments(chat_attachments_service, created_chat_attachment result = chat_attachments_service.fetch_page(limit=1) assert len(result) > 0 - assert all(isinstance(attachment, ChatAttachment) for attachment in result) + assert all(isinstance(attachment, AttachmentModel) for attachment in result) def test_create_chat_attachment(created_chat_attachment, chat_attachment_data): # noqa: AAA01 - assert isinstance(created_chat_attachment, ChatAttachment) + assert isinstance(created_chat_attachment, AttachmentModel) assert created_chat_attachment.to_dict().get("name") == chat_attachment_data["name"] def test_get_chat_attachment(chat_attachments_service, created_chat_attachment): result = chat_attachments_service.get(created_chat_attachment.id) - assert isinstance(result, ChatAttachment) + assert isinstance(result, AttachmentModel) def test_update_chat_attachment(chat_attachments_service, created_chat_attachment, short_uuid): @@ -34,7 +34,7 @@ def test_update_chat_attachment(chat_attachments_service, created_chat_attachmen {"name": updated_name, "description": updated_name}, ) - assert isinstance(result, ChatAttachment) + assert isinstance(result, AttachmentModel) assert result.to_dict().get("name") == updated_name diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index 07a2845b..df76d043 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -19,3 +19,63 @@ def http_client(): @pytest.fixture def async_http_client(): return AsyncHTTPClient(base_url=API_URL, api_token=API_TOKEN) + + +@pytest.fixture +def attachment_data(): + return { + "id": "ATT-001", + "name": "attachment.pdf", + "type": "Document", + "size": 2048, + "description": "Attachment description", + "contentType": "application/pdf", + } + + +@pytest.fixture +def document_inherited_data(): + return { + "id": "DOC-001", + "name": "User Guide", + "type": "Document", + "description": "User guide document", + "status": "Active", + "filename": "guide.pdf", + "size": 4096, + "contentType": "application/pdf", + "url": "https://example.com/guide.pdf", + } + + +@pytest.fixture +def media_inherited_data(): + return { + "id": "MED-001", + "name": "Screenshot", + "type": "Image", + "description": "Product screenshot", + "status": "Active", + "filename": "screenshot.png", + "size": 512000, + "contentType": "image/png", + "displayOrder": 1, + "url": "https://example.com/screenshot.png", + } + + +@pytest.fixture +def term_variant_inherited_data(): + return { + "id": "TRV-001", + "name": "English Variant", + "type": "PDF", + "assetUrl": "https://example.com/file.pdf", + "languageCode": "en-US", + "description": "English language variant", + "status": "Active", + "filename": "terms.pdf", + "size": 2048, + "contentType": "application/pdf", + "fileId": "FILE-001", + } diff --git a/tests/unit/models/test_attachment_model.py b/tests/unit/models/test_attachment_model.py new file mode 100644 index 00000000..e8468d65 --- /dev/null +++ b/tests/unit/models/test_attachment_model.py @@ -0,0 +1,42 @@ +from mpt_api_client.models import AttachmentModel + + +class AttachmentModelDummy(AttachmentModel): + """Dummy class for testing AttachmentModel.""" + + +def test_attachment_absent_fields(): # noqa: WPS218 + result = AttachmentModelDummy({"id": "ATT-001"}) + + assert result.id == "ATT-001" + assert result.name is None + assert result.type is None + assert result.size is None + assert result.description is None + assert result.content_type is None + + +def test_attachment_populates_camel(): # noqa: WPS218 + resource_data = { + "id": "ATT-001", + "name": "doc.pdf", + "type": "application/pdf", + "size": 1024, + "description": "A document", + "contentType": "application/pdf", + } + + result = AttachmentModelDummy(resource_data) + + assert result.name == "doc.pdf" + assert result.type == "application/pdf" + assert result.size == 1024 + assert result.description == "A document" + assert result.content_type == "application/pdf" + assert result.to_dict() == resource_data + + +def test_attachment_repr(): + result = AttachmentModelDummy({"id": "ATT-001"}) + + assert repr(result) == "" diff --git a/tests/unit/models/test_document_model.py b/tests/unit/models/test_document_model.py new file mode 100644 index 00000000..20a8a50f --- /dev/null +++ b/tests/unit/models/test_document_model.py @@ -0,0 +1,47 @@ +from mpt_api_client.models import DocumentModel + + +class DocumentModelDummy(DocumentModel): + """Dummy class for testing DocumentModel.""" + + +def test_document_absent_fields(): # noqa: WPS218 + result = DocumentModelDummy({"id": "DOC-001"}) + + assert result.id == "DOC-001" + assert result.name is None + assert result.type is None + assert result.size is None + assert result.description is None + assert result.content_type is None + assert result.status is None + assert result.filename is None + assert result.url is None + + +def test_document_populates_camel(): + resource_data = { + "id": "DOC-001", + "name": "User Guide", + "type": "Document", + "size": 4096, + "description": "User guide document", + "contentType": "application/pdf", + "status": "Active", + "filename": "guide.pdf", + "url": "https://example.com/guide.pdf", + } + + result = DocumentModelDummy(resource_data) + + assert result.name == "User Guide" + assert result.status == "Active" + assert result.filename == "guide.pdf" + assert result.url == "https://example.com/guide.pdf" + assert result.to_dict() == resource_data + + +def test_document_repr(): + result = DocumentModelDummy({"id": "DOC-001"}) + + assert repr(result) == "" diff --git a/tests/unit/models/test_file_resource_model.py b/tests/unit/models/test_file_resource_model.py new file mode 100644 index 00000000..1286ffe2 --- /dev/null +++ b/tests/unit/models/test_file_resource_model.py @@ -0,0 +1,42 @@ +from mpt_api_client.models import FileResourceModel + + +class FileResourceModelDummy(FileResourceModel): + """Dummy class for testing FileResourceModel.""" + + +def test_file_resource_absent_fields(): # noqa: WPS218 + result = FileResourceModelDummy({"id": "FRM-001"}) + + assert result.id == "FRM-001" + assert result.name is None + assert result.type is None + assert result.size is None + assert result.description is None + assert result.content_type is None + + +def test_file_resource_populates_camel(): # noqa: WPS218 + resource_data = { + "id": "FRM-001", + "name": "file.pdf", + "type": "Document", + "size": 1024, + "description": "A file", + "contentType": "application/pdf", + } + + result = FileResourceModelDummy(resource_data) + + assert result.name == "file.pdf" + assert result.type == "Document" + assert result.size == 1024 + assert result.description == "A file" + assert result.content_type == "application/pdf" + assert result.to_dict() == resource_data + + +def test_file_resource_repr(): + result = FileResourceModelDummy({"id": "FRM-001"}) + + assert repr(result) == "" diff --git a/tests/unit/models/test_media_model.py b/tests/unit/models/test_media_model.py new file mode 100644 index 00000000..96c7f79c --- /dev/null +++ b/tests/unit/models/test_media_model.py @@ -0,0 +1,49 @@ +from mpt_api_client.models import MediaModel + + +class MediaModelDummy(MediaModel): + """Dummy class for testing MediaModel.""" + + +def test_media_absent_fields(): # noqa: WPS218 + result = MediaModelDummy({"id": "MED-001"}) + + assert result.id == "MED-001" + assert result.name is None + assert result.type is None + assert result.size is None + assert result.description is None + assert result.content_type is None + assert result.status is None + assert result.filename is None + assert result.display_order is None + assert result.url is None + + +def test_media_populates_camel(): + resource_data = { + "id": "MED-001", + "name": "Screenshot", + "type": "Image", + "size": 512000, + "description": "Product screenshot", + "contentType": "image/png", + "status": "Active", + "filename": "screenshot.png", + "displayOrder": 1, + "url": "https://example.com/screenshot.png", + } + + result = MediaModelDummy(resource_data) + + assert result.name == "Screenshot" + assert result.status == "Active" + assert result.display_order == 1 + assert result.url == "https://example.com/screenshot.png" + assert result.to_dict() == resource_data + + +def test_media_repr(): + result = MediaModelDummy({"id": "MED-001"}) + + assert repr(result) == "" diff --git a/tests/unit/models/test_term_variant_model.py b/tests/unit/models/test_term_variant_model.py new file mode 100644 index 00000000..075f297b --- /dev/null +++ b/tests/unit/models/test_term_variant_model.py @@ -0,0 +1,51 @@ +from mpt_api_client.models import TermVariantModel + + +class TermVariantModelDummy(TermVariantModel): + """Dummy class for testing TermVariantModel.""" + + +def test_term_variant_absent_fields(): # noqa: WPS218 + result = TermVariantModelDummy({"id": "TRV-001"}) + + assert result.id == "TRV-001" + assert result.name is None + assert result.type is None + assert result.size is None + assert result.description is None + assert result.content_type is None + assert result.asset_url is None + assert result.language_code is None + assert result.status is None + assert result.filename is None + assert result.file_id is None + + +def test_term_variant_populates_camel(): + resource_data = { + "id": "TRV-001", + "name": "English Variant", + "type": "PDF", + "size": 2048, + "description": "English language variant", + "contentType": "application/pdf", + "assetUrl": "https://example.com/file.pdf", + "languageCode": "en-US", + "status": "Active", + "filename": "terms.pdf", + "fileId": "FILE-001", + } + + result = TermVariantModelDummy(resource_data) + + assert result.name == "English Variant" + assert result.asset_url == "https://example.com/file.pdf" + assert result.language_code == "en-US" + assert result.file_id == "FILE-001" + assert result.to_dict() == resource_data + + +def test_term_variant_repr(): + result = TermVariantModelDummy({"id": "TRV-001"}) + + assert repr(result) == "" diff --git a/tests/unit/resources/billing/test_credit_memo_attachments.py b/tests/unit/resources/billing/test_credit_memo_attachments.py index 56cc6fdd..661b78e9 100644 --- a/tests/unit/resources/billing/test_credit_memo_attachments.py +++ b/tests/unit/resources/billing/test_credit_memo_attachments.py @@ -2,6 +2,7 @@ from mpt_api_client.resources.billing.credit_memo_attachments import ( AsyncCreditMemoAttachmentsService, + CreditMemoAttachment, CreditMemoAttachmentsService, ) @@ -50,3 +51,20 @@ def test_async_methods_present(async_credit_memo_attachments_service, method: st result = hasattr(async_credit_memo_attachments_service, method) assert result is True + + +def test_attachment_inherited_primitive_fields(attachment_data): + result = CreditMemoAttachment(attachment_data) + + assert result.to_dict() == attachment_data + + +def test_attachment_inherited_fields_absent(): # noqa: WPS218 + result = CreditMemoAttachment({"id": "ATT-001"}) + + assert result.id == "ATT-001" + assert result.name is None + assert result.type is None + assert result.size is None + assert result.description is None + assert result.content_type is None diff --git a/tests/unit/resources/billing/test_custom_ledger_attachments.py b/tests/unit/resources/billing/test_custom_ledger_attachments.py index 69b37ce8..2a29c793 100644 --- a/tests/unit/resources/billing/test_custom_ledger_attachments.py +++ b/tests/unit/resources/billing/test_custom_ledger_attachments.py @@ -2,6 +2,7 @@ from mpt_api_client.resources.billing.custom_ledger_attachments import ( AsyncCustomLedgerAttachmentsService, + CustomLedgerAttachment, CustomLedgerAttachmentsService, ) @@ -48,3 +49,20 @@ def test_async_methods_present(async_custom_ledger_attachments_service, method: result = hasattr(async_custom_ledger_attachments_service, method) assert result is True + + +def test_attachment_inherited_primitive_fields(attachment_data): + result = CustomLedgerAttachment(attachment_data) + + assert result.to_dict() == attachment_data + + +def test_attachment_inherited_fields_absent(): # noqa: WPS218 + result = CustomLedgerAttachment({"id": "ATT-001"}) + + assert result.id == "ATT-001" + assert result.name is None + assert result.type is None + assert result.size is None + assert result.description is None + assert result.content_type is None diff --git a/tests/unit/resources/billing/test_invoice_attachments.py b/tests/unit/resources/billing/test_invoice_attachments.py index a43dc56f..15591a66 100644 --- a/tests/unit/resources/billing/test_invoice_attachments.py +++ b/tests/unit/resources/billing/test_invoice_attachments.py @@ -2,6 +2,7 @@ from mpt_api_client.resources.billing.invoice_attachments import ( AsyncInvoiceAttachmentsService, + InvoiceAttachment, InvoiceAttachmentsService, ) @@ -49,3 +50,20 @@ def test_async_methods_present(async_invoice_attachments_service, method: str): result = hasattr(async_invoice_attachments_service, method) assert result is True + + +def test_attachment_inherited_primitive_fields(attachment_data): + result = InvoiceAttachment(attachment_data) + + assert result.to_dict() == attachment_data + + +def test_attachment_inherited_fields_absent(): # noqa: WPS218 + result = InvoiceAttachment({"id": "ATT-001"}) + + assert result.id == "ATT-001" + assert result.name is None + assert result.type is None + assert result.size is None + assert result.description is None + assert result.content_type is None diff --git a/tests/unit/resources/billing/test_journal_attachments.py b/tests/unit/resources/billing/test_journal_attachments.py index 86cdc1c7..89321aec 100644 --- a/tests/unit/resources/billing/test_journal_attachments.py +++ b/tests/unit/resources/billing/test_journal_attachments.py @@ -2,6 +2,7 @@ from mpt_api_client.resources.billing.journal_attachments import ( AsyncJournalAttachmentsService, + JournalAttachment, JournalAttachmentsService, ) @@ -49,3 +50,20 @@ def test_async_methods_present(async_journal_attachments_service, method: str) - result = hasattr(async_journal_attachments_service, method) assert result is True + + +def test_attachment_inherited_primitive_fields(attachment_data): + result = JournalAttachment(attachment_data) + + assert result.to_dict() == attachment_data + + +def test_attachment_inherited_fields_absent(): # noqa: WPS218 + result = JournalAttachment({"id": "ATT-001"}) + + assert result.id == "ATT-001" + assert result.name is None + assert result.type is None + assert result.size is None + assert result.description is None + assert result.content_type is None diff --git a/tests/unit/resources/billing/test_ledger_attachments.py b/tests/unit/resources/billing/test_ledger_attachments.py index d4321c6d..55911edb 100644 --- a/tests/unit/resources/billing/test_ledger_attachments.py +++ b/tests/unit/resources/billing/test_ledger_attachments.py @@ -2,6 +2,7 @@ from mpt_api_client.resources.billing.ledger_attachments import ( AsyncLedgerAttachmentsService, + LedgerAttachment, LedgerAttachmentsService, ) @@ -49,3 +50,20 @@ def test_async_methods_present(async_ledger_attachments_service, method: str) -> result = hasattr(async_ledger_attachments_service, method) assert result is True + + +def test_attachment_inherited_primitive_fields(attachment_data): + result = LedgerAttachment(attachment_data) + + assert result.to_dict() == attachment_data + + +def test_attachment_inherited_fields_absent(): # noqa: WPS218 + result = LedgerAttachment({"id": "ATT-001"}) + + assert result.id == "ATT-001" + assert result.name is None + assert result.type is None + assert result.size is None + assert result.description is None + assert result.content_type is None diff --git a/tests/unit/resources/billing/test_statement_attachments.py b/tests/unit/resources/billing/test_statement_attachments.py index be1573df..b177f339 100644 --- a/tests/unit/resources/billing/test_statement_attachments.py +++ b/tests/unit/resources/billing/test_statement_attachments.py @@ -2,6 +2,7 @@ from mpt_api_client.resources.billing.statement_attachments import ( AsyncStatementAttachmentsService, + StatementAttachment, StatementAttachmentsService, ) @@ -50,3 +51,20 @@ def test_async_methods_present(async_statement_attachments_service, method: str) result = hasattr(async_statement_attachments_service, method) assert result is True + + +def test_attachment_inherited_primitive_fields(attachment_data): + result = StatementAttachment(attachment_data) + + assert result.to_dict() == attachment_data + + +def test_attachment_inherited_fields_absent(): # noqa: WPS218 + result = StatementAttachment({"id": "ATT-001"}) + + assert result.id == "ATT-001" + assert result.name is None + assert result.type is None + assert result.size is None + assert result.description is None + assert result.content_type is None diff --git a/tests/unit/resources/catalog/test_pricing_policy_attachments.py b/tests/unit/resources/catalog/test_pricing_policy_attachments.py index ec923977..773e9dc6 100644 --- a/tests/unit/resources/catalog/test_pricing_policy_attachments.py +++ b/tests/unit/resources/catalog/test_pricing_policy_attachments.py @@ -83,10 +83,15 @@ def test_pricing_policy_attachment_nested_models(pricing_policy_attachment_data) assert isinstance(result.audit, BaseModel) -def test_pricing_policy_attachment_absent(): +def test_pricing_policy_attachment_absent(): # noqa: WPS218 result = PricingPolicyAttachment({"id": "ATT-001"}) assert result.id == "ATT-001" - assert not hasattr(result, "name") - assert not hasattr(result, "status") - assert not hasattr(result, "audit") + assert result.name is None + assert result.type is None + assert result.size is None + assert result.description is None + assert result.content_type is None + assert result.file_name is None + assert result.status is None + assert result.audit is None diff --git a/tests/unit/resources/catalog/test_product_term_variants.py b/tests/unit/resources/catalog/test_product_term_variants.py index 940ff4f6..90020f90 100644 --- a/tests/unit/resources/catalog/test_product_term_variants.py +++ b/tests/unit/resources/catalog/test_product_term_variants.py @@ -89,6 +89,12 @@ def test_term_variant_primitive_fields(term_variant_data: dict) -> None: assert result.to_dict() == term_variant_data +def test_term_variant_inherited_primitive_fields(term_variant_inherited_data: dict) -> None: + result = TermVariant(term_variant_inherited_data) + + assert result.to_dict() == term_variant_inherited_data + + def test_term_variant_nested_base_models(term_variant_data: dict) -> None: result = TermVariant(term_variant_data) @@ -96,10 +102,19 @@ def test_term_variant_nested_base_models(term_variant_data: dict) -> None: assert isinstance(result.audit, BaseModel) -def test_term_variant_optional_fields_absent() -> None: +def test_term_variant_optional_fields_absent() -> None: # noqa: WPS218 result = TermVariant({"id": "TRV-001"}) assert result.id == "TRV-001" - assert not hasattr(result, "name") - assert not hasattr(result, "status") - assert not hasattr(result, "audit") + assert result.name is None + assert result.type is None + assert result.asset_url is None + assert result.language_code is None + assert result.description is None + assert result.status is None + assert result.filename is None + assert result.size is None + assert result.content_type is None + assert result.file_id is None + assert result.terms_and_conditions is None + assert result.audit is None diff --git a/tests/unit/resources/catalog/test_products_documents.py b/tests/unit/resources/catalog/test_products_documents.py index af22ccfa..6180ae26 100644 --- a/tests/unit/resources/catalog/test_products_documents.py +++ b/tests/unit/resources/catalog/test_products_documents.py @@ -76,6 +76,12 @@ def test_document_primitive_fields(document_data): assert result.to_dict() == document_data +def test_document_inherited_primitive_fields(document_inherited_data): + result = Document(document_inherited_data) + + assert result.to_dict() == document_inherited_data + + def test_document_nested_fields_are_base_models(document_data): result = Document(document_data) @@ -83,10 +89,18 @@ def test_document_nested_fields_are_base_models(document_data): assert isinstance(result.audit, BaseModel) -def test_document_optional_fields_absent(): +def test_document_optional_fields_absent(): # noqa: WPS218 result = Document({"id": "DOC-001"}) assert result.id == "DOC-001" - assert not hasattr(result, "name") - assert not hasattr(result, "status") - assert not hasattr(result, "audit") + assert result.name is None + assert result.type is None + assert result.description is None + assert result.status is None + assert result.filename is None + assert result.size is None + assert result.content_type is None + assert result.url is None + assert result.language is None + assert result.product is None + assert result.audit is None diff --git a/tests/unit/resources/catalog/test_products_media.py b/tests/unit/resources/catalog/test_products_media.py index bd789af9..565978eb 100644 --- a/tests/unit/resources/catalog/test_products_media.py +++ b/tests/unit/resources/catalog/test_products_media.py @@ -76,6 +76,12 @@ def test_media_primitive_fields(media_data): assert result.to_dict() == media_data +def test_media_inherited_primitive_fields(media_inherited_data): + result = Media(media_inherited_data) + + assert result.to_dict() == media_inherited_data + + def test_media_nested_fields_are_base_models(media_data): result = Media(media_data) @@ -83,10 +89,18 @@ def test_media_nested_fields_are_base_models(media_data): assert isinstance(result.audit, BaseModel) -def test_media_optional_fields_absent(): +def test_media_optional_fields_absent(): # noqa: WPS218 result = Media({"id": "MED-001"}) assert result.id == "MED-001" - assert not hasattr(result, "name") - assert not hasattr(result, "status") - assert not hasattr(result, "audit") + assert result.name is None + assert result.type is None + assert result.description is None + assert result.status is None + assert result.filename is None + assert result.size is None + assert result.content_type is None + assert result.display_order is None + assert result.url is None + assert result.product is None + assert result.audit is None diff --git a/tests/unit/resources/integration/test_extension_documents.py b/tests/unit/resources/integration/test_extension_documents.py index bbef452a..8b8f50a8 100644 --- a/tests/unit/resources/integration/test_extension_documents.py +++ b/tests/unit/resources/integration/test_extension_documents.py @@ -100,6 +100,12 @@ def test_extension_document_primitive_fields(document_data): assert result.to_dict() == document_data +def test_extension_document_inherited_fields(document_inherited_data): + result = ExtensionDocument(document_inherited_data) + + assert result.to_dict() == document_inherited_data + + def test_extension_document_nested_fields(document_data): result = ExtensionDocument(document_data) @@ -111,9 +117,18 @@ def test_extension_document_optional_absent(): result = ExtensionDocument({"id": "DOC-001"}) assert result.id == "DOC-001" - assert not hasattr(result, "name") - assert not hasattr(result, "status") - assert not hasattr(result, "audit") + assert result.name is None + assert result.type is None + assert result.description is None + assert result.status is None + assert result.filename is None + assert result.size is None + assert result.content_type is None + assert result.url is None + assert result.revision is None + assert result.language is None + assert result.extension is None + assert result.audit is None def test_extension_document_create(extension_documents_service, tmp_path): diff --git a/tests/unit/resources/integration/test_extension_media.py b/tests/unit/resources/integration/test_extension_media.py index 55a39362..8df0d369 100644 --- a/tests/unit/resources/integration/test_extension_media.py +++ b/tests/unit/resources/integration/test_extension_media.py @@ -103,6 +103,12 @@ def test_extension_media_primitive_fields(media_data) -> None: assert result.display_order == 1 +def test_extension_media_inherited_fields(media_inherited_data) -> None: + result = ExtensionMedia(media_inherited_data) + + assert result.to_dict() == media_inherited_data + + def test_extension_media_nested_fields(media_data) -> None: # noqa: WPS118 result = ExtensionMedia(media_data) diff --git a/tests/unit/resources/integration/test_extension_term_variants.py b/tests/unit/resources/integration/test_extension_term_variants.py index ea714c17..45df1de8 100644 --- a/tests/unit/resources/integration/test_extension_term_variants.py +++ b/tests/unit/resources/integration/test_extension_term_variants.py @@ -87,6 +87,14 @@ def test_extension_term_variant_primitive_fields(variant_data: dict) -> None: assert result.to_dict() == variant_data +def test_extension_term_variant_inherited_fields( + term_variant_inherited_data: dict, +) -> None: + result = ExtensionTermVariant(term_variant_inherited_data) + + assert result.to_dict() == term_variant_inherited_data + + def test_extension_term_variant_nested_fields(variant_data: dict) -> None: result = ExtensionTermVariant(variant_data) diff --git a/tests/unit/resources/program/test_programs_documents.py b/tests/unit/resources/program/test_programs_documents.py index e49dd98a..b68f0070 100644 --- a/tests/unit/resources/program/test_programs_documents.py +++ b/tests/unit/resources/program/test_programs_documents.py @@ -76,6 +76,12 @@ def test_document_primitive_fields(document_data): assert result.to_dict() == document_data +def test_document_inherited_primitive_fields(document_inherited_data): + result = Document(document_inherited_data) + + assert result.to_dict() == document_inherited_data + + def test_document_nested_fields_are_base_models(document_data): result = Document(document_data) @@ -87,8 +93,13 @@ def test_document_optional_fields_absent(): result = Document({"id": "PDM-001"}) assert result.id == "PDM-001" - assert not hasattr(result, "name") - assert not hasattr(result, "type") - assert not hasattr(result, "description") - assert not hasattr(result, "status") - assert not hasattr(result, "audit") + assert result.name is None + assert result.type is None + assert result.description is None + assert result.status is None + assert result.filename is None + assert result.size is None + assert result.content_type is None + assert result.url is None + assert result.program is None + assert result.audit is None diff --git a/tests/unit/resources/program/test_programs_media.py b/tests/unit/resources/program/test_programs_media.py index 3dbe0d45..24229915 100644 --- a/tests/unit/resources/program/test_programs_media.py +++ b/tests/unit/resources/program/test_programs_media.py @@ -76,6 +76,12 @@ def test_media_primitive_fields(media_data): assert result.to_dict() == media_data +def test_media_inherited_primitive_fields(media_inherited_data): + result = Media(media_inherited_data) + + assert result.to_dict() == media_inherited_data + + def test_media_nested_fields_are_base_models(media_data): result = Media(media_data) @@ -87,11 +93,14 @@ def test_media_optional_fields_absent(): result = Media({"id": "PMD-001"}) assert result.id == "PMD-001" - assert not hasattr(result, "name") - assert not hasattr(result, "type") - assert not hasattr(result, "description") - assert not hasattr(result, "status") - assert not hasattr(result, "filename") - assert not hasattr(result, "size") - assert not hasattr(result, "content_type") - assert not hasattr(result, "audit") + assert result.name is None + assert result.type is None + assert result.description is None + assert result.status is None + assert result.filename is None + assert result.size is None + assert result.content_type is None + assert result.display_order is None + assert result.url is None + assert result.program is None + assert result.audit is None diff --git a/tests/unit/resources/program/test_programs_terms_variant.py b/tests/unit/resources/program/test_programs_terms_variant.py index 780334f0..ece2a8e2 100644 --- a/tests/unit/resources/program/test_programs_terms_variant.py +++ b/tests/unit/resources/program/test_programs_terms_variant.py @@ -87,6 +87,12 @@ def test_term_variant_primitive_fields(term_variant_data: dict) -> None: assert result.to_dict() == term_variant_data +def test_term_variant_inherited_primitive_fields(term_variant_inherited_data: dict) -> None: + result = TermVariant(term_variant_inherited_data) + + assert result.to_dict() == term_variant_inherited_data + + def test_term_variant_nested_base_model(term_variant_data: dict) -> None: result = TermVariant(term_variant_data) @@ -98,13 +104,15 @@ def test_term_variant_optional_fields_absent() -> None: result = TermVariant({"id": "PTV-001"}) assert result.id == "PTV-001" - assert not hasattr(result, "type") - assert not hasattr(result, "assetUrl") - assert not hasattr(result, "languageCode") - assert not hasattr(result, "name") - assert not hasattr(result, "description") - assert not hasattr(result, "status") - assert not hasattr(result, "filename") - assert not hasattr(result, "size") - assert not hasattr(result, "contentType") - assert not hasattr(result, "fileId") + assert result.name is None + assert result.type is None + assert result.asset_url is None + assert result.language_code is None + assert result.description is None + assert result.status is None + assert result.filename is None + assert result.size is None + assert result.content_type is None + assert result.file_id is None + assert result.program_terms_and_conditions is None + assert result.audit is None