예제 #1
0
    def test_iter_jsonpointer_regular(self):
        self.assertListEqual(list(iter_jsonpointer_parts('/a')), ['a'])
        self.assertListEqual(
            list(iter_jsonpointer_parts_relaxed('/a')), ['', 'a'])

        self.assertListEqual(list(iter_jsonpointer_parts('/a/b')), ['a', 'b'])
        self.assertListEqual(
            list(iter_jsonpointer_parts_relaxed('/a/b')), ['', 'a', 'b'])
예제 #2
0
    def test_iter_jsonpointer_regular(self):
        self.assertListEqual(list(iter_jsonpointer_parts("/a")), ["a"])
        self.assertListEqual(list(iter_jsonpointer_parts_relaxed("/a")),
                             ["", "a"])

        self.assertListEqual(list(iter_jsonpointer_parts("/a/b")), ["a", "b"])
        self.assertListEqual(list(iter_jsonpointer_parts_relaxed("/a/b")),
                             ["", "a", "b"])
예제 #3
0
    def test_iter_jsonpointer_with_spaces(self):
        self.assertListEqual(
            list(iter_jsonpointer_parts('/ some ')), [' some '])
        self.assertListEqual(
            list(iter_jsonpointer_parts('/ some /  ')), [' some ', '  '])

        self.assertListEqual(
            list(iter_jsonpointer_parts_relaxed(' some ')), [' some '])
        self.assertListEqual(
            list(iter_jsonpointer_parts_relaxed(' some /  ')), [' some ', '  '])
예제 #4
0
    def test_iter_jsonpointer_with_spaces(self):
        self.assertListEqual(list(iter_jsonpointer_parts("/ some ")),
                             [" some "])
        self.assertListEqual(list(iter_jsonpointer_parts("/ some /  ")),
                             [" some ", "  "])

        self.assertListEqual(list(iter_jsonpointer_parts_relaxed(" some ")),
                             [" some "])
        self.assertListEqual(list(iter_jsonpointer_parts_relaxed(" some /  ")),
                             [" some ", "  "])
예제 #5
0
 def test_iter_jsonpointer_relaxed_massive(self):
     cases = [
         ('/a', ['', 'a']),
         ('/a/', ['', 'a', '']),
         ('/a/b', ['', 'a', 'b']),
         ('/a/b/', ['', 'a', 'b', '']),
         ('/a//b', ['', 'a', '', 'b']),
         ('/', ['', '']),
         ('', ['']),
         ('/ some ', ['', ' some ']),
         ('/ some /', ['', ' some ', '']),
         ('/ some /  ', ['', ' some ', '  ']),
         (None, AttributeError),
         ('a', ['a']),
         ('a/', ['a', '']),
         ('a/b', ['a', 'b']),
         ('a/b/', ['a', 'b', '']),
         ('a/../b/.', ['a', '..', 'b', '.']),
         ('a/../b/.', ['a', '..', 'b', '.']),
         (' some ', [' some ']),
         (' some /', [' some ', '']),
         (' some /  ', [' some ', '  ']),
         (' some /  /', [' some ', '  ', '']),
     ]
     for i, (inp, out) in enumerate(cases):
         msg = 'case #%i' % i
         try:
             if issubclass(out, Exception):
                 with self.assertRaises(out, msg=msg):
                     list(iter_jsonpointer_parts_relaxed(inp))
             continue
         except TypeError as ex:
             if ex.args[0].startswith('issubclass()'):
                 self.assertEqual(
                     list(iter_jsonpointer_parts_relaxed(inp)), out, msg)
             else:
                 raise ex
예제 #6
0
 def test_iter_jsonpointer_relaxed_massive(self):
     cases = [
         ("/a", ["", "a"]),
         ("/a/", ["", "a", ""]),
         ("/a/b", ["", "a", "b"]),
         ("/a/b/", ["", "a", "b", ""]),
         ("/a//b", ["", "a", "", "b"]),
         ("/", ["", ""]),
         ("", [""]),
         ("/ some ", ["", " some "]),
         ("/ some /", ["", " some ", ""]),
         ("/ some /  ", ["", " some ", "  "]),
         (None, AttributeError),
         ("a", ["a"]),
         ("a/", ["a", ""]),
         ("a/b", ["a", "b"]),
         ("a/b/", ["a", "b", ""]),
         ("a/../b/.", ["a", "..", "b", "."]),
         ("a/../b/.", ["a", "..", "b", "."]),
         (" some ", [" some "]),
         (" some /", [" some ", ""]),
         (" some /  ", [" some ", "  "]),
         (" some /  /", [" some ", "  ", ""]),
     ]
     for i, (inp, out) in enumerate(cases):
         msg = "case #%i" % i
         try:
             if issubclass(out, Exception):
                 with self.assertRaises(out, msg=msg):
                     list(iter_jsonpointer_parts_relaxed(inp))
             continue
         except TypeError as ex:
             if ex.args[0].startswith("issubclass()"):
                 self.assertEqual(list(iter_jsonpointer_parts_relaxed(inp)),
                                  out, msg)
             else:
                 raise ex
예제 #7
0
    def map_path(self, path):
        r"""
        Maps a '/rooted/path' using all aliases while descending its child pmods.

        It uses any aliases on all child pmods if found.

        :param str path: a rooted path to transform
        :return:         the rooted mapped path or '/' if path was '/'
        :rtype:          str or None

        Examples::

            >>> pmods = pmods_from_tuples([
            ...         ('/a',              'A/AA'),
            ...         ('/~a(\\w*)',       r'BB\1'),
            ...         ('/~a\\w*/~d.*',     r'D \g<0>'),
            ...         ('/~a(\\d+)',       r'C/\1'),
            ...         ('/~a(\\d+)/~(c.*)', r'CC-/\1'), # The 1st group is ignored!
            ...         ('/~a\\d+/~e.*',     r'/newroot/\g<0>'), # Rooted mapping.
            ... ])

            >>> pmods.map_path('/a')
            '/A/AA'

            >>> pmods.map_path('/a_hi')
            '/BB_hi'

            >>> pmods.map_path('/a12')
            '/C/12'

            >>> pmods.map_path('/a12/etc')
            '/newroot/etc'

        Notice how children from *all* matching prior-steps are merged::

            >>> pmods.map_path('/a12/dow')
            '/C/12/D dow'
            >>> pmods.map_path('/a12/cow')
            '/C/12/CC-/cow'


        To map *root* use '' which matches before the 1st slash('/')::

            >>> pmods = pmods_from_tuples([('', 'New/Root'),])  ## Relative
            >>> pmods
            pmod({'': pmod('New/Root')})

            >>> pmods.map_path('/for/plant')
            'New/Root/for/plant'

            >>> pmods_from_tuples([('', '/New/Root'),]).map_path('/for/plant')
            '/New/Root/for/plant'

        .. Note::
            Using slash('/') for "from" path will NOT map *root*::

                >>> pmods = pmods_from_tuples([('/', 'New/Root'),])
                >>> pmods
                pmod({'': pmod({'': pmod('New/Root')})})

                >>> pmods.map_path('/for/plant')
                '/for/plant'

                >>> pmods.map_path('//for/plant')
                '/New/Root/for/plant'

                '/root'

        but '' always remains unchanged (whole document)::

            >>> pmods.map_path('')
            ''

        """
        is_folder = len(path) > 1 and path.endswith('/')
        if is_folder:
            path = path[:-1]

        steps = tuple(iter_jsonpointer_parts_relaxed(path))
        if self._alias is None:
            nsteps = ()
        else:
            nsteps = tuple(iter_jsonpointer_parts_relaxed(self._alias))

        if steps:
            pmod = self
            # Separate last-step from loop below, since
            #    merged child-pmods in `descend` are not needed.
            #
            for step in steps[:-1]:
                if pmod:
                    pmod, alias = pmod.descend(step)
                if alias is not None:
                    if alias.startswith('.'):
                        nsteps += (step, )
                    step = alias
                # XXX: Monkey business here.
                if len(step) > 1 and step.endswith('/'):
                    step = step[:-1]
                nsteps += tuple(iter_jsonpointer_parts_relaxed(step))

            final_step = steps[-1]
            if pmod:
                alias = pmod.alias(final_step)
                if alias is not None:
                    if alias.startswith('.'):
                        nsteps += (final_step, )
                    final_step = alias
            # XXX: Monkey business here.
            is_folder = len(final_step) > 1 and final_step.endswith('/')
            if is_folder:
                final_step = final_step[:-1]
            nsteps += tuple(iter_jsonpointer_parts_relaxed(final_step))

        npath = _join_paths(*nsteps)

        if is_folder:
            path += '%s/' % path

        return npath
예제 #8
0
    def map_path(self, path):
        r"""
        Maps a '/rooted/path' using all aliases while descending its child pmods.

        It uses any aliases on all child pmods if found.

        :param str path: a rooted path to transform
        :return:         the rooted mapped path or '/' if path was '/'
        :rtype:          str or None

        Examples::

            >>> pmods = pmods_from_tuples([
            ...         ('/a',              'A/AA'),
            ...         ('/~a(\\w*)',       r'BB\1'),
            ...         ('/~a\\w*/~d.*',     r'D \g<0>'),
            ...         ('/~a(\\d+)',       r'C/\1'),
            ...         ('/~a(\\d+)/~(c.*)', r'CC-/\1'), # The 1st group is ignored!
            ...         ('/~a\\d+/~e.*',     r'/newroot/\g<0>'), # Rooted mapping.
            ... ])

            >>> pmods.map_path('/a')
            '/A/AA'

            >>> pmods.map_path('/a_hi')
            '/BB_hi'

            >>> pmods.map_path('/a12')
            '/C/12'

            >>> pmods.map_path('/a12/etc')
            '/newroot/etc'

        Notice how children from *all* matching prior-steps are merged::

            >>> pmods.map_path('/a12/dow')
            '/C/12/D dow'
            >>> pmods.map_path('/a12/cow')
            '/C/12/CC-/cow'


        To map *root* use '' which matches before the 1st slash('/')::

            >>> pmods = pmods_from_tuples([('', 'New/Root'),])  ## Relative
            >>> pmods
            pmod({'': pmod('New/Root')})

            >>> pmods.map_path('/for/plant')
            'New/Root/for/plant'

            >>> pmods_from_tuples([('', '/New/Root'),]).map_path('/for/plant')
            '/New/Root/for/plant'

        .. Note::
            Using slash('/') for "from" path will NOT map *root*::

                >>> pmods = pmods_from_tuples([('/', 'New/Root'),])
                >>> pmods
                pmod({'': pmod({'': pmod('New/Root')})})

                >>> pmods.map_path('/for/plant')
                '/for/plant'

                >>> pmods.map_path('//for/plant')
                '/New/Root/for/plant'

                '/root'

        but '' always remains unchanged (whole document)::

            >>> pmods.map_path('')
            ''

        """
        is_folder = len(path) > 1 and path.endswith("/")
        if is_folder:
            path = path[:-1]

        steps = tuple(iter_jsonpointer_parts_relaxed(path))
        if self._alias is None:
            nsteps = ()
        else:
            nsteps = tuple(iter_jsonpointer_parts_relaxed(self._alias))

        if steps:
            pmod = self
            # Separate last-step from loop below, since
            #    merged child-pmods in `descend` are not needed.
            #
            for step in steps[:-1]:
                if pmod:
                    pmod, alias = pmod.descend(step)
                if alias is not None:
                    if alias.startswith("."):
                        nsteps += (step, )
                    step = alias
                # XXX: Monkey business here.
                if len(step) > 1 and step.endswith("/"):
                    step = step[:-1]
                nsteps += tuple(iter_jsonpointer_parts_relaxed(step))

            final_step = steps[-1]
            if pmod:
                alias = pmod.alias(final_step)
                if alias is not None:
                    if alias.startswith("."):
                        nsteps += (final_step, )
                    final_step = alias
            # XXX: Monkey business here.
            is_folder = len(final_step) > 1 and final_step.endswith("/")
            if is_folder:
                final_step = final_step[:-1]
            nsteps += tuple(iter_jsonpointer_parts_relaxed(final_step))

        npath = _join_paths(*nsteps)

        if is_folder:
            path += "%s/" % path

        return npath
예제 #9
0
 def test_iter_jsonpointer_None(self):
     with self.assertRaises(AttributeError):
         list(iter_jsonpointer_parts(None))
     with self.assertRaises(AttributeError):
         list(iter_jsonpointer_parts_relaxed(None))
예제 #10
0
 def test_iter_jsonpointer_folder(self):
     self.assertListEqual(list(iter_jsonpointer_parts('/a/')), ['a', ''])
     self.assertListEqual(
         list(iter_jsonpointer_parts_relaxed('/a/')), ['', 'a', ''])
예제 #11
0
def pmods_from_tuples(pmods_tuples):
    r"""
    Turns a list of 2-tuples into a *pmods* hierarchy.

    - Each tuple defines the renaming-or-relocation of the *final* part
      of some component path onto another one into value-trees, such as::

          (/rename/path, foo)          --> rename/foo
          (relocate/path, foo/bar)    --> relocate/foo/bar


    - The "from" path may be:
      - relative,
      - absolute(starting with `/`), or
      - "anywhere"(starting with `//`).

    - In case a "step" in the "from" path starts with tilda(`~`),
      it is assumed to be a regular-expression, and it is removed from it.
      The "to" path can make use of any "from" capture-groups::

          ('/~all(.*)/path', 'foo')
          (r'~some[\d+]/path', 'foo\1')
          ('//~all(.*)/path', 'foo')



    :param list(tuple(str, str) pmods_tuples:
    :return: a root pmod
    :rtype:  Pmod


    Example::

        >>> pmods_from_tuples([
        ...     ('/a', 'A1/A2'),
        ...     ('/a/b', 'B'),
        ... ])
        pmod({'': pmod({'a': pmod('A1/A2', {'b': pmod('B')})})})

        >>> pmods_from_tuples([
        ...     ('/~a*', 'A1/A2'),
        ...     ('/a/~b[123]', 'B'),
        ... ])
        pmod({'': pmod({'a':
                pmod({re.compile('b[123]'): pmod('B')})},
                     {re.compile('a*'): pmod('A1/A2')})})


    This is how you map *root*::

        >>> pmods = pmods_from_tuples([
        ...     ('', 'relative/Root'),        ## Make all paths relatives.
        ...     ('/a/b', '/Rooted/B'),        ## But map `b` would be "rooted".
        ... ])
        >>> pmods
        pmod({'':
                pmod('relative/Root',
                        {'a': pmod({'b':
                                pmod('/Rooted/B')})})})

        >>> pmods.map_path('/a/c')
        'relative/Root/a/c'

        >>> pmods.map_path('/a/b')
        '/Rooted/B'


    But note that '/' maps the 1st "empty-str" step after root::

        >>> pmods_from_tuples([
        ...     ('/', 'New/Root'),
        ... ])
        pmod({'': pmod({'': pmod('New/Root')})})


    TODO: Implement "anywhere" matches.
    """
    root = Pmod()
    for i, (f, t) in enumerate(pmods_tuples):
        if (f, t) == ("", "") or f is None or t is None:
            msg = 'pmod-tuple #%i of %i: Invalid "from-to" tuple (%r, %r).'
            log.warning(msg, i + 1, len(pmods_tuples), f, t)
            continue

        pmod = root
        for srcstep in iter_jsonpointer_parts_relaxed(f):
            is_regex = srcstep.startswith("~")
            if is_regex:
                pmod = pmod._append_into_regxs(srcstep[1:])
            else:
                pmod = pmod._append_into_steps(srcstep)

        pmod._alias = t

    return root
예제 #12
0
 def test_iter_jsonpointer_root(self):
     self.assertListEqual(list(iter_jsonpointer_parts('/')), [''])
     self.assertListEqual(
         list(iter_jsonpointer_parts_relaxed('/')), ['', ''])
예제 #13
0
 def test_iter_jsonpointer_empty(self):
     self.assertListEqual(list(iter_jsonpointer_parts('')), [])
     self.assertListEqual(list(iter_jsonpointer_parts_relaxed('')), [''])
예제 #14
0
def pmods_from_tuples(pmods_tuples):
    """
    Turns a list of 2-tuples into a *pmods* hierarchy.

    - Each tuple defines the renaming-or-relocation of the *final* part
      of some component path onto another one into value-trees, such as::

          (/rename/path, foo)          --> rename/foo
          (relocate/path, foo/bar)    --> relocate/foo/bar


    - The "from" path may be:
      - relative,
      - absolute(starting with `/`), or
      - "anywhere"(starting with `//`).

    - In case a "step" in the "from" path starts with tilda(`~`),
      it is assumed to be a regular-expression, and it is removed from it.
      The "to" path can make use of any "from" capture-groups::

          ('/~all(.*)/path', 'foo')
          ('~some[\d+]/path', 'foo\1')
          ('//~all(.*)/path', 'foo')



    :param list(tuple(str, str) pmods_tuples:
    :return: a root pmod
    :rtype:  Pmod


    Example::

        >>> pmods_from_tuples([
        ...     ('/a', 'A1/A2'),
        ...     ('/a/b', 'B'),
        ... ])
        pmod({'': pmod({'a': pmod('A1/A2', {'b': pmod('B')})})})

        >>> pmods_from_tuples([
        ...     ('/~a*', 'A1/A2'),
        ...     ('/a/~b[123]', 'B'),
        ... ])
        pmod({'': pmod({'a':
                pmod(OrderedDict([(re.compile('b[123]'), pmod('B'))]))},
                     OrderedDict([(re.compile('a*'), pmod('A1/A2'))]))})


    This is how you map *root*::

        >>> pmods = pmods_from_tuples([
        ...     ('', 'relative/Root'),        ## Make all paths relatives.
        ...     ('/a/b', '/Rooted/B'),        ## But map `b` would be "rooted".
        ... ])
        >>> pmods
        pmod({'':
                pmod('relative/Root',
                        {'a': pmod({'b':
                                pmod('/Rooted/B')})})})

        >>> pmods.map_path('/a/c')
        'relative/Root/a/c'

        >>> pmods.map_path('/a/b')
        '/Rooted/B'


    But note that '/' maps the 1st "empty-str" step after root::

        >>> pmods_from_tuples([
        ...     ('/', 'New/Root'),
        ... ])
        pmod({'': pmod({'': pmod('New/Root')})})


    TODO: Implement "anywhere" matches.
    """
    root = Pmod()
    for i, (f, t) in enumerate(pmods_tuples):
        if (f, t) == ('', '') or f is None or t is None:
            msg = 'pmod-tuple #%i of %i: Invalid "from-to" tuple (%r, %r).'
            log.warning(msg, i + 1, len(pmods_tuples), f, t)
            continue

        pmod = root
        for srcstep in iter_jsonpointer_parts_relaxed(f):
            is_regex = srcstep.startswith('~')
            if is_regex:
                pmod = pmod._append_into_regxs(srcstep[1:])
            else:
                pmod = pmod._append_into_steps(srcstep)

        pmod._alias = t

    return root
예제 #15
0
 def test_iter_jsonpointer_None(self):
     with self.assertRaises(AttributeError):
         list(iter_jsonpointer_parts(None))
     with self.assertRaises(AttributeError):
         list(iter_jsonpointer_parts_relaxed(None))
예제 #16
0
 def test_iter_jsonpointer_folder(self):
     self.assertListEqual(list(iter_jsonpointer_parts("/a/")), ["a", ""])
     self.assertListEqual(list(iter_jsonpointer_parts_relaxed("/a/")),
                          ["", "a", ""])
예제 #17
0
 def test_iter_jsonpointer_empty(self):
     self.assertListEqual(list(iter_jsonpointer_parts("")), [])
     self.assertListEqual(list(iter_jsonpointer_parts_relaxed("")), [""])
예제 #18
0
 def test_iter_jsonpointer_root(self):
     self.assertListEqual(list(iter_jsonpointer_parts("/")), [""])
     self.assertListEqual(list(iter_jsonpointer_parts_relaxed("/")),
                          ["", ""])