Mercurial > hgrepos > Python > libs > ConfigMix
comparison configmix/config.py @ 530:28191d61b042
FIX: Handle non-cacheable interpolations properly.
Currently all non-default namespaces prohibit interpolation caching.
| author | Franz Glasner <f.glasner@feldmann-mg.com> |
|---|---|
| date | Mon, 20 Dec 2021 14:33:54 +0100 |
| parents | 9976ff66c439 |
| children | be740ed67d16 |
comparison
equal
deleted
inserted
replaced
| 529:9976ff66c439 | 530:28191d61b042 |
|---|---|
| 629 if default is _MARKER: | 629 if default is _MARKER: |
| 630 raise | 630 raise |
| 631 else: | 631 else: |
| 632 return default | 632 return default |
| 633 | 633 |
| 634 def _getvar_s_with_cache_info(self, varname): | |
| 635 """Internal variant of :meth:`~.getvar_s` that returns some information | |
| 636 whether caching of interpolated values is allowed | |
| 637 | |
| 638 Caching is currently not allowed when namespaces are used. | |
| 639 | |
| 640 Currently used by :meth:`~.interpolate_variables`. | |
| 641 | |
| 642 """ | |
| 643 varns, varname = self._split_ns(varname) | |
| 644 if not varns: | |
| 645 cacheable = True | |
| 646 if varname: | |
| 647 varnameparts = tuple([unquote(vp) | |
| 648 for vp in varname.split(_HIER_SEPARATOR)]) | |
| 649 else: | |
| 650 varnameparts = tuple() | |
| 651 else: | |
| 652 cacheable = False | |
| 653 varnameparts = (varname,) | |
| 654 obj = self.getvarl(*varnameparts, namespace=varns) | |
| 655 return (self.substitute_variables_in_obj(obj), cacheable) | |
| 656 | |
| 634 def getfirstvar_s(self, *varnames, **kwds): | 657 def getfirstvar_s(self, *varnames, **kwds): |
| 635 """A variant of :meth:`~.getvar_s` that returns the first found | 658 """A variant of :meth:`~.getvar_s` that returns the first found |
| 636 variable in the list of given variables in `varnames`. | 659 variable in the list of given variables in `varnames`. |
| 637 | 660 |
| 638 """ | 661 """ |
| 774 start = s.find(_STARTTOK, 0) | 797 start = s.find(_STARTTOK, 0) |
| 775 if start < 0: | 798 if start < 0: |
| 776 return s | 799 return s |
| 777 res = self.__interpolation_cache.get(s, _MARKER) | 800 res = self.__interpolation_cache.get(s, _MARKER) |
| 778 if res is not _MARKER: | 801 if res is not _MARKER: |
| 779 return res | 802 if res is _MISSING: |
| 803 warnings.warn("Cannot interpolate variables in string " | |
| 804 "%r (cached)" % (s, ), | |
| 805 UserWarning, | |
| 806 stacklevel=1) | |
| 807 raise KeyError("Cannot interpolate variables in string " | |
| 808 "%r (cached)" % (s, )) | |
| 809 else: | |
| 810 return res | |
| 780 len_s = len(s) | 811 len_s = len(s) |
| 781 res = [] | 812 res = [] |
| 782 res_append = res.append | 813 res_append = res.append |
| 783 rest = 0 | 814 rest = 0 |
| 815 use_cache = True | |
| 784 while start != -1: | 816 while start != -1: |
| 785 res_append(s[rest:start]) | 817 res_append(s[rest:start]) |
| 786 end = s.find(_ENDTOK, start) | 818 end = s.find(_ENDTOK, start) |
| 787 if end < 0: | 819 if end < 0: |
| 788 rest = start | 820 rest = start |
| 789 break | 821 break |
| 790 varname, filters = self._split_filters( | 822 varname, filters = self._split_filters( |
| 791 s[start+2:end]) | 823 s[start+2:end]) |
| 792 try: | 824 try: |
| 793 varvalue = self.getvar_s(varname) | 825 varvalue, cacheable = self._getvar_s_with_cache_info(varname) |
| 794 except KeyError: | 826 except KeyError: |
| 827 cacheable = True | |
| 795 if NONE_FILTER in filters: | 828 if NONE_FILTER in filters: |
| 796 varvalue = None | 829 varvalue = None |
| 797 elif EMPTY_FILTER in filters: | 830 elif EMPTY_FILTER in filters: |
| 798 varvalue = _EMPTY_STR | 831 varvalue = _EMPTY_STR |
| 799 else: | 832 else: |
| 800 warnings.warn("Cannot expand variable %r in string " | 833 self.__interpolation_cache[s] = _MISSING |
| 834 warnings.warn("Cannot interpolate variable %r in string " | |
| 801 "%r" % (varname, s, ), | 835 "%r" % (varname, s, ), |
| 802 UserWarning, | 836 UserWarning, |
| 803 stacklevel=1) | 837 stacklevel=1) |
| 804 raise | 838 raise |
| 839 if not cacheable: | |
| 840 use_cache = False | |
| 805 varvalue = self._apply_filters(filters, varvalue) | 841 varvalue = self._apply_filters(filters, varvalue) |
| 806 rest = end + 2 | 842 rest = end + 2 |
| 807 # | 843 # |
| 808 # Dont apply and type conversions to the variable value if | 844 # Dont apply and type conversions to the variable value if |
| 809 # the whole `s` is just one expansion | 845 # the whole `s` is just one expansion |
| 810 # | 846 # |
| 811 if (start == 0) and (rest == len_s): | 847 if (start == 0) and (rest == len_s): |
| 812 self.__interpolation_cache[s] = varvalue | 848 if use_cache: |
| 849 self.__interpolation_cache[s] = varvalue | |
| 813 return varvalue | 850 return varvalue |
| 814 if varvalue is None: | 851 if varvalue is None: |
| 815 pass | 852 pass |
| 816 else: | 853 else: |
| 817 res_append(str_and_u(varvalue)) | 854 res_append(str_and_u(varvalue)) |
| 818 # don't re-evaluate because `self.getvar_s()` expands already | 855 # don't re-evaluate because `self.getvar_s()` expands already |
| 819 start = s.find(_STARTTOK, rest) | 856 start = s.find(_STARTTOK, rest) |
| 820 res_append(s[rest:]) | 857 res_append(s[rest:]) |
| 821 res = _EMPTY_STR.join(res) | 858 res = _EMPTY_STR.join(res) |
| 822 self.__interpolation_cache[s] = res | 859 if use_cache: |
| 860 self.__interpolation_cache[s] = res | |
| 823 return res | 861 return res |
| 824 | 862 |
| 825 def _apply_filters(self, filters, value): | 863 def _apply_filters(self, filters, value): |
| 826 for name in filters: | 864 for name in filters: |
| 827 try: | 865 try: |
