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: