Source code for code_aster.Utilities.strfunc

# coding=utf-8
# --------------------------------------------------------------------
# Copyright (C) 1991 - 2026 - EDF - www.code-aster.org
# This file is part of code_aster.
#
# code_aster is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# code_aster is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with code_aster.  If not, see <http://www.gnu.org/licenses/>.
# --------------------------------------------------------------------

"""
:py:mod:`strfunc` --- String manipulations utilities
****************************************************

This module defines utilities functions for strings manipulation.
"""

import locale
import os

from .base_utils import force_list

_encoding = None


[docs]def get_encoding(): """Return local encoding""" global _encoding if _encoding is None: try: _encoding = locale.getpreferredencoding() or "ascii" except locale.Error: _encoding = "ascii" return _encoding
[docs]def to_unicode(string): """Try to convert string into a unicode string. Arguments: string (str): String to convert to unicode. Returns: str: Unicode string. """ if type(string) is str: return string elif type(string) is dict: new = {} for k, v in list(string.items()): new[k] = to_unicode(v) return new elif type(string) is list: return [to_unicode(elt) for elt in string] elif type(string) is tuple: return tuple(to_unicode(list(string))) elif type(string) is not str: return string assert type(string) is str, "unsupported object: %s" % string for encoding in ("utf-8", "iso-8859-15", "cp1252"): try: s = str(string, encoding) return s except UnicodeDecodeError: pass return str(string, "utf-8", "replace")
[docs]def from_unicode(ustring, encoding, errors="replace"): """Try to encode a unicode string using encoding. Arguments: ustring (str): Unicode string to encode. encoding (str): Encoding name. errors (str): Behaviour in case of encoding error (see :py:func:`string.encode`). Returns: str: Encoded string. """ try: return ustring.encode(encoding) except UnicodeError: pass return ustring.encode(encoding, errors)
[docs]def convert(content, encoding=None, errors="replace"): """Convert content using encoding or default encoding if *None*. Arguments: content (str/unicode): Text to convert. encoding (str): Encoding name. errors (str): Behaviour in case of encoding error (see :meth:`string.encode`). Returns: str: Encoded string. """ if type(content) is not str: content = str(content) if type(content) == str: content = to_unicode(content) return content
[docs]def ufmt(uformat, *args): """Helper function to format a string by converting all its arguments to unicode""" if type(uformat) is not str: uformat = to_unicode(uformat) if len(args) == 1 and type(args[0]) is dict: arguments = to_unicode(args[0]) else: nargs = [] for arg in args: if type(arg) in (str, str, list, tuple, dict): nargs.append(to_unicode(arg)) elif type(arg) not in (int, int, float): nargs.append(to_unicode(str(arg))) else: nargs.append(arg) arguments = tuple(nargs) try: formatted_string = uformat % arguments except UnicodeDecodeError as err: print(type(uformat), uformat) print(type(arguments), arguments) raise return formatted_string
[docs]def clean_string(chaine): """Supprime tous les caractères non imprimables.""" invalid = "?" txt = [] for char in chaine: if ord(char) != 0: txt.append(char) else: txt.append(invalid) return "".join(txt)
[docs]def cut_long_lines(txt, maxlen, sep=os.linesep, l_separ=(" ", ",", ";", ".", ":")): """Coupe les morceaux de `txt` (isolés avec `sep`) de plus de `maxlen` caractères. On utilise successivement les séparateurs de `l_separ`. """ l_lines = txt.split(sep) newlines = [] for line in l_lines: if len(line) > maxlen: l_sep = list(l_separ) if len(l_sep) == 0: newlines.extend(force_split(line, maxlen)) continue else: line = cut_long_lines(line, maxlen, l_sep[0], l_sep[1:]) line = maximize_lines(line, maxlen, l_sep[0]) newlines.extend(line) else: newlines.append(line) # au plus haut niveau, on assemble le texte if sep == os.linesep: newlines = os.linesep.join(newlines) return newlines
[docs]def maximize_lines(l_fields, maxlen, sep): """Construit des lignes dont la longueur est au plus de `maxlen` caractères. Les champs sont assemblés avec le séparateur `sep`. """ newlines = [] if len(l_fields) == 0: return newlines # ceinture assert max([len(f) for f in l_fields]) <= maxlen, "lignes trop longues : %s" % l_fields while len(l_fields) > 0: cur = [] while len(l_fields) > 0 and len(sep.join(cur + [l_fields[0]])) <= maxlen: cur.append(l_fields.pop(0)) # bretelle assert len(cur) > 0, l_fields newlines.append(sep.join(cur)) newlines = [l for l in newlines if l != ""] return newlines
[docs]def force_split(txt, maxlen): """Force le découpage de la ligne à 'maxlen' caractères.""" l_res = [] while len(txt) > maxlen: l_res.append(txt[:maxlen]) txt = txt[maxlen:] l_res.append(txt) return l_res
[docs]def copy_text_to(text, files): """Print a message into one or more files. Files may be filenames (as string) or file-object. Arguments: text (str): Message to be printed files (str|file, list[str|file]): Filename(s) or file-object(s) """ def _dump(fobj): fobj.write(text) fobj.write(os.linesep) fobj.flush() files = force_list(files) for f_i in files: if isinstance(f_i, str): with open(f_i, "a") as obj: _dump(obj) else: _dump(f_i)
[docs]def _fixed_length(lines, maxlen, align="<"): """Fix lines length at `maxlen`. Arguments: lines (list[str]): List of lines. maxlen (int): Lines length. align (str): One of "<", "^", ">" Returns: list[str]: List of formatted lines. """ fmt = "{{0:{1}{0}s}}".format(maxlen, align) return [fmt.format(line) for line in lines]
[docs]def textbox(text, maxlen=90): """Format a text into a box to be highlighted. Arguments: text (str): Text to be decorated. maxlen (int): Lines length. Returns: str: Decorated text. """ maxlen = maxlen - 6 upleft = chr(0x2554) upright = chr(0x2557) horiz = "=" vert = chr(0x2551) botleft = chr(0x255A) botright = chr(0x255D) head = " " + upleft + horiz * (maxlen + 2) + upright foot = " " + botleft + horiz * (maxlen + 2) + botright fmt = " " + vert + " {0} " + vert lines = ["", head] splitted = cut_long_lines(text, maxlen).splitlines() fixed = _fixed_length(splitted, maxlen) lines.extend([fmt.format(line) for line in fixed]) lines.extend([foot, ""]) return os.linesep.join(lines)
[docs]def center(text, maxlen=90): """Format a text as centered. Arguments: text (str): Text to be centered. maxlen (int): Lines length. Returns: str: Centered text. """ splitted = cut_long_lines(text, maxlen).splitlines() lines = _fixed_length(splitted, maxlen, align="^") return os.linesep.join(lines)