detextive 2.0__tar.gz → 3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. detextive-3.1/.gitignore +7 -0
  2. {detextive-2.0 → detextive-3.1}/PKG-INFO +6 -2
  3. {detextive-2.0 → detextive-3.1}/README.rst +3 -0
  4. {detextive-2.0 → detextive-3.1}/pyproject.toml +14 -6
  5. {detextive-2.0 → detextive-3.1}/sources/detextive/__/imports.py +7 -3
  6. {detextive-2.0 → detextive-3.1}/sources/detextive/__/nomina.py +0 -5
  7. {detextive-2.0 → detextive-3.1}/sources/detextive/__init__.py +1 -1
  8. detextive-3.1/sources/detextive/charsets.py +201 -0
  9. {detextive-2.0 → detextive-3.1}/sources/detextive/core.py +34 -23
  10. detextive-3.1/sources/detextive/decoders.py +254 -0
  11. {detextive-2.0 → detextive-3.1}/sources/detextive/detectors.py +41 -20
  12. {detextive-2.0 → detextive-3.1}/sources/detextive/exceptions.py +10 -7
  13. {detextive-2.0 → detextive-3.1}/sources/detextive/inference.py +49 -43
  14. {detextive-2.0 → detextive-3.1}/sources/detextive/nomina.py +7 -4
  15. detextive-2.0/.gitignore +0 -12
  16. detextive-2.0/sources/detextive/charsets.py +0 -118
  17. detextive-2.0/sources/detextive/decoders.py +0 -98
  18. {detextive-2.0 → detextive-3.1}/LICENSE.txt +0 -0
  19. {detextive-2.0 → detextive-3.1}/sources/detextive/__/__init__.py +0 -0
  20. {detextive-2.0 → detextive-3.1}/sources/detextive/_typedecls/puremagic/__init__.pyi +0 -0
  21. {detextive-2.0 → detextive-3.1}/sources/detextive/lineseparators.py +0 -0
  22. {detextive-2.0 → detextive-3.1}/sources/detextive/mimetypes.py +0 -0
  23. {detextive-2.0 → detextive-3.1}/sources/detextive/py.typed +0 -0
  24. {detextive-2.0 → detextive-3.1}/sources/detextive/validation.py +0 -0
@@ -0,0 +1,7 @@
1
+ .env
2
+ *.so
3
+ .*.swp
4
+ __pycache__/
5
+ bugs/
6
+ build/
7
+ dist/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: detextive
3
- Version: 2.0
3
+ Version: 3.1
4
4
  Summary: Detects textual content.
5
5
  Project-URL: Homepage, https://github.com/emcd/python-detextive
6
6
  Project-URL: Documentation, https://emcd.github.io/python-detextive
@@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
20
  Classifier: Programming Language :: Python :: 3.12
21
21
  Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
22
23
  Classifier: Programming Language :: Python :: Implementation :: CPython
23
24
  Classifier: Programming Language :: Python :: Implementation :: PyPy
24
25
  Classifier: Topic :: Software Development
@@ -27,7 +28,7 @@ Requires-Dist: absence~=1.1
27
28
  Requires-Dist: accretive~=4.1
28
29
  Requires-Dist: chardet
29
30
  Requires-Dist: dynadoc~=1.4
30
- Requires-Dist: frigid~=4.1
31
+ Requires-Dist: frigid~=4.2
31
32
  Requires-Dist: puremagic
32
33
  Requires-Dist: typing-extensions
33
34
  Provides-Extra: all
@@ -306,6 +307,9 @@ Other Projects by This Author 🌟
306
307
  * `python-icecream-truck <https://github.com/emcd/python-icecream-truck>`_ (`icecream-truck <https://pypi.org/project/icecream-truck/>`_ on PyPI)
307
308
 
308
309
  🍦 **Flavorful Debugging** - A Python library which enhances the powerful and well-known ``icecream`` package with flavored traces, configuration hierarchies, customized outputs, ready-made recipes, and more.
310
+ * `python-librovore <https://github.com/emcd/python-librovore>`_ (`librovore <https://pypi.org/project/librovore/>`_ on PyPI)
311
+
312
+ 🐲 **Documentation Search Engine** - An intelligent documentation search and extraction tool that provides both a command-line interface for humans and an MCP (Model Context Protocol) server for AI agents. Search across Sphinx and MkDocs sites with fuzzy matching, extract clean markdown content, and integrate seamlessly with AI development workflows.
309
313
  * `python-mimeogram <https://github.com/emcd/python-mimeogram>`_ (`mimeogram <https://pypi.org/project/mimeogram/>`_ on PyPI)
310
314
 
311
315
  📨 A command-line tool for **exchanging collections of files with Large Language Models** - bundle multiple files into a single clipboard-ready document while preserving directory structure and metadata... good for code reviews, project sharing, and LLM interactions.
@@ -263,6 +263,9 @@ Other Projects by This Author 🌟
263
263
  * `python-icecream-truck <https://github.com/emcd/python-icecream-truck>`_ (`icecream-truck <https://pypi.org/project/icecream-truck/>`_ on PyPI)
264
264
 
265
265
  🍦 **Flavorful Debugging** - A Python library which enhances the powerful and well-known ``icecream`` package with flavored traces, configuration hierarchies, customized outputs, ready-made recipes, and more.
266
+ * `python-librovore <https://github.com/emcd/python-librovore>`_ (`librovore <https://pypi.org/project/librovore/>`_ on PyPI)
267
+
268
+ 🐲 **Documentation Search Engine** - An intelligent documentation search and extraction tool that provides both a command-line interface for humans and an MCP (Model Context Protocol) server for AI agents. Search across Sphinx and MkDocs sites with fuzzy matching, extract clean markdown content, and integrate seamlessly with AI development workflows.
266
269
  * `python-mimeogram <https://github.com/emcd/python-mimeogram>`_ (`mimeogram <https://pypi.org/project/mimeogram/>`_ on PyPI)
267
270
 
268
271
  📨 A command-line tool for **exchanging collections of files with Large Language Models** - bundle multiple files into a single clipboard-ready document while preserving directory structure and metadata... good for code reviews, project sharing, and LLM interactions.
@@ -15,14 +15,14 @@ license = 'Apache-2.0'
15
15
  readme = { 'file' = 'README.rst', 'content-type' = 'text/x-rst' }
16
16
  requires-python = '>= 3.10'
17
17
  dependencies = [
18
- 'absence~=1.1',
19
18
  'accretive~=4.1',
20
19
  'chardet',
21
- 'dynadoc~=1.4',
22
- 'frigid~=4.1',
23
20
  'puremagic',
24
21
  'typing-extensions',
25
22
  # --- BEGIN: Injected by Copier ---
23
+ 'absence~=1.1',
24
+ 'dynadoc~=1.4',
25
+ 'frigid~=4.2',
26
26
  # --- END: Injected by Copier ---
27
27
  ]
28
28
  classifiers = [ # https://pypi.org/classifiers
@@ -35,6 +35,7 @@ classifiers = [ # https://pypi.org/classifiers
35
35
  'Programming Language :: Python :: 3.11',
36
36
  'Programming Language :: Python :: 3.12',
37
37
  'Programming Language :: Python :: 3.13',
38
+ 'Programming Language :: Python :: 3.14',
38
39
  'Programming Language :: Python :: Implementation :: CPython',
39
40
  'Programming Language :: Python :: Implementation :: PyPy',
40
41
  # --- END: Injected by Copier ---
@@ -105,13 +106,13 @@ strict-naming = false
105
106
  python = '3.10'
106
107
  [tool.hatch.envs.develop]
107
108
  description = ''' Development environment. '''
109
+ builder = true
108
110
  dependencies = [
109
- 'Jinja2',
110
111
  'coverage[toml]',
111
112
  'detextive[all]',
112
113
  'furo',
113
114
  'isort',
114
- 'packaging',
115
+ 'myst-parser',
115
116
  'pre-commit',
116
117
  'pyright',
117
118
  'pytest',
@@ -129,6 +130,7 @@ post-install-commands = [
129
130
  # --- END: Injected by Copier ---
130
131
  ]
131
132
  [tool.hatch.envs.develop.env-vars]
133
+ PYTHONIOENCODING = 'utf-8' # TODO: Only for coverage/doctest.
132
134
  PYTHONUNBUFFERED = 'TRUE' # TODO: Only for coverage/pytest.
133
135
  # --- BEGIN: Injected by Copier ---
134
136
  # --- END: Injected by Copier ---
@@ -141,10 +143,10 @@ docsgen = [
141
143
  ]
142
144
  linters = [
143
145
  """ruff check --quiet sources documentation tests""",
146
+ """vibelinter check""",
144
147
  # --- BEGIN: Injected by Copier ---
145
148
  # --- END: Injected by Copier ---
146
149
  """isort --check-only --diff sources tests""",
147
- """vulture""",
148
150
  """pyright sources""",
149
151
  ]
150
152
  packagers = [
@@ -186,7 +188,9 @@ python = [
186
188
  '3.11',
187
189
  '3.12',
188
190
  '3.13',
191
+ '3.14',
189
192
  'pypy3.10',
193
+ 'pypy3.11',
190
194
  ]
191
195
  [tool.hatch.version]
192
196
  path = 'sources/detextive/__init__.py'
@@ -359,6 +363,10 @@ directory = 'repair'
359
363
  name = 'Repairs'
360
364
  showcontent = true
361
365
 
366
+ [tool.vibelinter]
367
+ context = 3
368
+ exclude_paths = [ '.auxiliary/**', '.venv/**', 'tests/**', ]
369
+
362
370
  [tool.vulture]
363
371
  paths = [ '.auxiliary/configuration/vulturefood.py', 'sources' ]
364
372
  min_confidence = 60
@@ -24,8 +24,10 @@
24
24
 
25
25
  import collections.abc as cabc
26
26
  import codecs
27
+ import contextlib as ctxl
27
28
  import dataclasses as dcls
28
29
  import enum
30
+ import functools as funct
29
31
  import locale
30
32
  import mimetypes
31
33
  import os
@@ -36,11 +38,13 @@ import unicodedata
36
38
  from pathlib import Path
37
39
 
38
40
  import accretive as accret
39
- import dynadoc as ddoc
40
- import frigid as immut
41
41
  import typing_extensions as typx
42
42
 
43
- from absence import Absential, absent, is_absent
43
+ # --- BEGIN: Injected by Copier ---
44
+ import dynadoc as ddoc
45
+ import frigid as immut
46
+ # --- END: Injected by Copier ---
44
47
 
45
48
  # --- BEGIN: Injected by Copier ---
49
+ from absence import Absential, absent, is_absent
46
50
  # --- END: Injected by Copier ---
@@ -30,8 +30,3 @@ PositionalArguments: __.typx.TypeAlias = __.cabc.Sequence[ __.typx.Any ]
30
30
 
31
31
 
32
32
  package_name = __name__.split( '.', maxsplit = 1 )[ 0 ]
33
-
34
-
35
- def is_public_identifier( name: str ) -> bool:
36
- ''' Is Python identifier public? '''
37
- return not name.startswith( '_' )
@@ -37,7 +37,7 @@ from . import exceptions
37
37
  # --- END: Injected by Copier ---
38
38
 
39
39
 
40
- __version__ = '2.0'
40
+ __version__ = '3.1'
41
41
 
42
42
 
43
43
  __.immut.finalize_module( __name__, recursive = True )
@@ -0,0 +1,201 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Management of bytes array decoding via trial character sets. '''
22
+
23
+
24
+ from . import __
25
+ from . import core as _core
26
+ from . import exceptions as _exceptions
27
+ from . import nomina as _nomina
28
+
29
+ from .core import ( # isort: skip
30
+ BEHAVIORS_DEFAULT as _BEHAVIORS_DEFAULT,
31
+ BehaviorTristate as _BehaviorTristate,
32
+ Behaviors as _Behaviors,
33
+ CharsetResult as _CharsetResult,
34
+ CodecSpecifiers as _CodecSpecifiers,
35
+ )
36
+
37
+
38
+ def attempt_decodes( # noqa: PLR0913
39
+ content: _nomina.Content, /, *,
40
+ behaviors: _Behaviors = _BEHAVIORS_DEFAULT,
41
+ inference: __.Absential[ str ] = __.absent,
42
+ supplement: __.Absential[ str ] = __.absent,
43
+ location: __.Absential[ _nomina.Location ] = __.absent,
44
+ validator: __.Absential[
45
+ __.cabc.Callable[ [ str, _CharsetResult ], None ]
46
+ ] = __.absent,
47
+ ) -> tuple[ str, _CharsetResult ]:
48
+ ''' Attempts to decode content with various character sets.
49
+
50
+ Will try character sets in the order specified by the trial codecs
51
+ listed on the behaviors object.
52
+ '''
53
+ confidence = _core.confidence_from_bytes_quantity(
54
+ content, behaviors = behaviors )
55
+ trial_codecs = _collect_trial_codecs(
56
+ content,
57
+ behaviors = behaviors,
58
+ inference = inference,
59
+ supplement = supplement )
60
+ trials: set[ str ] = set( )
61
+ for trial_codec in trial_codecs:
62
+ try: text = content.decode(
63
+ trial_codec, errors = behaviors.on_decode_error )
64
+ except UnicodeDecodeError: continue
65
+ finally: trials.add( trial_codec )
66
+ result = _CharsetResult(
67
+ charset = normalize_charset_for_content( content, trial_codec ),
68
+ confidence = confidence )
69
+ if not __.is_absent( validator ):
70
+ try: validator( text, result )
71
+ except _exceptions.TextInvalidity: continue
72
+ return text, result
73
+ raise _exceptions.ContentDecodeFailure(
74
+ charset = tuple( trials ), location = location )
75
+
76
+
77
+ def discover_os_charset_default( ) -> str:
78
+ ''' Discovers default character set encoding from operating system. '''
79
+ discoverer = getattr(
80
+ __.locale, 'getencoding', __.sys.getfilesystemencoding )
81
+ return normalize_charset( discoverer( ) )
82
+
83
+
84
+ def normalize_charset( charset: str, bom_cognizant: bool = False ) -> str:
85
+ ''' Normalizes character set encoding names. '''
86
+ charset_ = __.codecs.lookup( charset ).name
87
+ if bom_cognizant and charset_ == 'utf-8': return 'utf-8-sig'
88
+ return charset_
89
+
90
+
91
+ def normalize_charset_for_content(
92
+ content: _nomina.Content, charset: str
93
+ ) -> str:
94
+ ''' Normalizes charset reporting based on byte-order mark provenance. '''
95
+ charset_ = normalize_charset( charset )
96
+ bom_charset = _discover_utf_bom_charset( content )
97
+ if charset_ in ( 'utf-8', 'utf-8-sig' ):
98
+ if bom_charset == 'utf-8-sig': return 'utf-8-sig'
99
+ return 'utf-8'
100
+ for family in ( 'utf-16', 'utf-32' ):
101
+ if not charset_.startswith( family ): continue
102
+ if bom_charset in ( f"{family}-le", f"{family}-be" ):
103
+ return family
104
+ return charset_
105
+ return charset_
106
+
107
+
108
+ def trial_decode_as_confident( # noqa: PLR0913
109
+ content: _nomina.Content, /, *,
110
+ behaviors: _Behaviors = _BEHAVIORS_DEFAULT,
111
+ inference: __.Absential[ str ] = __.absent,
112
+ confidence: float = 0.0,
113
+ supplement: __.Absential[ str ] = __.absent,
114
+ location: __.Absential[ _nomina.Location ] = __.absent,
115
+ ) -> _CharsetResult:
116
+ ''' Performs trial decode of content.
117
+
118
+ Considers desired trial decode behavior and detection confidence.
119
+ '''
120
+ nomargs: __.NominativeArguments = dict(
121
+ behaviors = behaviors,
122
+ inference = inference,
123
+ supplement = supplement,
124
+ location = location )
125
+ should_decode = False
126
+ match behaviors.trial_decode:
127
+ case _BehaviorTristate.Always: should_decode = True
128
+ case _BehaviorTristate.AsNeeded:
129
+ should_decode = confidence < behaviors.trial_decode_confidence
130
+ case _BehaviorTristate.Never: pass
131
+ if should_decode:
132
+ _, result = attempt_decodes( content, **nomargs )
133
+ return result
134
+ if __.is_absent( inference ):
135
+ raise _exceptions.CharsetDetectFailure( location = location )
136
+ return _CharsetResult( charset = inference, confidence = confidence )
137
+
138
+
139
+ def _collect_trial_codecs(
140
+ content: _nomina.Content, /, *,
141
+ behaviors: _Behaviors,
142
+ inference: __.Absential[ str ],
143
+ supplement: __.Absential[ str ],
144
+ ) -> tuple[ str, ... ]:
145
+ codecs: list[ str ] = [ ] # No set needed; this candidate list is tiny.
146
+ for codec in behaviors.trial_codecs:
147
+ charset = _resolve_trial_codec(
148
+ codec, inference = inference, supplement = supplement )
149
+ if __.is_absent( charset ): continue
150
+ charset = normalize_charset( charset )
151
+ if _is_ambiguous_utf_trial( content, charset, behaviors ): continue
152
+ if behaviors.remove_bom and charset == 'utf-8': charset = 'utf-8-sig'
153
+ if charset in codecs: continue
154
+ codecs.append( charset )
155
+ return tuple( codecs )
156
+
157
+
158
+ def _discover_utf_bom_charset(
159
+ content: _nomina.Content
160
+ ) -> __.typx.Optional[ str ]:
161
+ # Must check UTF-32 markers first, since they prefix-match UTF-16 markers.
162
+ if content.startswith( __.codecs.BOM_UTF32_LE ): return 'utf-32-le'
163
+ if content.startswith( __.codecs.BOM_UTF32_BE ): return 'utf-32-be'
164
+ if content.startswith( __.codecs.BOM_UTF8 ): return 'utf-8-sig'
165
+ if content.startswith( __.codecs.BOM_UTF16_LE ): return 'utf-16-le'
166
+ if content.startswith( __.codecs.BOM_UTF16_BE ): return 'utf-16-be'
167
+ return None
168
+
169
+
170
+ def _is_ambiguous_utf_trial(
171
+ content: _nomina.Content, charset: str, behaviors: _Behaviors
172
+ ) -> bool:
173
+ if not behaviors.utf_16_32_requires_byte_order: return False
174
+ match charset:
175
+ case 'utf-16':
176
+ bom_charset = _discover_utf_bom_charset( content )
177
+ return bom_charset not in ( 'utf-16-le', 'utf-16-be' )
178
+ case 'utf-32':
179
+ bom_charset = _discover_utf_bom_charset( content )
180
+ return bom_charset not in ( 'utf-32-le', 'utf-32-be' )
181
+ case _: return False
182
+
183
+
184
+ def _resolve_trial_codec(
185
+ codec: __.typx.Any, /, *,
186
+ inference: __.Absential[ str ],
187
+ supplement: __.Absential[ str ],
188
+ ) -> __.Absential[ str ]:
189
+ charset: __.Absential[ str ] = __.absent
190
+ match codec:
191
+ case _CodecSpecifiers.FromInference:
192
+ if not __.is_absent( inference ): charset = inference
193
+ case _CodecSpecifiers.OsDefault:
194
+ charset = discover_os_charset_default( )
195
+ case _CodecSpecifiers.PythonDefault:
196
+ charset = __.locale.getpreferredencoding( )
197
+ case _CodecSpecifiers.UserSupplement:
198
+ if not __.is_absent( supplement ): charset = supplement
199
+ case str( ): charset = codec
200
+ case _: pass
201
+ return charset
@@ -22,15 +22,10 @@
22
22
 
23
23
 
24
24
  from . import __
25
+ from . import exceptions as _exceptions
25
26
  from . import nomina as _nomina
26
27
 
27
28
 
28
- _STANDARD_CHARSET_PROMOTIONS = (
29
- ( 'ascii', 'utf-8-sig' ),
30
- ( 'utf-8', 'utf-8-sig' ),
31
- )
32
-
33
-
34
29
  CHARSET_DEFAULT = 'utf-8'
35
30
  MIMETYPE_DEFAULT = 'application/octet-stream'
36
31
 
@@ -68,9 +63,9 @@ class Behaviors( __.immut.DataclassObject ):
68
63
  ''' Minimum number of bytes for full detection confidence. ''' ),
69
64
  ] = 1024
70
65
  charset_detect: __.typx.Annotated[
71
- BehaviorTristate,
72
- __.ddoc.Doc( ''' When to detect charset from content. ''' ),
73
- ] = BehaviorTristate.AsNeeded
66
+ bool,
67
+ __.ddoc.Doc( ''' Whether to detect charset from content. ''' ),
68
+ ] = True
74
69
  charset_detectors_order: __.typx.Annotated[
75
70
  __.cabc.Sequence[ str ],
76
71
  __.ddoc.Doc(
@@ -80,20 +75,10 @@ class Behaviors( __.immut.DataclassObject ):
80
75
  DetectFailureActions,
81
76
  __.ddoc.Doc( ''' Action to take on charset detection failure. ''' ),
82
77
  ] = DetectFailureActions.Default
83
- charset_promotions: __.typx.Annotated[
84
- __.cabc.Mapping[ str, str ],
85
- __.ddoc.Doc(
86
- ''' Which detected charsets to promote to other charsets.
87
-
88
- E.g., 7-bit ASCII to UTF-8.
89
- ''' ),
90
- ] = __.dcls.field(
91
- default_factory = (
92
- lambda: __.immut.Dictionary( _STANDARD_CHARSET_PROMOTIONS ) ) )
93
78
  mimetype_detect: __.typx.Annotated[
94
- BehaviorTristate,
95
- __.ddoc.Doc( ''' When to detect MIME type from content. ''' ),
96
- ] = BehaviorTristate.AsNeeded
79
+ bool,
80
+ __.ddoc.Doc( ''' Whether to detect MIME type from content. ''' ),
81
+ ] = True
97
82
  mimetype_detectors_order: __.typx.Annotated[
98
83
  __.cabc.Sequence[ str ],
99
84
  __.ddoc.Doc(
@@ -114,6 +99,9 @@ class Behaviors( __.immut.DataclassObject ):
114
99
  'codecs' module.
115
100
  ''' ),
116
101
  ] = 'strict'
102
+ remove_bom: __.typx.Annotated[
103
+ bool, __.ddoc.Doc( ''' Remove byte-ordering mark? ''' )
104
+ ] = True
117
105
  text_validate: __.typx.Annotated[
118
106
  BehaviorTristate,
119
107
  __.ddoc.Doc( ''' When to validate text. ''' ),
@@ -125,7 +113,13 @@ class Behaviors( __.immut.DataclassObject ):
125
113
  trial_codecs: __.typx.Annotated[
126
114
  __.cabc.Sequence[ str | CodecSpecifiers ],
127
115
  __.ddoc.Doc( ''' Sequence of codec names or specifiers. ''' ),
128
- ] = ( CodecSpecifiers.FromInference, CodecSpecifiers.UserSupplement )
116
+ ] = (
117
+ CodecSpecifiers.UserSupplement,
118
+ 'utf-8',
119
+ CodecSpecifiers.FromInference,
120
+ CodecSpecifiers.OsDefault,
121
+ CodecSpecifiers.PythonDefault,
122
+ )
129
123
  trial_decode: __.typx.Annotated[
130
124
  BehaviorTristate,
131
125
  __.ddoc.Doc(
@@ -134,6 +128,23 @@ class Behaviors( __.immut.DataclassObject ):
134
128
  trial_decode_confidence: __.typx.Annotated[
135
129
  float, __.ddoc.Doc( ''' Minimum confidence to skip trial decode. ''')
136
130
  ] = 0.80
131
+ utf_16_32_requires_byte_order: __.typx.Annotated[
132
+ bool,
133
+ __.ddoc.Doc(
134
+ ''' Require explicit byte order for BOM-less generic UTF-16/32? '''
135
+ ),
136
+ ] = False
137
+
138
+ def __post_init__( self ) -> None:
139
+ if not isinstance( self.charset_detect, bool ):
140
+ raise _exceptions.BehaviorsInvalidity(
141
+ 'charset_detect', 'a boolean' )
142
+ if not isinstance( self.mimetype_detect, bool ):
143
+ raise _exceptions.BehaviorsInvalidity(
144
+ 'mimetype_detect', 'a boolean' )
145
+ if not isinstance( self.utf_16_32_requires_byte_order, bool ):
146
+ raise _exceptions.BehaviorsInvalidity(
147
+ 'utf_16_32_requires_byte_order', 'a boolean' )
137
148
 
138
149
 
139
150
  BehaviorsArgument: __.typx.TypeAlias = __.typx.Annotated[