Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions himl/config_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
from .python_compat import iteritems, primitive_types, PY3
from .remote_state import S3TerraformRemoteStateRetriever

logging.basicConfig()
logging.root.setLevel(logging.INFO)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


Expand Down
5 changes: 4 additions & 1 deletion himl/config_merger.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
from .config_generator import ConfigProcessor
from multiprocessing import Pool, cpu_count
from .filter_rules import FilterRules
logger = logging.getLogger(__name__)

logging.basicConfig()
logging.root.setLevel(logging.INFO)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class Loader(yaml.SafeLoader):
"""
Expand Down
85 changes: 76 additions & 9 deletions himl/interpolation.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,71 @@
# governing permissions and limitations under the License.

import re
from functools import lru_cache

from .inject_env import EnvVarInjector
from .inject_secrets import SecretInjector
from .python_compat import iteritems, string_types, primitive_types

# Pre-compile regex patterns for performance
_INTERPOLATION_PATTERN = re.compile(r'\{\{[^`].*?[^`]\}\}')
_ESCAPED_PATTERN = re.compile(r'\{\{`.*?`\}\}')
_FULL_INTERPOLATION_PATTERN = re.compile(r'^\{\{[^`].*?[^`]\}\}$')
_FULLY_ESCAPED_PATTERN = re.compile(r'^\{\{`.*?`\}\}$')


# Cached internal functions that only handle strings
@lru_cache(maxsize=10000)
def _is_interpolation_cached(value):
"""Internal cached function - only for strings"""
return bool(_INTERPOLATION_PATTERN.search(value)) and not bool(_ESCAPED_PATTERN.search(value))


@lru_cache(maxsize=10000)
def _is_escaped_interpolation_cached(value):
"""Internal cached function - only for strings"""
return bool(_ESCAPED_PATTERN.search(value))


@lru_cache(maxsize=10000)
def _is_fully_escaped_interpolation_cached(value):
"""Internal cached function - only for strings"""
return bool(_FULLY_ESCAPED_PATTERN.match(value))


@lru_cache(maxsize=10000)
def _is_full_interpolation_cached(value):
"""Internal cached function - only for strings"""
return bool(_FULL_INTERPOLATION_PATTERN.match(value)) and not _is_fully_escaped_interpolation_cached(value)


# Public functions with type safety
def is_interpolation(value):
return isinstance(value, string_types) and '{{' in value and '}}' in value \
and not is_escaped_interpolation(value)
"""Optimized interpolation detection with regex and caching"""
if not isinstance(value, string_types):
return False
return _is_interpolation_cached(value)


def is_escaped_interpolation(value):
return isinstance(value, string_types) and '{{`' in value and '`}}' in value
"""Optimized escaped interpolation detection with regex and caching"""
if not isinstance(value, string_types):
return False
return _is_escaped_interpolation_cached(value)


def is_fully_escaped_interpolation(value):
return isinstance(value, string_types) and value.startswith('{{`') and value.endswith('`}}')
"""Optimized fully escaped interpolation detection with regex and caching"""
if not isinstance(value, string_types):
return False
return _is_fully_escaped_interpolation_cached(value)


def is_full_interpolation(value):
return is_interpolation(value) and value.startswith('{{') and value.endswith('}}') \
and not is_fully_escaped_interpolation(value)
"""Optimized full interpolation detection with regex and caching"""
if not isinstance(value, string_types):
return False
return _is_full_interpolation_cached(value)


def remove_white_spaces(value):
Expand Down Expand Up @@ -201,6 +244,8 @@ class FromDictInjector(object):

def __init__(self):
self.results = {}
# Cache for parsed data structures to avoid redundant parsing
self._parse_cache = {}

def resolve(self, line, data):
"""
Expand All @@ -209,8 +254,16 @@ def resolve(self, line, data):
:return: dev
"""

self.parse_leaves(data, "")
for key, value in iteritems(self.results):
# Use cached results if available, otherwise parse and cache
data_id = id(data)
if data_id not in self._parse_cache:
self._parse_cache[data_id] = {}
self._parse_leaves_cached(data, "", self._parse_cache[data_id])

# Use cached results instead of rebuilding
cached_results = self._parse_cache[data_id]

for key, value in iteritems(cached_results):
placeholder = "{{" + key + "}}"
if placeholder not in line:
continue
Expand All @@ -220,7 +273,22 @@ def resolve(self, line, data):
line = line.replace(placeholder, value)
return line

def _parse_leaves_cached(self, data, partial_key, cache_dict):
"""Optimized version that populates cache dictionary directly"""
if isinstance(data, primitive_types):
cache_dict[partial_key] = data
return
if isinstance(data, dict):
for key in data:
value = data[key]
new_key = partial_key
if new_key:
new_key += "."
new_key += key
self._parse_leaves_cached(value, new_key, cache_dict)

def parse_leaves(self, data, partial_key):
"""Legacy method maintained for compatibility"""
if isinstance(data, primitive_types):
self.results[partial_key] = data
return
Expand Down Expand Up @@ -290,4 +358,3 @@ def get_value_from_escaping(line):
line = line[3:-3]

return line