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

re.error: incomplete escape \U at position 2 #40

Open
charlie-dufort opened this issue Oct 16, 2023 · 0 comments
Open

re.error: incomplete escape \U at position 2 #40

charlie-dufort opened this issue Oct 16, 2023 · 0 comments

Comments

@charlie-dufort
Copy link

charlie-dufort commented Oct 16, 2023

Error raised on Windows, especially when executing some code with a dependency to config2py.
Comes from dol.naming.mk_pattern_from_template_and_format_dict.

Example

Executing from config2py import simple_config_getter raises:

---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
Untitled-1.ipynb Cell 5 line 1
----> [1](vscode-notebook-cell:Untitled-1.ipynb?jupyter-notebook#X11sdW50aXRsZWQ%3D?line=0) from config2py import simple_config_getter, get_configs_folder_for_app

File ~\OneDrive - Analog Devices, Inc\Python\OtoSense\config2py\config2py\__init__.py:4
      1 """Tools to read and write configurations from various sources and formats"""
      3 from config2py.s_configparser import ConfigStore, ConfigReader
----> 4 from config2py.tools import (
      5     extract_exports,
      6     get_configs_local_store,
      7     simple_config_getter,
      8     config_getter,
      9     local_configs,
     10     Configs,  # user-customized configs store class (default is TextFiles)
     11     configs,  # user-customized configs store instance (default is local_configs)
     12     # or make configs be more of a default get_configs "chained Mapping"
     13 )
     14 from config2py.base import get_config, user_gettable, sources_chainmap
     15 from config2py.util import (
     16     ask_user_for_input,
     17     get_app_data_folder,
   (...)
     20     parse_assignments_from_py_source,
     21 )

File ~\OneDrive - Analog Devices, Inc\Python\OtoSense\config2py\config2py\tools.py:88
     84     return config_getter
     87 # Make a ready-to-use config getter, using the defaults
---> 88 config_getter = simple_config_getter()
     90 # --------------------------------------------------------------------
     91 # Ready to import instances
     92 #
   (...)
     97 #   Note: Perhaps there's no need for a class.
     98 #   Maybe just a function that returns a store
     99 Configs = TextFiles  # TODO: deprecate

File ~\OneDrive - Analog Devices, Inc\Python\OtoSense\config2py\config2py\tools.py:71, in simple_config_getter(configs_src, first_look_in_env_vars, ask_user_if_key_not_found, config_store_factory)
     52 """Make a simple config getter from a "central" config source specification.
     53 
     54 The purpose of this function is to implement a common pattern of getting configs:
   (...)
     68     and returns the central config store
     69 """
     70 # TODO: Resource validation block. Refactor! And add tool to config2py if not there
---> 71 central_configs = config_store_factory(configs_src)
     72 sources = []
     73 if first_look_in_env_vars:

File ~\OneDrive - Analog Devices, Inc\Python\OtoSense\config2py\config2py\tools.py:24, in get_configs_local_store(config_src)
     16 """Get the local store of configs.
     17 
     18 :param config_src: A specification of the local config store. By default:
   (...)
     21     If it's a string, it's assumed to be an app name, from which to create a folder
     22 """
     23 if os.path.isdir(config_src):
---> 24     return TextFiles(config_src)
     25 elif os.path.isfile(config_src):
     26     # TODO: Not tested
     27     # TODO: Make this open-closed plug-in via routing argument
     28     _, extension = os.path.splitext(config_src)

File ~\OneDrive - Analog Devices, Inc\Python\OtoSense\dol\dol\paths.py:688, in mk_relative_path_store.<locals>.__init__(self, *args, **kwargs)
    686 @wraps(store_cls.__init__)
    687 def __init__(self, *args, **kwargs):
--> 688     Store.__init__(self, store=store_cls(*args, **kwargs))
    689     prefix = recursive_get_attr(self.store, prefix_attr, '')
    690     setattr(
    691         self, prefix_attr, prefix
    692     )

File ~\OneDrive - Analog Devices, Inc\Python\OtoSense\dol\dol\filesys.py:215, in FileSysCollection.__init__(self, rootdir, subpath, pattern_for_field, max_levels, include_hidden, assert_rootdir_existence)
    213 self.rootdir = ensure_slash_suffix(rootdir)
    214 self.subpath = subpath
--> 215 self._key_pattern = mk_pattern_from_template_and_format_dict(
    216     os.path.join(rootdir, subpath), pattern_for_field
    217 )
    218 self._max_levels = max_levels
    219 self.include_hidden = include_hidden

File ~\OneDrive - Analog Devices, Inc\Python\OtoSense\dol\dol\naming.py:325, in mk_pattern_from_template_and_format_dict(template, format_dict, sep)
    323 format_dict = mk_format_mapping_dict(format_dict, fields, sep=sep)
    324 named_capture_patterns = mk_named_capture_patterns(format_dict)
--> 325 return re.compile(template_to_pattern(named_capture_patterns, template))

File c:\Users\cdufort\AppData\Local\Programs\Python\Python311\Lib\re\__init__.py:227, in compile(pattern, flags)
    225 def compile(pattern, flags=0):
    226     "Compile a regular expression pattern, returning a Pattern object."
--> 227     return _compile(pattern, flags)

File c:\Users\cdufort\AppData\Local\Programs\Python\Python311\Lib\re\__init__.py:294, in _compile(pattern, flags)
    288     import warnings
    289     warnings.warn("The re.TEMPLATE/re.T flag is deprecated "
    290               "as it is an undocumented flag "
    291               "without an obvious purpose. "
    292               "Don't use it.",
    293               DeprecationWarning)
--> 294 p = _compiler.compile(pattern, flags)
    295 if not (flags & DEBUG):
    296     if len(_cache) >= _MAXCACHE:
    297         # Drop the oldest item

File c:\Users\cdufort\AppData\Local\Programs\Python\Python311\Lib\re\_compiler.py:743, in compile(p, flags)
    741 if isstring(p):
    742     pattern = p
--> 743     p = _parser.parse(p, flags)
    744 else:
    745     pattern = None

File c:\Users\cdufort\AppData\Local\Programs\Python\Python311\Lib\re\_parser.py:980, in parse(str, flags, state)
    977 state.flags = flags
    978 state.str = str
--> 980 p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
    981 p.state.flags = fix_flags(str, p.state.flags)
    983 if source.next is not None:

File c:\Users\cdufort\AppData\Local\Programs\Python\Python311\Lib\re\_parser.py:455, in _parse_sub(source, state, verbose, nested)
    453 start = source.tell()
    454 while True:
--> 455     itemsappend(_parse(source, state, verbose, nested + 1,
    456                        not nested and not items))
    457     if not sourcematch("|"):
    458         break

File c:\Users\cdufort\AppData\Local\Programs\Python\Python311\Lib\re\_parser.py:539, in _parse(source, state, verbose, nested, first)
    536         continue
    538 if this[0] == "\\":
--> 539     code = _escape(source, this, state)
    540     subpatternappend(code)
    542 elif this not in SPECIAL_CHARS:

File c:\Users\cdufort\AppData\Local\Programs\Python\Python311\Lib\re\_parser.py:393, in _escape(source, escape, state)
    391 escape += source.getwhile(8, HEXDIGITS)
    392 if len(escape) != 10:
--> 393     raise source.error("incomplete escape %s" % escape, len(escape))
    394 c = int(escape[2:], 16)
    395 chr(c) # raise ValueError for invalid code

error: incomplete escape \U at position 2

Workaround

Add re.escape to the regex to compile: return re.compile(re.escape(template_to_pattern(named_capture_patterns, template)))

I guess this annihilates some of the functionnality of mk_pattern_from_template_and_format_dict, but that's the only thing I have found to go around this error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant