1# hgconfig.py - unicode wrapper for Mercurial's ui object 2# 3# Copyright 2019 Yuya Nishihara <yuya@tcha.org> 4# 5# This software may be used and distributed according to the terms of the 6# GNU General Public License version 2 or any later version. 7 8from __future__ import absolute_import 9 10from mercurial import ( 11 encoding, 12 pycompat, 13 ui as uimod, 14) 15 16from ..util import ( 17 hglib, 18) 19 20if hglib.TYPE_CHECKING: 21 from typing import ( 22 List, 23 Text, 24 Tuple, 25 ) 26 27UNSET_DEFAULT = uimod._unset 28 29class HgConfig(object): 30 """Unicode wrapper for Mercurial's ui object 31 32 This provides Qt-like API on top of the ui object. Almost all methods 33 are proxied through RepoAgent. Use these methods unless necessary. 34 35 All config*() getter functions never return None, nor take None as 36 default value. That's because Qt C++ API is strict about data types 37 in general. Use hasConfig() to test if the config value is set. 38 """ 39 40 # Design notes: 41 # - It's probably better to fetch bytes data from ui at once, and cache 42 # the unicode representation in this object. We'll have to be careful 43 # to keep the data sync with the underlying ui object. 44 # - No setter functions are provided right now because we can't propagate 45 # new values to the command process. 46 47 def __init__(self, ui): 48 # type: (uimod.ui) -> None 49 self._ui = ui 50 51 def rawUi(self): 52 # type: () -> uimod.ui 53 return self._ui 54 55 def configBool(self, section, name, default=UNSET_DEFAULT): 56 # type: (Text, Text, bool) -> bool 57 data = self._ui.configbool(_tobytes(section), _tobytes(name), 58 default=default) 59 return bool(data) 60 61 def configInt(self, section, name, default=UNSET_DEFAULT): 62 # type: (Text, Text, int) -> int 63 data = self._ui.configint(_tobytes(section), _tobytes(name), 64 default=default) 65 return int(data) 66 67 def configString(self, section, name, default=UNSET_DEFAULT): 68 # type: (Text, Text, Text) -> Text 69 if default is not UNSET_DEFAULT: 70 default = _tobytes(default) 71 data = self._ui.config(_tobytes(section), _tobytes(name), 72 default=default) 73 if data is None: 74 return '' 75 return _tostr(data) 76 77 def configStringList(self, section, name, default=UNSET_DEFAULT): 78 # type: (Text, Text, List[Text]) -> List[Text] 79 if default is not UNSET_DEFAULT: 80 default = pycompat.maplist(_tobytes, default) 81 data = self._ui.configlist(_tobytes(section), _tobytes(name), 82 default=default) 83 return pycompat.maplist(_tostr, data) 84 85 def configStringItems(self, section): 86 # type: (Text) -> List[Tuple[Text, Text]] 87 """Returns a list of string (key, value) pairs under the specified 88 section""" 89 items = self._ui.configitems(_tobytes(section)) 90 return [(_tostr(k), _tostr(v)) for k, v in items] 91 92 def hasConfig(self, section, name): 93 # type: (Text, Text) -> bool 94 return self._ui.hasconfig(_tobytes(section), _tobytes(name)) 95 96 97if pycompat.ispy3: 98 _tostr = hglib.tounicode 99 _tobytes = hglib.fromunicode 100else: 101 def _tostr(s): 102 # keep ascii string as byte string on Python 2, which is supposedly 103 # faster and safer. 104 if encoding.isasciistr(s): 105 return s 106 return hglib.tounicode(s) 107 108 def _tobytes(s): 109 if not isinstance(s, pycompat.unicode): 110 return s 111 return hglib.fromunicode(s) 112