Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiline blocks and inline commets on profiles #16329

Closed
Closed
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
39 changes: 37 additions & 2 deletions conans/client/profile_loader.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import platform
import re
from collections import OrderedDict, defaultdict

from jinja2 import Environment, FileSystemLoader
Expand All @@ -16,6 +17,7 @@
from conans.model.recipe_ref import RecipeReference
from conans.util.config_parser import ConfigParser
from conans.util.files import mkdir, load_user_encoded
from typing import Iterable


def _unquote(text):
Expand Down Expand Up @@ -190,9 +192,42 @@ def valid_path(_profile_path, _profile_name=None):
return profile_path


# TODO: maybe move this logic to an utils class/file/folder
def process_line(line: str) -> str:
"""
Process a single line to handle backslashes and comments
"""
# Remove comments outside of strings
def replacer(match):
string, comment = match.groups()
return string if string else ""
# Match either a string or a comment
pattern = re.compile(r'(\".*?\"|\'.*?\')|(\s+\#.*)')
# Replace comments with empty strings
line = pattern.sub(replacer, line)
return line.rstrip()

def process_lines(lines: Iterable[str]) -> str:
"""
Process lines to handle backslashes for line continuation and remove comments
"""
processed_lines = []
current_line = ""
for line in lines:
line = process_line(line)
# Detect multiline delimiter: line ends with '\' and it is separated at least one blank space
# from the end of the text
if line.endswith("\\") and line[-2].isspace():
current_line += line[:-1]
else:
current_line += line
processed_lines.append(current_line)
current_line = ""
return "\n".join(processed_lines)


# TODO: This class can be removed/simplified now to a function, it reduced to just __init__
class _ProfileParser:

def __init__(self, text):
""" divides the text in 3 items:
- self.includes: List of other profiles to include
Expand All @@ -206,7 +241,7 @@ def __init__(self, text):
if not line or line.startswith("#"):
continue
if line.startswith("["):
self.profile_text = "\n".join(text.splitlines()[counter:])
self.profile_text = process_lines(text.splitlines()[counter:])
break
elif line.startswith("include("):
include = line.split("include(", 1)[1]
Expand Down