From 4a23ea61a1ccb869084a979aa58c3c872e268e9d Mon Sep 17 00:00:00 2001 From: Joey Wilhelm Date: Fri, 6 Apr 2018 05:00:00 -0700 Subject: [PATCH] Switch to using regex instead of re (#170) * Use regex instead of re as regex implements \p{*} py3 re stdlib fails if the regular expression contains things it can't understand like \p. However, regex actually understands those constructs * Update a couple more references to use regex --- pyangbind/lib/xpathhelper.py | 14 +++++++------- pyangbind/lib/yangtypes.py | 17 +++++++++-------- requirements.txt | 1 + tests/serialise/openconfig-serialise/run.py | 4 ++-- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/pyangbind/lib/xpathhelper.py b/pyangbind/lib/xpathhelper.py index 24b57d84..8d98a977 100644 --- a/pyangbind/lib/xpathhelper.py +++ b/pyangbind/lib/xpathhelper.py @@ -26,7 +26,7 @@ from collections import OrderedDict from lxml import etree -import re +import regex import uuid from .yangtypes import safe_name from .base import PybindBase @@ -104,11 +104,11 @@ def __init__(self): class YANGPathHelper(PybindXpathHelper): - _attr_re = re.compile("^(?P[^\[]+)(?P(\[[^\]]+\])+)$") - _arg_re = re.compile("^((and|or) )?[@]?(?P[a-zA-Z0-9\-\_:]+)([ ]+)?" + + _attr_re = regex.compile("^(?P[^\[]+)(?P(\[[^\]]+\])+)$") + _arg_re = regex.compile("^((and|or) )?[@]?(?P[a-zA-Z0-9\-\_:]+)([ ]+)?" + "=([ ]+)?[\'\"]?(?P[^ ^\'^\"]+)([\'\"])?([ ]+)?" + "(?P.*)") - _relative_path_re = re.compile("^(\.|\.\.)") + _relative_path_re = regex.compile("^(\.|\.\.)") def __init__(self): # Initialise an empty library and a new FakeRoot class to act as the @@ -174,7 +174,7 @@ def _encode_path(self, path, mode="search", find_parent=False, for k, v in attributes.iteritems(): # handling for rfc6020 current() specification if "current()" in v: - remaining_path = re.sub("current\(\)(?P.*)", + remaining_path = regex.sub("current\(\)(?P.*)", '\g', v).split("/") # since the calling leaf may not exist, we need to do a # lookup on a path that will do, which is the parent @@ -227,7 +227,7 @@ def register(self, object_path, object_ptr, caller=False): if isinstance(object_path, str): raise XPathError("not meant to receive strings as input to register()") - if re.match('^\.\.', object_path[0]): + if regex.match('^\.\.', object_path[0]): raise XPathError("unhandled relative path in register()") # This is a hack to register anything that is a top-level object, @@ -279,7 +279,7 @@ def register(self, object_path, object_ptr, caller=False): def unregister(self, object_path, caller=False): if isinstance(object_path, str): raise XPathError("should not receive paths as a str in unregister()") - if re.match("^(\.|\.\.|\/)", object_path[0]): + if regex.match("^(\.|\.\.|\/)", object_path[0]): raise XPathError("unhandled relative path in unregister()") existing_objs = self._get_etree(object_path) diff --git a/pyangbind/lib/yangtypes.py b/pyangbind/lib/yangtypes.py index fa8aee58..e0a0e53c 100644 --- a/pyangbind/lib/yangtypes.py +++ b/pyangbind/lib/yangtypes.py @@ -24,7 +24,7 @@ from decimal import Decimal from bitarray import bitarray import uuid -import re +import regex import collections import copy import six @@ -32,7 +32,7 @@ # For Python3 if six.PY3: unicode = str - + basestring = str # Words that could turn up in YANG definition files that are actually # reserved names in Python, such as being builtin types. This list is # not complete, but will probably continue to grow. @@ -139,7 +139,7 @@ def RestrictedClassType(*args, **kwargs): # this gives deserialisers some hints as to how to encode/decode this value # it must be a list since a restricted class can encapsulate a restricted # class - current_restricted_class_type = re.sub("<(type|class) '(?P.*)'>", + current_restricted_class_type = regex.sub("<(type|class) '(?P.*)'>", "\g", str(base_type)) if hasattr(base_type, "_restricted_class_base"): restricted_class_hint = getattr(base_type, "_restricted_class_base") @@ -179,9 +179,9 @@ def __new__(self, *args, **kwargs): _restriction_test method so that it can be called by other functions. """ - range_regex = re.compile("(?P\-?[0-9\.]+|min)([ ]+)?\.\.([ ]+)?" + + range_regex = regex.compile("(?P\-?[0-9\.]+|min)([ ]+)?\.\.([ ]+)?" + "(?P(\-?[0-9\.]+|max))") - range_single_value_regex = re.compile("(?P\-?[0-9\.]+)") + range_single_value_regex = regex.compile("(?P\-?[0-9\.]+)") def convert_regexp(pattern): @@ -203,6 +203,7 @@ def convert_regexp(pattern): pattern = "^%s" % pattern if not pattern[len(pattern) - 1] == "$": pattern = "%s$" % pattern + return pattern def build_length_range_tuples(range, length=False, multiplier=1): @@ -253,7 +254,7 @@ def match_pattern_check(regexp): def mp_check(value): if not isinstance(value, basestring): return False - if re.match(convert_regexp(regexp), value): + if regex.match(convert_regexp(regexp), value): return True return False return mp_check @@ -947,7 +948,7 @@ class YANGBaseClass(base_type): if yang_type in ["container", "list"] or is_container == "container": __slots__ = tuple(clsslots) - _pybind_base_class = re.sub("<(type|class) '(?P.*)'>", "\g", + _pybind_base_class = regex.sub("<(type|class) '(?P.*)'>", "\g", str(base_type)) def __new__(self, *args, **kwargs): @@ -1211,7 +1212,7 @@ def __init__(self, *args, **kwargs): if value is not None: set_method(value) - self._type = re.sub("<(type|class) '(?P.*)'>", "\g", + self._type = regex.sub("<(type|class) '(?P.*)'>", "\g", str(get_method()._base_type)) self._utype = get_method()._base_type diff --git a/requirements.txt b/requirements.txt index 45efb901..cf8ceb9a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ pyang bitarray lxml +regex six enum34 diff --git a/tests/serialise/openconfig-serialise/run.py b/tests/serialise/openconfig-serialise/run.py index 6a55d081..d11f8ea2 100755 --- a/tests/serialise/openconfig-serialise/run.py +++ b/tests/serialise/openconfig-serialise/run.py @@ -6,7 +6,7 @@ import json import requests import time -import re +import regex import difflib from pyangbind.lib.xpathhelper import YANGPathHelper @@ -94,7 +94,7 @@ def main(): for fn in os.listdir(os.path.join(this_dir, "json")): jobj = json.load(open(os.path.join(this_dir, "json", fn), 'r')) - parameters = re.sub( + parameters = regex.sub( 'interfaces\_ph:(?P[a-zA-Z]+)\-flt:(?P[a-zA-Z]+)\-m:(?P[a-zA-Z]+)\.json', '\g||\g||\g', fn).split("||") path_helper, config_filter, mode = YANGBool(parameters[0]), YANGBool(parameters[1]), parameters[2]