From 80d2dcd35e99f4f982af3e23c8b83117a5af34d4 Mon Sep 17 00:00:00 2001 From: RishavTiwari25 Date: Mon, 26 Oct 2026 14:21:56 +0530 Subject: [PATCH 1/2] fix(types): keep raw_transcription_config values and rebuild transcript.config from them TranscriptionConfig(raw_transcription_config=raw) assigned every constructor argument onto raw, so their None defaults erased nearly all of raw's values. Transcript.config passed the response's fields as constructor arguments, which raised for a transcript with custom_spelling (the API returns a list of from/to objects, the argument is a dict) or language_detection_results (not an argument at all). It now builds a RawTranscriptionConfig and passes that. --- assemblyai/prerecorded/v2/_base.py | 11 +++++-- assemblyai/types.py | 17 +++++++---- tests/unit/test_config.py | 34 +++++++++++++++++++++ tests/unit/test_transcript.py | 48 ++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 9 deletions(-) diff --git a/assemblyai/prerecorded/v2/_base.py b/assemblyai/prerecorded/v2/_base.py index 24d8d74e..a2724fbf 100644 --- a/assemblyai/prerecorded/v2/_base.py +++ b/assemblyai/prerecorded/v2/_base.py @@ -100,10 +100,15 @@ def config_from_response( ) -> types.TranscriptionConfig: """Rebuilds the `TranscriptionConfig` a transcript was created with.""" + # Goes through `RawTranscriptionConfig`: the response carries fields in their + # API shape (e.g. `custom_spelling` as a list of from/to objects) and fields + # that are not constructor arguments (e.g. `language_detection_results`). return types.TranscriptionConfig( - **response.dict( - include=set(types.RawTranscriptionConfig.__fields__), - exclude_none=True, + raw_transcription_config=types.RawTranscriptionConfig( + **response.dict( + include=set(types.RawTranscriptionConfig.__fields__), + exclude_none=True, + ) ) ) diff --git a/assemblyai/types.py b/assemblyai/types.py index f7226587..54a4ad57 100644 --- a/assemblyai/types.py +++ b/assemblyai/types.py @@ -1256,13 +1256,11 @@ def __init__( keyterms_prompt_options: Options for controlling keyterms boosting behavior when using `keyterms_prompt`. domain: The domain to use for the transcription (e.g. 'medical-v1'). """ - self._raw_transcription_config = ( - raw_transcription_config - if raw_transcription_config is not None - else RawTranscriptionConfig() - ) + # The explicit arguments are applied to a fresh config first. Applying them + # straight onto `raw_transcription_config` would overwrite each of its + # values with the argument's `None` default. + self._raw_transcription_config = RawTranscriptionConfig() - # explicit configurations have higher priority if `raw_transcription_config` has been passed as well self.language_code = language_code self.language_codes = language_codes self.punctuate = punctuate @@ -1317,6 +1315,13 @@ def __init__( self.speech_understanding = speech_understanding # type: ignore[assignment] self.domain = domain + if raw_transcription_config is not None: + # explicit configurations have higher priority if `raw_transcription_config` has been passed as well + for field, value in self._raw_transcription_config: + if value is not None: + setattr(raw_transcription_config, field, value) + self._raw_transcription_config = raw_transcription_config + @property def raw(self) -> RawTranscriptionConfig: return self._raw_transcription_config diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index 3b97b161..aaf731a6 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -18,3 +18,37 @@ def test_configuration_are_none_by_default(): pytest.fail( f"Configuration field {name} is {value} and not None by default." ) + + +def test_raw_transcription_config_values_are_kept(): + """ + Tests that the values of a passed `raw_transcription_config` are not + overwritten by the `None` defaults of the other constructor arguments. + """ + + raw = aai.RawTranscriptionConfig( + language_code="de", + punctuate=False, + custom_spelling=[{"from": ["k8s"], "to": "Kubernetes"}], + ) + + config = aai.TranscriptionConfig(raw_transcription_config=raw) + + assert config.raw is raw + assert config.language_code == "de" + assert config.punctuate is False + assert config.custom_spelling == {"Kubernetes": ["k8s"]} + + +def test_explicit_arguments_override_raw_transcription_config(): + """ + Tests that explicit constructor arguments take priority over the values of + a passed `raw_transcription_config`, and the others are kept. + """ + + raw = aai.RawTranscriptionConfig(language_code="de", punctuate=False) + + config = aai.TranscriptionConfig(raw_transcription_config=raw, language_code="fr") + + assert config.language_code == "fr" + assert config.punctuate is False diff --git a/tests/unit/test_transcript.py b/tests/unit/test_transcript.py index 25f6f6cf..8c4b9aa3 100644 --- a/tests/unit/test_transcript.py +++ b/tests/unit/test_transcript.py @@ -577,3 +577,51 @@ def test_metadata_not_present(): transcript_response = aai.types.TranscriptResponse(**mock_transcript_response) assert transcript_response.metadata is None + + +def test_config_from_response_with_custom_spelling(): + """ + Tests that `transcript.config` rebuilds a config whose response echoes + `custom_spelling` in its API shape, a list of from/to objects. + """ + + mock_transcript_response = factories.generate_dict_factory( + factories.TranscriptCompletedResponseFactory + )() + mock_transcript_response["custom_spelling"] = [ + {"from": ["k8s", "kube"], "to": "Kubernetes"} + ] + + transcript = aai.Transcript.from_response( + client=aai.Client.get_default(), + response=aai.types.TranscriptResponse(**mock_transcript_response), + ) + + assert transcript.config.custom_spelling == {"Kubernetes": ["k8s", "kube"]} + + +def test_config_from_response_with_language_detection_results(): + """ + Tests that `transcript.config` rebuilds a config whose response carries + `language_detection_results`, which is not a `TranscriptionConfig` argument. + """ + + mock_transcript_response = factories.generate_dict_factory( + factories.TranscriptCompletedResponseFactory + )() + mock_transcript_response["language_detection"] = True + mock_transcript_response["language_detection_results"] = { + "code_switching_languages": [{"language_code": "es", "confidence": 0.4}] + } + + transcript = aai.Transcript.from_response( + client=aai.Client.get_default(), + response=aai.types.TranscriptResponse(**mock_transcript_response), + ) + + config = transcript.config + + assert config.language_detection is True + results = config.language_detection_results + assert results is not None and results.code_switching_languages is not None + assert results.code_switching_languages[0].language_code == "es" From 413643d573d911df53959bdd0aba5e0e736d8474 Mon Sep 17 00:00:00 2001 From: RishavTiwari25 Date: Mon, 26 Oct 2026 14:28:56 +0530 Subject: [PATCH 2/2] chore: bump version to 1.8.3 --- assemblyai/__version__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assemblyai/__version__.py b/assemblyai/__version__.py index 320141d8..a44132de 100644 --- a/assemblyai/__version__.py +++ b/assemblyai/__version__.py @@ -1 +1 @@ -__version__ = "1.8.2" +__version__ = "1.8.3"