cengal.web_tools.detect_browsers_host_device_type.by_http_headers.versions.v_0.by_http_headers

  1#!/usr/bin/env python
  2# coding=utf-8
  3
  4# Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>
  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__all__ = ['UAProf', 'is_wap_browser', 'BrowserViewState', 'browser_view_state', 'ClientDevicePlatform', 
 20           'client_device_platform', 'client_device_platform_version', 'client_device_model', 'client_device_arch', 
 21           'MobileDeviceType', 'mobile_device_type_by_user_agent', 'ClientDeviceType', 'client_device_type', 
 22           'ClientViewType', 'client_view_type']
 23
 24
 25"""
 26Module Docstring
 27Docstrings: http://www.python.org/dev/peps/pep-0257/
 28"""
 29
 30__author__ = "ButenkoMS <gtalk@butenkoms.space>"
 31__copyright__ = "Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>"
 32__credits__ = ["ButenkoMS <gtalk@butenkoms.space>", ]
 33__license__ = "Apache License, Version 2.0"
 34__version__ = "4.4.1"
 35__maintainer__ = "ButenkoMS <gtalk@butenkoms.space>"
 36__email__ = "gtalk@butenkoms.space"
 37# __status__ = "Prototype"
 38__status__ = "Development"
 39# __status__ = "Production"
 40
 41
 42from enum import Enum, IntEnum
 43from typing import Mapping, Optional
 44from cengal.web_tools.detect_browsers_host_device_type.by_http_user_agent import is_mobile_or_tablet_browser
 45
 46
 47UAProf = {
 48    'x-wap-profile'.casefold(),
 49    '19-Profile'.casefold(),
 50    'WAP-Profile'.casefold(),
 51}
 52
 53
 54def is_wap_browser(headers: Mapping) -> bool:
 55    return bool(UAProf.intersection(headers.keys()))
 56
 57
 58class BrowserViewState(str, Enum):
 59    desktop = '?0'
 60    mobile = '?1'
 61    unknown = 'unknown'
 62
 63
 64def browser_view_state(headers: Mapping) -> BrowserViewState:
 65    return BrowserViewState(headers.get('Sec-CH-UA-Mobile'.casefold(), 'unknown'))
 66
 67
 68class ClientDevicePlatform(str, Enum):
 69    unknown = 'unknown'
 70    windows = 'Windows'
 71    macos = 'macOS'
 72    linux = 'Linux'
 73    ios = 'iOS'
 74    chromiumos = 'Chromium OS'
 75    chromeos = 'Chrome OS'
 76    android = 'Android'
 77
 78
 79def client_device_platform(headers: Mapping) -> ClientDevicePlatform:
 80    return ClientDevicePlatform(headers.get('Sec-CH-UA-Platform'.casefold(), 'unknown'))
 81
 82
 83def client_device_platform_version(headers: Mapping) -> Optional[str]:
 84    return headers.get('Sec-CH-UA-Platform-Version'.casefold(), None)
 85
 86
 87def client_device_model(headers: Mapping) -> Optional[str]:
 88    return headers.get('Sec-CH-UA-Model'.casefold(), None)
 89
 90
 91def client_device_arch(headers: Mapping) -> Optional[str]:
 92    return headers.get('Sec-CH-UA-Arch'.casefold(), None)
 93
 94
 95class MobileDeviceType(str, Enum):
 96    unknown = 'unknown'
 97    mobile = 'mobile'
 98    tablet = 'tablet'
 99
100
101def mobile_device_type_by_user_agent(headers: Mapping) -> MobileDeviceType:
102    mobile, tablet = is_mobile_or_tablet_browser(headers.get('User-Agent'.casefold(), ''))
103    if tablet:
104        return MobileDeviceType.tablet
105    elif mobile:
106        return MobileDeviceType.mobile
107    else:
108        return MobileDeviceType.unknown
109
110
111class ClientDeviceType(str, Enum):
112    desktop = 'desktop'
113    laptop = 'laptop'
114    tablet = 'tablet'
115    mobile = 'mobile'
116
117
118def client_device_type(headers: Mapping) -> ClientDeviceType:
119    if is_wap_browser(headers):
120        return ClientDeviceType.mobile
121    else:
122        cdp: ClientDevicePlatform = client_device_platform(headers)
123        if ClientDevicePlatform.unknown == cdp:
124            mdt: MobileDeviceType = mobile_device_type_by_user_agent(headers)
125            if MobileDeviceType.tablet == mdt:
126                return ClientDeviceType.tablet
127            elif MobileDeviceType.mobile == mdt:
128                return ClientDeviceType.mobile
129            else:
130                return ClientDeviceType.desktop
131        elif cdp in {ClientDevicePlatform.ios, ClientDevicePlatform.android}:
132            mdt: MobileDeviceType = mobile_device_type_by_user_agent(headers)
133            if MobileDeviceType.tablet == mdt:
134                return ClientDeviceType.tablet
135            else:
136                return ClientDeviceType.mobile
137        else:
138            return ClientDeviceType.desktop
139
140
141class ClientViewType(str, Enum):
142    desktop = 'desktop'
143    laptop = 'laptop'
144    tablet = 'tablet'
145    mobile = 'mobile'
146
147
148def client_view_type(headers: Mapping) -> ClientViewType:
149    bvs: BrowserViewState = browser_view_state(headers)
150    if BrowserViewState.desktop == bvs:
151        return ClientViewType.desktop
152    elif BrowserViewState.mobile == bvs:
153        mdt: MobileDeviceType = mobile_device_type_by_user_agent(headers)
154        if MobileDeviceType.tablet == mdt:
155            return ClientViewType.tablet
156        else:
157            return ClientViewType.mobile
158    elif BrowserViewState.unknown == bvs:
159        if is_wap_browser(headers):
160            return ClientDeviceType.mobile
161        else:
162            mdt: MobileDeviceType = mobile_device_type_by_user_agent(headers)
163            if MobileDeviceType.tablet == mdt:
164                return ClientViewType.tablet
165            elif MobileDeviceType.mobile == mdt:
166                return ClientViewType.mobile
167            else:
168                return ClientViewType.desktop
169    else:
170        raise ValueError(f'Unknown BrowserViewState: {bvs}')
UAProf = {'19-profile', 'wap-profile', 'x-wap-profile'}
def is_wap_browser(headers: Mapping) -> bool:
55def is_wap_browser(headers: Mapping) -> bool:
56    return bool(UAProf.intersection(headers.keys()))
class BrowserViewState(builtins.str, enum.Enum):
59class BrowserViewState(str, Enum):
60    desktop = '?0'
61    mobile = '?1'
62    unknown = 'unknown'

An enumeration.

desktop = <BrowserViewState.desktop: '?0'>
mobile = <BrowserViewState.mobile: '?1'>
unknown = <BrowserViewState.unknown: 'unknown'>
Inherited Members
enum.Enum
name
value
builtins.str
encode
replace
split
rsplit
join
capitalize
casefold
title
center
count
expandtabs
find
partition
index
ljust
lower
lstrip
rfind
rindex
rjust
rstrip
rpartition
splitlines
strip
swapcase
translate
upper
startswith
endswith
isascii
islower
isupper
istitle
isspace
isdecimal
isdigit
isnumeric
isalpha
isalnum
isidentifier
isprintable
zfill
format
format_map
maketrans
def browser_view_state( headers: Mapping) -> BrowserViewState:
65def browser_view_state(headers: Mapping) -> BrowserViewState:
66    return BrowserViewState(headers.get('Sec-CH-UA-Mobile'.casefold(), 'unknown'))
class ClientDevicePlatform(builtins.str, enum.Enum):
69class ClientDevicePlatform(str, Enum):
70    unknown = 'unknown'
71    windows = 'Windows'
72    macos = 'macOS'
73    linux = 'Linux'
74    ios = 'iOS'
75    chromiumos = 'Chromium OS'
76    chromeos = 'Chrome OS'
77    android = 'Android'

An enumeration.

unknown = <ClientDevicePlatform.unknown: 'unknown'>
windows = <ClientDevicePlatform.windows: 'Windows'>
macos = <ClientDevicePlatform.macos: 'macOS'>
linux = <ClientDevicePlatform.linux: 'Linux'>
ios = <ClientDevicePlatform.ios: 'iOS'>
chromiumos = <ClientDevicePlatform.chromiumos: 'Chromium OS'>
chromeos = <ClientDevicePlatform.chromeos: 'Chrome OS'>
android = <ClientDevicePlatform.android: 'Android'>
Inherited Members
enum.Enum
name
value
builtins.str
encode
replace
split
rsplit
join
capitalize
casefold
title
center
count
expandtabs
find
partition
index
ljust
lower
lstrip
rfind
rindex
rjust
rstrip
rpartition
splitlines
strip
swapcase
translate
upper
startswith
endswith
isascii
islower
isupper
istitle
isspace
isdecimal
isdigit
isnumeric
isalpha
isalnum
isidentifier
isprintable
zfill
format
format_map
maketrans
def client_device_platform( headers: Mapping) -> ClientDevicePlatform:
80def client_device_platform(headers: Mapping) -> ClientDevicePlatform:
81    return ClientDevicePlatform(headers.get('Sec-CH-UA-Platform'.casefold(), 'unknown'))
def client_device_platform_version(headers: Mapping) -> Union[str, NoneType]:
84def client_device_platform_version(headers: Mapping) -> Optional[str]:
85    return headers.get('Sec-CH-UA-Platform-Version'.casefold(), None)
def client_device_model(headers: Mapping) -> Union[str, NoneType]:
88def client_device_model(headers: Mapping) -> Optional[str]:
89    return headers.get('Sec-CH-UA-Model'.casefold(), None)
def client_device_arch(headers: Mapping) -> Union[str, NoneType]:
92def client_device_arch(headers: Mapping) -> Optional[str]:
93    return headers.get('Sec-CH-UA-Arch'.casefold(), None)
class MobileDeviceType(builtins.str, enum.Enum):
96class MobileDeviceType(str, Enum):
97    unknown = 'unknown'
98    mobile = 'mobile'
99    tablet = 'tablet'

An enumeration.

unknown = <MobileDeviceType.unknown: 'unknown'>
mobile = <MobileDeviceType.mobile: 'mobile'>
tablet = <MobileDeviceType.tablet: 'tablet'>
Inherited Members
enum.Enum
name
value
builtins.str
encode
replace
split
rsplit
join
capitalize
casefold
title
center
count
expandtabs
find
partition
index
ljust
lower
lstrip
rfind
rindex
rjust
rstrip
rpartition
splitlines
strip
swapcase
translate
upper
startswith
endswith
isascii
islower
isupper
istitle
isspace
isdecimal
isdigit
isnumeric
isalpha
isalnum
isidentifier
isprintable
zfill
format
format_map
maketrans
def mobile_device_type_by_user_agent( headers: Mapping) -> MobileDeviceType:
102def mobile_device_type_by_user_agent(headers: Mapping) -> MobileDeviceType:
103    mobile, tablet = is_mobile_or_tablet_browser(headers.get('User-Agent'.casefold(), ''))
104    if tablet:
105        return MobileDeviceType.tablet
106    elif mobile:
107        return MobileDeviceType.mobile
108    else:
109        return MobileDeviceType.unknown
class ClientDeviceType(builtins.str, enum.Enum):
112class ClientDeviceType(str, Enum):
113    desktop = 'desktop'
114    laptop = 'laptop'
115    tablet = 'tablet'
116    mobile = 'mobile'

An enumeration.

desktop = <ClientDeviceType.desktop: 'desktop'>
laptop = <ClientDeviceType.laptop: 'laptop'>
tablet = <ClientDeviceType.tablet: 'tablet'>
mobile = <ClientDeviceType.mobile: 'mobile'>
Inherited Members
enum.Enum
name
value
builtins.str
encode
replace
split
rsplit
join
capitalize
casefold
title
center
count
expandtabs
find
partition
index
ljust
lower
lstrip
rfind
rindex
rjust
rstrip
rpartition
splitlines
strip
swapcase
translate
upper
startswith
endswith
isascii
islower
isupper
istitle
isspace
isdecimal
isdigit
isnumeric
isalpha
isalnum
isidentifier
isprintable
zfill
format
format_map
maketrans
def client_device_type( headers: Mapping) -> ClientDeviceType:
119def client_device_type(headers: Mapping) -> ClientDeviceType:
120    if is_wap_browser(headers):
121        return ClientDeviceType.mobile
122    else:
123        cdp: ClientDevicePlatform = client_device_platform(headers)
124        if ClientDevicePlatform.unknown == cdp:
125            mdt: MobileDeviceType = mobile_device_type_by_user_agent(headers)
126            if MobileDeviceType.tablet == mdt:
127                return ClientDeviceType.tablet
128            elif MobileDeviceType.mobile == mdt:
129                return ClientDeviceType.mobile
130            else:
131                return ClientDeviceType.desktop
132        elif cdp in {ClientDevicePlatform.ios, ClientDevicePlatform.android}:
133            mdt: MobileDeviceType = mobile_device_type_by_user_agent(headers)
134            if MobileDeviceType.tablet == mdt:
135                return ClientDeviceType.tablet
136            else:
137                return ClientDeviceType.mobile
138        else:
139            return ClientDeviceType.desktop
class ClientViewType(builtins.str, enum.Enum):
142class ClientViewType(str, Enum):
143    desktop = 'desktop'
144    laptop = 'laptop'
145    tablet = 'tablet'
146    mobile = 'mobile'

An enumeration.

desktop = <ClientViewType.desktop: 'desktop'>
laptop = <ClientViewType.laptop: 'laptop'>
tablet = <ClientViewType.tablet: 'tablet'>
mobile = <ClientViewType.mobile: 'mobile'>
Inherited Members
enum.Enum
name
value
builtins.str
encode
replace
split
rsplit
join
capitalize
casefold
title
center
count
expandtabs
find
partition
index
ljust
lower
lstrip
rfind
rindex
rjust
rstrip
rpartition
splitlines
strip
swapcase
translate
upper
startswith
endswith
isascii
islower
isupper
istitle
isspace
isdecimal
isdigit
isnumeric
isalpha
isalnum
isidentifier
isprintable
zfill
format
format_map
maketrans
def client_view_type( headers: Mapping) -> ClientViewType:
149def client_view_type(headers: Mapping) -> ClientViewType:
150    bvs: BrowserViewState = browser_view_state(headers)
151    if BrowserViewState.desktop == bvs:
152        return ClientViewType.desktop
153    elif BrowserViewState.mobile == bvs:
154        mdt: MobileDeviceType = mobile_device_type_by_user_agent(headers)
155        if MobileDeviceType.tablet == mdt:
156            return ClientViewType.tablet
157        else:
158            return ClientViewType.mobile
159    elif BrowserViewState.unknown == bvs:
160        if is_wap_browser(headers):
161            return ClientDeviceType.mobile
162        else:
163            mdt: MobileDeviceType = mobile_device_type_by_user_agent(headers)
164            if MobileDeviceType.tablet == mdt:
165                return ClientViewType.tablet
166            elif MobileDeviceType.mobile == mdt:
167                return ClientViewType.mobile
168            else:
169                return ClientViewType.desktop
170    else:
171        raise ValueError(f'Unknown BrowserViewState: {bvs}')