common.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import getpass
  2. import sys
  3. from dataclasses import dataclass
  4. from typing import Any, Sequence, Optional, Dict
  5. from clickhouse_connect import __version__
  6. from clickhouse_connect.driver.exceptions import ProgrammingError
  7. def version():
  8. return __version__.version
  9. def format_error(msg: str) -> str:
  10. max_size = _common_settings['max_error_size'].value
  11. if max_size:
  12. return msg[:max_size]
  13. return msg
  14. @dataclass
  15. class CommonSetting:
  16. name: str
  17. options: Sequence[Any]
  18. default: Any
  19. value: Optional[Any] = None
  20. _common_settings: Dict[str, CommonSetting] = {}
  21. def build_client_name(client_name: str):
  22. product_name = get_setting('product_name')
  23. product_name = product_name.strip() + ' ' if product_name else ''
  24. client_name = client_name.strip() + ' ' if client_name else ''
  25. py_version = sys.version.split(' ', maxsplit=1)[0]
  26. os_user = ''
  27. if get_setting('send_os_user'):
  28. try:
  29. os_user = f'; os_user:{getpass.getuser()}'
  30. except Exception: # pylint: disable=broad-except
  31. pass
  32. return (f'{client_name}{product_name}clickhouse-connect/{version()}' +
  33. f' (lv:py/{py_version}; mode:sync; os:{sys.platform}{os_user})')
  34. def get_setting(name: str):
  35. setting = _common_settings.get(name)
  36. if setting is None:
  37. raise ProgrammingError(f'Unrecognized common setting {name}')
  38. return setting.value if setting.value is not None else setting.default
  39. def set_setting(name: str, value: Any):
  40. setting = _common_settings.get(name)
  41. if setting is None:
  42. raise ProgrammingError(f'Unrecognized common setting {name}')
  43. if setting.options and value not in setting.options:
  44. raise ProgrammingError(f'Unrecognized option {value} for setting {name})')
  45. if value == setting.default:
  46. setting.value = None
  47. else:
  48. setting.value = value
  49. def _init_common(name: str, options: Sequence[Any], default: Any):
  50. _common_settings[name] = CommonSetting(name, options, default)
  51. _init_common('autogenerate_session_id', (True, False), True)
  52. _init_common('dict_parameter_format', ('json', 'map'), 'json')
  53. _init_common('invalid_setting_action', ('send', 'drop', 'error'), 'error')
  54. _init_common('max_connection_age', (), 10 * 60) # Max time in seconds to keep reusing a database TCP connection
  55. _init_common('product_name', (), '') # Product name used as part of client identification for ClickHouse query_log
  56. _init_common('readonly', (0, 1), 0) # Implied "read_only" ClickHouse settings for versions prior to 19.17
  57. _init_common('send_os_user', (True, False), True)
  58. # Use the client protocol version This is needed for DateTime timezone columns but breaks with current version of
  59. # chproxy
  60. _init_common('use_protocol_version', (True, False), True)
  61. _init_common('max_error_size', (), 1024)