On Wed, Nov 6, 2019, 11:50 PM Mark Michelson <[email protected]> wrote:

> Acked-by: Mark Michelson <[email protected]>
>

Thanks for the review. Looks like the patch failed in CI.

Below changes in Makefile.am fixed it.

I applied this patch to master with the below additional changes.

Thanks
Numan

diff --git a/Makefile.am b/Makefile.am
index 88ede2d82..1e41e49ea 100644
--- a/Makefile.am
+++ b/Makefile.am
 ALL_LOCAL =
@@ -165,7 +165,7 @@ ro_shell = printf '\043 Generated automatically -- do
not modify!    -*- buffer-

 SUFFIXES += .in
 .in:
-       $(AM_V_GEN)PYTHONPATH=$$PYTHONPATH$(psep)$(srcdir)/python $(PYTHON)
$(srcdir)/build-aux/soexpand.py -I$(srcdir) -I$(OVS_SRCDIR) < $< | \
+
$(AM_V_GEN)PYTHONPATH=$(OVS_SRCDIR)/python$(psep)$$PYTHONPATH$(psep)$(srcdir)/python
$(PYTHON) $(srcdir)/build-aux/soexpand.py -I$(srcdir) -I$(OVS_SRCDIR) < $<
| \
          $(PYTHON) $(srcdir)/build-aux/dpdkstrip.py $(DPDKSTRIP_FLAGS) | \
          sed \
            -e 's,[@]PKIDIR[@],$(PKIDIR),g' \
@@ -424,8 +424,8 @@ endif
 CLEANFILES += flake8-check

 include $(srcdir)/manpages.mk
-$(srcdir)/manpages.mk: $(MAN_ROOTS) build-aux/sodepends.py
python/build/soutil.py
-       @PYTHONPATH=$$PYTHONPATH$(psep)$(srcdir)/python $(PYTHON)
$(srcdir)/build-aux/sodepends.py -I. -I$(srcdir) -I$(OVS_MANDIR)
$(MAN_ROOTS) >$(@F).tmp
+$(srcdir)/manpages.mk: $(MAN_ROOTS) build-aux/sodepends.py
$(OVS_SRCDIR)/python/build/soutil.py
+
@PYTHONPATH=$(OVS_SRCDIR)/python$(psep)$$PYTHONPATH$(psep)$(srcdir)/python
$(PYTHON) $(srcdir)/build-aux/sodepends.py -I. -I$(srcdir) -I$(OVS_MANDIR)
$(MAN_ROOTS) >$(@F).tmp
        @if cmp -s $(@F).tmp $@; then \
          touch $@; \
          rm -f $(@F).tmp; \


> On 11/6/19 6:52 AM, [email protected] wrote:
> > From: Numan Siddique <[email protected]>
> >
> > The python/ directory belongs to Open vSwitch repo.
> > This patch uses the python utils required for building OVN from
> > the configured OVS source directory and deletes the python directory.
> >
> > Signed-off-by: Numan Siddique <[email protected]>
> > ---
> >   Makefile.am                                   |    5 +-
> >   python/.gitignore                             |    2 -
> >   python/README.rst                             |    1 -
> >   python/automake.mk                            |  123 -
> >   python/build/__init__.py                      |    0
> >   python/build/nroff.py                         |  398 ---
> >   python/build/soutil.py                        |   56 -
> >   python/ovs/.gitignore                         |    1 -
> >   python/ovs/__init__.py                        |    1 -
> >   python/ovs/_json.c                            |  269 --
> >   python/ovs/compat/__init__.py                 |    0
> >   python/ovs/compat/sortedcontainers/LICENSE    |   13 -
> >   .../ovs/compat/sortedcontainers/__init__.py   |   52 -
> >   .../ovs/compat/sortedcontainers/sorteddict.py |  741 -----
> >   .../ovs/compat/sortedcontainers/sortedlist.py | 2508 -----------------
> >   .../ovs/compat/sortedcontainers/sortedset.py  |  327 ---
> >   python/ovs/daemon.py                          |  652 -----
> >   python/ovs/db/__init__.py                     |    1 -
> >   python/ovs/db/custom_index.py                 |  154 -
> >   python/ovs/db/data.py                         |  585 ----
> >   python/ovs/db/error.py                        |   34 -
> >   python/ovs/db/idl.py                          | 2030 -------------
> >   python/ovs/db/parser.py                       |  118 -
> >   python/ovs/db/schema.py                       |  304 --
> >   python/ovs/db/types.py                        |  647 -----
> >   python/ovs/dirs.py                            |   31 -
> >   python/ovs/dirs.py.template                   |   31 -
> >   python/ovs/fatal_signal.py                    |  183 --
> >   python/ovs/fcntl_win.py                       |   46 -
> >   python/ovs/json.py                            |  531 ----
> >   python/ovs/jsonrpc.py                         |  616 ----
> >   python/ovs/ovsuuid.py                         |   70 -
> >   python/ovs/poller.py                          |  290 --
> >   python/ovs/process.py                         |   41 -
> >   python/ovs/reconnect.py                       |  608 ----
> >   python/ovs/socket_util.py                     |  335 ---
> >   python/ovs/stream.py                          |  831 ------
> >   python/ovs/timeval.py                         |   81 -
> >   python/ovs/unixctl/__init__.py                |   91 -
> >   python/ovs/unixctl/client.py                  |   68 -
> >   python/ovs/unixctl/server.py                  |  260 --
> >   python/ovs/util.py                            |   95 -
> >   python/ovs/vlog.py                            |  475 ----
> >   python/ovs/winutils.py                        |  266 --
> >   python/ovstest/__init__.py                    |    1 -
> >   python/ovstest/args.py                        |  283 --
> >   python/ovstest/rpcserver.py                   |  383 ---
> >   python/ovstest/tcp.py                         |  120 -
> >   python/ovstest/tests.py                       |  250 --
> >   python/ovstest/udp.py                         |   85 -
> >   python/ovstest/util.py                        |  253 --
> >   python/ovstest/vswitch.py                     |  107 -
> >   python/setup.py                               |  102 -
> >   tests/atlocal.in                              |    2 +-
> >   tests/ovn-controller-vtep.at                  |    2 +
> >   55 files changed, 5 insertions(+), 15554 deletions(-)
> >   delete mode 100644 python/.gitignore
> >   delete mode 100644 python/README.rst
> >   delete mode 100644 python/automake.mk
> >   delete mode 100644 python/build/__init__.py
> >   delete mode 100644 python/build/nroff.py
> >   delete mode 100755 python/build/soutil.py
> >   delete mode 100644 python/ovs/.gitignore
> >   delete mode 100644 python/ovs/__init__.py
> >   delete mode 100644 python/ovs/_json.c
> >   delete mode 100644 python/ovs/compat/__init__.py
> >   delete mode 100644 python/ovs/compat/sortedcontainers/LICENSE
> >   delete mode 100644 python/ovs/compat/sortedcontainers/__init__.py
> >   delete mode 100644 python/ovs/compat/sortedcontainers/sorteddict.py
> >   delete mode 100644 python/ovs/compat/sortedcontainers/sortedlist.py
> >   delete mode 100644 python/ovs/compat/sortedcontainers/sortedset.py
> >   delete mode 100644 python/ovs/daemon.py
> >   delete mode 100644 python/ovs/db/__init__.py
> >   delete mode 100644 python/ovs/db/custom_index.py
> >   delete mode 100644 python/ovs/db/data.py
> >   delete mode 100644 python/ovs/db/error.py
> >   delete mode 100644 python/ovs/db/idl.py
> >   delete mode 100644 python/ovs/db/parser.py
> >   delete mode 100644 python/ovs/db/schema.py
> >   delete mode 100644 python/ovs/db/types.py
> >   delete mode 100644 python/ovs/dirs.py
> >   delete mode 100644 python/ovs/dirs.py.template
> >   delete mode 100644 python/ovs/fatal_signal.py
> >   delete mode 100644 python/ovs/fcntl_win.py
> >   delete mode 100644 python/ovs/json.py
> >   delete mode 100644 python/ovs/jsonrpc.py
> >   delete mode 100644 python/ovs/ovsuuid.py
> >   delete mode 100644 python/ovs/poller.py
> >   delete mode 100644 python/ovs/process.py
> >   delete mode 100644 python/ovs/reconnect.py
> >   delete mode 100644 python/ovs/socket_util.py
> >   delete mode 100644 python/ovs/stream.py
> >   delete mode 100644 python/ovs/timeval.py
> >   delete mode 100644 python/ovs/unixctl/__init__.py
> >   delete mode 100644 python/ovs/unixctl/client.py
> >   delete mode 100644 python/ovs/unixctl/server.py
> >   delete mode 100644 python/ovs/util.py
> >   delete mode 100644 python/ovs/vlog.py
> >   delete mode 100644 python/ovs/winutils.py
> >   delete mode 100644 python/ovstest/__init__.py
> >   delete mode 100644 python/ovstest/args.py
> >   delete mode 100644 python/ovstest/rpcserver.py
> >   delete mode 100644 python/ovstest/tcp.py
> >   delete mode 100644 python/ovstest/tests.py
> >   delete mode 100644 python/ovstest/udp.py
> >   delete mode 100644 python/ovstest/util.py
> >   delete mode 100644 python/ovstest/vswitch.py
> >   delete mode 100644 python/setup.py
> >
> > diff --git a/Makefile.am b/Makefile.am
> > index 88ede2d82..59c1605fe 100644
> > --- a/Makefile.am
> > +++ b/Makefile.am
> > @@ -70,7 +70,7 @@ endif
> >   # foo/__init__.py into an (older) version with plain foo.py, since
> >   # foo/__init__.pyc will cause Python to ignore foo.py.
> >   run_python = \
> > -     PYTHONPATH=$(top_srcdir)/python$(psep)$$PYTHONPATH \
> > +     PYTHONPATH=$(OVS_SRCDIR)/python$(psep)$$PYTHONPATH \
> >       PYTHONDONTWRITEBYTECODE=yes $(PYTHON)
> >
> >   ALL_LOCAL =
> > @@ -424,7 +424,7 @@ endif
> >   CLEANFILES += flake8-check
> >
> >   include $(srcdir)/manpages.mk
> > -$(srcdir)/manpages.mk: $(MAN_ROOTS) build-aux/sodepends.py
> python/build/soutil.py
> > +$(srcdir)/manpages.mk: $(MAN_ROOTS) build-aux/sodepends.py
> $(OVS_SRCDIR)/python/build/soutil.py
> >       @PYTHONPATH=$$PYTHONPATH$(psep)$(srcdir)/python $(PYTHON)
> $(srcdir)/build-aux/sodepends.py -I. -I$(srcdir) -I$(OVS_MANDIR)
> $(MAN_ROOTS) >$(@F).tmp
> >       @if cmp -s $(@F).tmp $@; then \
> >         touch $@; \
> > @@ -495,7 +495,6 @@ include lib/ovsdb_automake.mk
> >   include ipsec/automake.mk
> >   include rhel/automake.mk
> >   include xenserver/automake.mk
> > -include python/automake.mk
> >   include tutorial/automake.mk
> >   include selinux/automake.mk
> >   include controller/automake.mk
> > diff --git a/python/.gitignore b/python/.gitignore
> > deleted file mode 100644
> > index 60ace6f05..000000000
> > --- a/python/.gitignore
> > +++ /dev/null
> > @@ -1,2 +0,0 @@
> > -dist/
> > -*.egg-info
> > diff --git a/python/README.rst b/python/README.rst
> > deleted file mode 100644
> > index 4f4742c53..000000000
> > --- a/python/README.rst
> > +++ /dev/null
> > @@ -1 +0,0 @@
> > -Python library for working with Open vSwitch
> > diff --git a/python/automake.mk b/python/automake.mk
> > deleted file mode 100644
> > index 5a1e1da8a..000000000
> > --- a/python/automake.mk
> > +++ /dev/null
> > @@ -1,123 +0,0 @@
> > -ovstest_pyfiles = \
> > -     python/ovstest/__init__.py \
> > -     python/ovstest/args.py \
> > -     python/ovstest/rpcserver.py \
> > -     python/ovstest/tcp.py \
> > -     python/ovstest/tests.py \
> > -     python/ovstest/udp.py \
> > -     python/ovstest/util.py \
> > -     python/ovstest/vswitch.py
> > -
> > -ovs_pyfiles = \
> > -     python/ovs/__init__.py \
> > -     python/ovs/compat/__init__.py \
> > -     python/ovs/compat/sortedcontainers/__init__.py \
> > -     python/ovs/compat/sortedcontainers/sortedlist.py \
> > -     python/ovs/compat/sortedcontainers/sorteddict.py \
> > -     python/ovs/compat/sortedcontainers/sortedset.py \
> > -     python/ovs/daemon.py \
> > -     python/ovs/fcntl_win.py \
> > -     python/ovs/db/__init__.py \
> > -     python/ovs/db/custom_index.py \
> > -     python/ovs/db/data.py \
> > -     python/ovs/db/error.py \
> > -     python/ovs/db/idl.py \
> > -     python/ovs/db/parser.py \
> > -     python/ovs/db/schema.py \
> > -     python/ovs/db/types.py \
> > -     python/ovs/fatal_signal.py \
> > -     python/ovs/json.py \
> > -     python/ovs/jsonrpc.py \
> > -     python/ovs/ovsuuid.py \
> > -     python/ovs/poller.py \
> > -     python/ovs/process.py \
> > -     python/ovs/reconnect.py \
> > -     python/ovs/socket_util.py \
> > -     python/ovs/stream.py \
> > -     python/ovs/timeval.py \
> > -     python/ovs/unixctl/__init__.py \
> > -     python/ovs/unixctl/client.py \
> > -     python/ovs/unixctl/server.py \
> > -     python/ovs/util.py \
> > -     python/ovs/version.py \
> > -     python/ovs/vlog.py \
> > -     python/ovs/winutils.py
> > -# These python files are used at build time but not runtime,
> > -# so they are not installed.
> > -EXTRA_DIST += \
> > -     python/build/__init__.py \
> > -     python/build/nroff.py \
> > -     python/build/soutil.py
> > -
> > -# PyPI support.
> > -EXTRA_DIST += \
> > -     python/ovs/compat/sortedcontainers/LICENSE \
> > -     python/README.rst \
> > -     python/setup.py
> > -
> > -# C extension support.
> > -EXTRA_DIST += python/ovs/_json.c
> > -
> > -PYFILES = $(ovs_pyfiles) python/ovs/dirs.py $(ovstest_pyfiles)
> > -EXTRA_DIST += $(PYFILES)
> > -PYCOV_CLEAN_FILES += $(PYFILES:.py=.py,cover)
> > -
> > -FLAKE8_PYFILES += \
> > -     $(filter-out python/ovs/compat/% python/ovs/dirs.py,$(PYFILES)) \
> > -     python/setup.py \
> > -     python/build/__init__.py \
> > -     python/build/nroff.py \
> > -     python/ovs/dirs.py.template
> > -
> > -if HAVE_PYTHON
> > -nobase_pkgdata_DATA = $(ovs_pyfiles) $(ovstest_pyfiles)
> > -ovs-install-data-local:
> > -     $(MKDIR_P) python/ovs
> > -     sed \
> > -             -e '/^##/d' \
> > -                -e 's,[@]pkgdatadir[@],$(pkgdatadir),g' \
> > -                -e 's,[@]RUNDIR[@],$(RUNDIR),g' \
> > -                -e 's,[@]LOGDIR[@],$(LOGDIR),g' \
> > -                -e 's,[@]bindir[@],$(bindir),g' \
> > -                -e 's,[@]sysconfdir[@],$(sysconfdir),g' \
> > -                -e 's,[@]DBDIR[@],$(DBDIR),g' \
> > -             < $(srcdir)/python/ovs/dirs.py.template \
> > -             > python/ovs/dirs.py.tmp
> > -     $(MKDIR_P) $(DESTDIR)$(pkgdatadir)/python/ovs
> > -     $(INSTALL_DATA) python/ovs/dirs.py.tmp
> $(DESTDIR)$(pkgdatadir)/python/ovs/dirs.py
> > -     rm python/ovs/dirs.py.tmp
> > -
> > -python-sdist: $(srcdir)/python/ovs/version.py $(ovs_pyfiles)
> python/ovs/dirs.py
> > -     (cd python/ && $(PYTHON) setup.py sdist)
> > -
> > -pypi-upload: $(srcdir)/python/ovs/version.py $(ovs_pyfiles)
> python/ovs/dirs.py
> > -     (cd python/ && $(PYTHON) setup.py sdist upload)
> > -else
> > -ovs-install-data-local:
> > -     @:
> > -endif
> > -install-data-local: ovs-install-data-local
> > -
> > -UNINSTALL_LOCAL += ovs-uninstall-local
> > -ovs-uninstall-local:
> > -     rm -f $(DESTDIR)$(pkgdatadir)/python/ovs/dirs.py
> > -
> > -ALL_LOCAL += $(srcdir)/python/ovs/version.py
> > -$(srcdir)/python/ovs/version.py: config.status
> > -     $(AM_V_GEN)$(ro_shell) > $(@F).tmp && \
> > -     echo 'VERSION = "$(VERSION)"' >> $(@F).tmp && \
> > -     if cmp -s $(@F).tmp $@; then touch $@; rm $(@F).tmp; else mv
> $(@F).tmp $@; fi
> > -
> > -ALL_LOCAL += $(srcdir)/python/ovs/dirs.py
> > -$(srcdir)/python/ovs/dirs.py: python/ovs/dirs.py.template
> > -     $(AM_V_GEN)sed \
> > -             -e '/^##/d' \
> > -                -e 's,[@]pkgdatadir[@],/usr/local/share/openvswitch,g' \
> > -                -e 's,[@]RUNDIR[@],/var/run,g' \
> > -                -e 's,[@]LOGDIR[@],/usr/local/var/log,g' \
> > -                -e 's,[@]bindir[@],/usr/local/bin,g' \
> > -                -e 's,[@]sysconfdir[@],/usr/local/etc,g' \
> > -                -e 's,[@]DBDIR[@],/usr/local/etc/openvswitch,g' \
> > -             < $? > [email protected] && \
> > -     mv [email protected] $@
> > -EXTRA_DIST += python/ovs/dirs.py.template
> > diff --git a/python/build/__init__.py b/python/build/__init__.py
> > deleted file mode 100644
> > index e69de29bb..000000000
> > diff --git a/python/build/nroff.py b/python/build/nroff.py
> > deleted file mode 100644
> > index a94907757..000000000
> > --- a/python/build/nroff.py
> > +++ /dev/null
> > @@ -1,398 +0,0 @@
> > -# Copyright (c) 2010, 2011, 2012, 2015, 2016, 2017 Nicira, Inc.
> > -#
> > -# Licensed under the Apache License, Version 2.0 (the "License");
> > -# you may not use this file except in compliance with the License.
> > -# You may obtain a copy of the License at:
> > -#
> > -#     http://www.apache.org/licenses/LICENSE-2.0
> > -#
> > -# Unless required by applicable law or agreed to in writing, software
> > -# distributed under the License is distributed on an "AS IS" BASIS,
> > -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> > -# See the License for the specific language governing permissions and
> > -# limitations under the License.
> > -
> > -import re
> > -import sys
> > -
> > -from ovs.db import error
> > -
> > -
> > -def text_to_nroff(s, font=r'\fR', escape_dot=True):
> > -    def escape(match):
> > -        c = match.group(0)
> > -
> > -        # In Roman type, let -- in XML be \- in nroff.  That gives us a
> way to
> > -        # write minus signs, which is important in some places in
> manpages.
> > -        #
> > -        # Bold in nroff usually represents literal text, where there's
> no
> > -        # distinction between hyphens and minus sign.  The convention
> in nroff
> > -        # appears to be to use a minus sign in such cases, so we follow
> that
> > -        # convention.
> > -        #
> > -        # Finally, we always output - as a minus sign when it is
> followed by a
> > -        # digit.
> > -        if c.startswith('-'):
> > -            if c == '--' and font == r'\fR':
> > -                return r'\-'
> > -            if c != '-' or font in (r'\fB', r'\fL'):
> > -                return c.replace('-', r'\-')
> > -            else:
> > -                return '-'
> > -
> > -        if c == '\\':
> > -            return r'\e'
> > -        elif c == '"':
> > -            return r'\(dq'
> > -        elif c == "'":
> > -            return r'\(cq'
> > -        elif c == ".":
> > -            if escape_dot:
> > -                # groff(7) says that . can be escaped by \. but in
> practice
> > -                # groff still gives an error with \. at the beginning
> of a
> > -                # line.
> > -                return r'\[char46]'
> > -            else:
> > -                return '.'
> > -        else:
> > -            raise error.Error("bad escape")
> > -
> > -    # Escape - \ " ' . as needed by nroff.
> > -    s = re.sub('(-[0-9]|--|[-"\'\\\\.])', escape, s)
> > -    return s
> > -
> > -
> > -def escape_nroff_literal(s, font=r'\fB'):
> > -    return font + r'%s\fR' % text_to_nroff(s, font)
> > -
> > -
> > -def inline_xml_to_nroff(node, font, to_upper=False, newline='\n'):
> > -    if node.nodeType == node.TEXT_NODE:
> > -        if to_upper:
> > -            s = text_to_nroff(node.data.upper(), font)
> > -        else:
> > -            s = text_to_nroff(node.data, font)
> > -        return s.replace('\n', newline)
> > -    elif node.nodeType == node.ELEMENT_NODE:
> > -        if node.tagName in ['code', 'em', 'option', 'env', 'b']:
> > -            s = r'\fB'
> > -            for child in node.childNodes:
> > -                s += inline_xml_to_nroff(child, r'\fB', to_upper,
> newline)
> > -            return s + font
> > -        elif node.tagName == 'ref':
> > -            if node.hasAttribute('column'):
> > -                s = node.attributes['column'].nodeValue
> > -                if node.hasAttribute('key'):
> > -                    s += ':' + node.attributes['key'].nodeValue
> > -            elif node.hasAttribute('table'):
> > -                s = node.attributes['table'].nodeValue
> > -            elif node.hasAttribute('group'):
> > -                s = node.attributes['group'].nodeValue
> > -            elif node.hasAttribute('db'):
> > -                s = node.attributes['db'].nodeValue
> > -            elif node.hasAttribute('field'):
> > -                s = node.attributes['field'].nodeValue
> > -            elif node.hasAttribute('section'):
> > -                s = node.attributes['section'].nodeValue
> > -            else:
> > -                raise error.Error("'ref' lacks required attributes: %s"
> > -                                  % list(node.attributes.keys()))
> > -            return r'\fB' + re.sub(r'\s+', ' ', s) + font
> > -        elif node.tagName in ['var', 'dfn', 'i', 'cite']:
> > -            s = r'\fI'
> > -            for child in node.childNodes:
> > -                s += inline_xml_to_nroff(child, r'\fI', to_upper,
> newline)
> > -            return s + font
> > -        elif node.tagName in ['literal']:
> > -            s = r'\fL'
> > -            for child in node.childNodes:
> > -                s += inline_xml_to_nroff(child, r'\fL')
> > -            return s + font
> > -        elif node.tagName == 'url':
> > -            return ('\n.URL "'
> > -                    + text_to_nroff(node.attributes['href'].nodeValue,
> > -                                    escape_dot=False)
> > -                    + '"\n')
> > -        else:
> > -            raise error.Error("element <%s> unknown or invalid here"
> > -                              % node.tagName)
> > -    elif node.nodeType == node.COMMENT_NODE:
> > -        return ''
> > -    else:
> > -        raise error.Error("unknown node %s in inline xml" % node)
> > -
> > -
> > -def pre_to_nroff(nodes, para, font):
> > -    # This puts 'font' at the beginning of each line so that leading and
> > -    # trailing whitespace stripping later doesn't removed leading spaces
> > -    # from preformatted text.
> > -    s = para + '\n.nf\n' + font
> > -    for node in nodes:
> > -        s += inline_xml_to_nroff(node, font, False, '\n.br\n' + font)
> + '\\fR'
> > -    s += '\n.fi\n'
> > -    return s
> > -
> > -
> > -def tbl_to_nroff(nodes, para):
> > -    s = para + '\n.TS\n'
> > -    for node in nodes:
> > -        if node.nodeType != node.TEXT_NODE:
> > -            fatal("<tbl> element may only have text children")
> > -        s += node.data + '\n'
> > -    s += '.TE\n'
> > -    return s
> > -
> > -
> > -def fatal(msg):
> > -    sys.stderr.write('%s\n' % msg)
> > -    sys.exit(1)
> > -
> > -
> > -def put_text(text, x, y, s):
> > -    x = int(x)
> > -    y = int(y)
> > -    extend = x + len(s) - len(text[y])
> > -    if extend > 0:
> > -        text[y] += ' ' * extend
> > -    text[y] = text[y][:x] + s + text[y][x + len(s):]
> > -
> > -
> > -def put_centered(text, x, width, y, s):
> > -    put_text(text, x + (width - len(s)) / 2, y, s)
> > -
> > -
> > -def diagram_header_to_nroff(header_node, text, x):
> > -    # Parse header.
> > -    header_fields = []
> > -    i = 0
> > -    for node in header_node.childNodes:
> > -        if node.nodeType == node.ELEMENT_NODE and node.tagName ==
> 'bits':
> > -            name = node.attributes['name'].nodeValue
> > -            width = node.attributes['width'].nodeValue
> > -            above = node.getAttribute('above')
> > -            below = node.getAttribute('below')
> > -            fill = node.getAttribute('fill')
> > -            header_fields += [{"name": name,
> > -                              "tag": "B%d" % i,
> > -                              "width": width,
> > -                              "above": above,
> > -                              "below": below,
> > -                              "fill": fill}]
> > -            i += 1
> > -        elif node.nodeType == node.COMMENT_NODE:
> > -            pass
> > -        elif node.nodeType == node.TEXT_NODE and node.data.isspace():
> > -            pass
> > -        else:
> > -            fatal("unknown node %s in diagram <header> element" % node)
> > -
> > -    # Format pic version.
> > -    pic_s = ""
> > -    for f in header_fields:
> > -        name = f['name'].replace('...', '. . .')
> > -        pic_s += "  %s: box \"%s\" width %s" % (f['tag'], name,
> f['width'])
> > -        if f['fill'] == 'yes':
> > -            pic_s += " fill"
> > -        pic_s += '\n'
> > -    for f in header_fields:
> > -        pic_s += "  \"%s\" at %s.n above\n" % (f['above'], f['tag'])
> > -        pic_s += "  \"%s\" at %s.s below\n" % (f['below'], f['tag'])
> > -    name = header_node.getAttribute('name')
> > -    if name == "":
> > -        visible = " invis"
> > -    else:
> > -        visible = ""
> > -    pic_s += "line <->%s \"%s\" above " % (visible, name)
> > -    pic_s += "from %s.nw + (0,textht) " % header_fields[0]['tag']
> > -    pic_s += "to %s.ne + (0,textht)\n" % header_fields[-1]['tag']
> > -
> > -    # Format text version.
> > -    header_width = 1
> > -    for f in header_fields:
> > -        field_width = max(len(f['above']), len(f['below']),
> len(f['name']))
> > -        f['width'] = field_width
> > -        header_width += field_width + 1
> > -    min_header_width = 2 + len(name)
> > -    while min_header_width > header_width:
> > -        for f in header_fields:
> > -            f['width'] += 1
> > -            header_width += 1
> > -            if header_width >= min_header_width:
> > -                break
> > -
> > -    if name != "":
> > -        put_centered(text, x, header_width, 0, name)
> > -        if header_width >= 4:
> > -            arrow = '<' + '-' * (header_width - 4) + '>'
> > -            put_text(text, x + 1, 1, arrow)
> > -    for f in header_fields:
> > -        box1 = '+' + '-' * f['width'] + '+'
> > -        box2 = '|' + ' ' * f['width'] + '|'
> > -        put_text(text, x, 3, box1)
> > -        put_text(text, x, 4, box2)
> > -        put_text(text, x, 5, box1)
> > -
> > -        put_centered(text, x + 1, f['width'], 2, f['above'])
> > -        put_centered(text, x + 1, f['width'], 4, f['name'])
> > -        put_centered(text, x + 1, f['width'], 6, f['below'])
> > -
> > -        x += f['width'] + 1
> > -
> > -    return pic_s, x + 1
> > -
> > -
> > -def diagram_to_nroff(nodes, para):
> > -    pic_s = ''
> > -    text = [''] * 7
> > -    x = 0
> > -    move = False
> > -    for node in nodes:
> > -        if node.nodeType == node.ELEMENT_NODE and node.tagName ==
> 'header':
> > -            if move:
> > -                pic_s += "move .1\n"
> > -                x += 1
> > -            elif x > 0:
> > -                x -= 1
> > -            pic_header, x = diagram_header_to_nroff(node, text, x)
> > -            pic_s += "[\n" + pic_header + "]\n"
> > -            move = True
> > -        elif node.nodeType == node.ELEMENT_NODE and node.tagName ==
> 'nospace':
> > -            move = False
> > -        elif node.nodeType == node.ELEMENT_NODE and node.tagName ==
> 'dots':
> > -            pic_s += "move .1\n"
> > -            pic_s += '". . ." ljust\n'
> > -
> > -            put_text(text, x, 4, " ... ")
> > -            x += 5
> > -        elif node.nodeType == node.COMMENT_NODE:
> > -            pass
> > -        elif node.nodeType == node.TEXT_NODE and node.data.isspace():
> > -            pass
> > -        else:
> > -            fatal("unknown node %s in diagram <header> element" % node)
> > -
> > -    text_s = '.br\n'.join(["\\fL%s\n" % s for s in text if s != ""])
> > -    return para + """
> > -.\\" check if in troff mode (TTY)
> > -.if t \\{
> > -.PS
> > -boxht = .2
> > -textht = 1/6
> > -fillval = .2
> > -""" + pic_s + """\
> > -.PE
> > -\\}
> > -.\\" check if in nroff mode:
> > -.if n \\{
> > -.nf
> > -""" + text_s + """\
> > -.fi
> > -\\}"""
> > -
> > -
> > -def block_xml_to_nroff(nodes, para='.PP'):
> > -    HEADER_TAGS = ('h1', 'h2', 'h3', 'h4')
> > -    s = ''
> > -    prev = ''
> > -    for node in nodes:
> > -        if node.nodeType == node.TEXT_NODE:
> > -            if s == '' and para != '.IP':
> > -                s = para + '\n'
> > -            text = re.sub(r'\s+', ' ', node.data)
> > -            if s.endswith(' '):
> > -                text = text.lstrip()
> > -            s += text_to_nroff(text)
> > -            s = s.lstrip()
> > -        elif node.nodeType == node.ELEMENT_NODE:
> > -            if node.tagName in ['ul', 'ol']:
> > -                if s != "":
> > -                    s += "\n"
> > -                s += ".RS\n"
> > -                i = 0
> > -                for li_node in node.childNodes:
> > -                    if (li_node.nodeType == node.ELEMENT_NODE
> > -                        and li_node.tagName == 'li'):
> > -                        i += 1
> > -                        if node.tagName == 'ul':
> > -                            s += ".IP \\(bu\n"
> > -                        else:
> > -                            s += ".IP %d. .4in\n" % i
> > -                        s += block_xml_to_nroff(li_node.childNodes,
> ".IP")
> > -                    elif li_node.nodeType == node.COMMENT_NODE:
> > -                        pass
> > -                    elif (li_node.nodeType != node.TEXT_NODE
> > -                          or not li_node.data.isspace()):
> > -                        raise error.Error("<%s> element may only have "
> > -                                          "<li> children" %
> node.tagName)
> > -                s += ".RE\n"
> > -            elif node.tagName == 'dl':
> > -                indent = True
> > -                if prev in HEADER_TAGS:
> > -                    indent = False
> > -                if s != "":
> > -                    s += "\n"
> > -                if indent:
> > -                    s += ".RS\n"
> > -                prev = "dd"
> > -                for li_node in node.childNodes:
> > -                    if (li_node.nodeType == node.ELEMENT_NODE
> > -                        and li_node.tagName == 'dt'):
> > -                        if prev == 'dd':
> > -                            s += '.TP\n'
> > -                        else:
> > -                            s += '.TQ .5in\n'
> > -                        prev = 'dt'
> > -                    elif (li_node.nodeType == node.ELEMENT_NODE
> > -                          and li_node.tagName == 'dd'):
> > -                        if prev == 'dd':
> > -                            s += '.IP\n'
> > -                        prev = 'dd'
> > -                    elif li_node.nodeType == node.COMMENT_NODE:
> > -                        continue
> > -                    elif (li_node.nodeType != node.TEXT_NODE
> > -                          or not li_node.data.isspace()):
> > -                        raise error.Error("<dl> element may only have "
> > -                                          "<dt> and <dd> children")
> > -                    s += block_xml_to_nroff(li_node.childNodes, ".IP")
> > -                if indent:
> > -                    s += ".RE\n"
> > -            elif node.tagName == 'p':
> > -                if s != "":
> > -                    if not s.endswith("\n"):
> > -                        s += "\n"
> > -                    s += para + "\n"
> > -                s += block_xml_to_nroff(node.childNodes, para)
> > -            elif node.tagName in HEADER_TAGS:
> > -                if s != "":
> > -                    if not s.endswith("\n"):
> > -                        s += "\n"
> > -                nroffTag, font = {'h1': ('SH', r'\fR'),
> > -                                  'h2': ('SS', r'\fB'),
> > -                                  'h3': ('ST', r'\fI'),
> > -                                  'h4': ('SU', r'\fI')}[node.tagName]
> > -                to_upper = node.tagName == 'h1'
> > -                s += ".%s \"" % nroffTag
> > -                for child_node in node.childNodes:
> > -                    s += inline_xml_to_nroff(child_node, font, to_upper)
> > -                s += "\"\n"
> > -            elif node.tagName == 'pre':
> > -                fixed = node.getAttribute('fixed')
> > -                if fixed == 'yes':
> > -                    font = r'\fL'
> > -                else:
> > -                    font = r'\fB'
> > -                s += pre_to_nroff(node.childNodes, para, font)
> > -            elif node.tagName == 'tbl':
> > -                s += tbl_to_nroff(node.childNodes, para)
> > -            elif node.tagName == 'diagram':
> > -                s += diagram_to_nroff(node.childNodes, para)
> > -            else:
> > -                s += inline_xml_to_nroff(node, r'\fR')
> > -            prev = node.tagName
> > -        elif node.nodeType == node.COMMENT_NODE:
> > -            pass
> > -        else:
> > -            raise error.Error("unknown node %s in block xml" % node)
> > -    if s != "" and not s.endswith('\n'):
> > -        s += '\n'
> > -    return s
> > diff --git a/python/build/soutil.py b/python/build/soutil.py
> > deleted file mode 100755
> > index b8027af86..000000000
> > --- a/python/build/soutil.py
> > +++ /dev/null
> > @@ -1,56 +0,0 @@
> > -#! /usr/bin/env python
> > -
> > -# Copyright (c) 2008, 2017 Nicira, Inc.
> > -#
> > -# Licensed under the Apache License, Version 2.0 (the "License");
> > -# you may not use this file except in compliance with the License.
> > -# You may obtain a copy of the License at:
> > -#
> > -#     http://www.apache.org/licenses/LICENSE-2.0
> > -#
> > -# Unless required by applicable law or agreed to in writing, software
> > -# distributed under the License is distributed on an "AS IS" BASIS,
> > -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> > -# See the License for the specific language governing permissions and
> > -# limitations under the License.
> > -
> > -import getopt
> > -import os
> > -import re
> > -import sys
> > -
> > -
> > -def parse_include_dirs():
> > -    include_dirs = []
> > -    options, args = getopt.gnu_getopt(sys.argv[1:], 'I:', ['include='])
> > -    for key, value in options:
> > -        if key in ['-I', '--include']:
> > -            include_dirs.append(value)
> > -        else:
> > -            assert False
> > -
> > -    include_dirs.append('.')
> > -    return include_dirs, args
> > -
> > -
> > -def find_file(include_dirs, name):
> > -    for dir in include_dirs:
> > -        file = "%s/%s" % (dir, name)
> > -        try:
> > -            os.stat(file)
> > -            return file
> > -        except OSError:
> > -            pass
> > -    sys.stderr.write("%s not found in: %s\n" % (name, '
> '.join(include_dirs)))
> > -    return None
> > -
> > -
> > -so_re = re.compile(r'^\.so (\S+)$')
> > -
> > -
> > -def extract_include_directive(line):
> > -    m = so_re.match(line)
> > -    if m:
> > -        return m.group(1)
> > -    else:
> > -        return None
> > diff --git a/python/ovs/.gitignore b/python/ovs/.gitignore
> > deleted file mode 100644
> > index 985278646..000000000
> > --- a/python/ovs/.gitignore
> > +++ /dev/null
> > @@ -1 +0,0 @@
> > -version.py
> > diff --git a/python/ovs/__init__.py b/python/ovs/__init__.py
> > deleted file mode 100644
> > index 218d8921e..000000000
> > --- a/python/ovs/__init__.py
> > +++ /dev/null
> > @@ -1 +0,0 @@
> > -# This file intentionally left blank.
> > diff --git a/python/ovs/_json.c b/python/ovs/_json.c
> > deleted file mode 100644
> > index ef7bb4b8e..000000000
> > --- a/python/ovs/_json.c
> > +++ /dev/null
> > @@ -1,269 +0,0 @@
> > -#include "Python.h"
> > -#include <openvswitch/json.h>
> > -#include "structmember.h"
> > -
> > -#if PY_MAJOR_VERSION >= 3
> > -#define IS_PY3K
> > -#endif
> > -
> > -typedef struct {
> > -    PyObject_HEAD
> > -    struct json_parser *_parser;
> > -} json_ParserObject;
> > -
> > -static void
> > -Parser_dealloc(json_ParserObject * p)
> > -{
> > -    json_parser_abort(p->_parser);
> > -    Py_TYPE(p)->tp_free(p);
> > -}
> > -
> > -static PyObject *
> > -Parser_new(PyTypeObject * type, PyObject * args, PyObject * kwargs)
> > -{
> > -    json_ParserObject *self;
> > -    static char *kwlist[] = { "check_trailer", NULL };
> > -    PyObject *check_trailer = NULL;
> > -    int ct_int = 0;
> > -
> > -    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist,
> > -                                     &check_trailer)) {
> > -        return NULL;
> > -    }
> > -
> > -    if (check_trailer != NULL) {
> > -        ct_int = PyObject_IsTrue(check_trailer);
> > -        if (ct_int < 0) {
> > -            return NULL;
> > -        } else if (ct_int) {
> > -            ct_int = JSPF_TRAILER;
> > -        }
> > -    }
> > -
> > -    self = (json_ParserObject *) type->tp_alloc(type, 0);
> > -    if (self != NULL) {
> > -        self->_parser = json_parser_create(ct_int);
> > -    }
> > -
> > -    return (PyObject *) self;
> > -}
> > -
> > -static PyObject *
> > -Parser_feed(json_ParserObject * self, PyObject * args)
> > -{
> > -    Py_ssize_t input_sz;
> > -    PyObject *input;
> > -    size_t rd;
> > -    char *input_str;
> > -
> > -    if (self->_parser == NULL) {
> > -        return NULL;
> > -    }
> > -
> > -    if (!PyArg_UnpackTuple(args, "input", 1, 1, &input)) {
> > -        return NULL;
> > -    }
> > -#ifdef IS_PY3K
> > -    if ((input_str = PyUnicode_AsUTF8AndSize(input, &input_sz)) ==
> NULL) {
> > -#else
> > -    if (PyString_AsStringAndSize(input, &input_str, &input_sz) < 0) {
> > -#endif
> > -        return NULL;
> > -    }
> > -
> > -    rd = json_parser_feed(self->_parser, input_str, (size_t) input_sz);
> > -
> > -#ifdef IS_PY3K
> > -    return PyLong_FromSize_t(rd);
> > -#else
> > -    return PyInt_FromSize_t(rd);
> > -#endif
> > -}
> > -
> > -static PyObject *
> > -Parser_is_done(json_ParserObject * self)
> > -{
> > -    if (self->_parser == NULL) {
> > -        return NULL;
> > -    }
> > -    return PyBool_FromLong(json_parser_is_done(self->_parser));
> > -}
> > -
> > -static PyObject *
> > -json_to_python(struct json *json)
> > -{
> > -    switch (json->type) {
> > -    case JSON_NULL:
> > -        Py_RETURN_NONE;
> > -    case JSON_FALSE:
> > -        Py_RETURN_FALSE;
> > -    case JSON_TRUE:
> > -        Py_RETURN_TRUE;
> > -    case JSON_OBJECT:{
> > -            struct shash_node *node;
> > -            PyObject *dict = PyDict_New();
> > -
> > -            if (dict == NULL) {
> > -                return PyErr_NoMemory();
> > -            }
> > -            SHASH_FOR_EACH (node, json->object) {
> > -                PyObject *key = PyUnicode_FromString(node->name);
> > -                PyObject *val = json_to_python(node->data);
> > -
> > -                if (!(key && val) || PyDict_SetItem(dict, key, val)) {
> > -                    Py_XDECREF(key);
> > -                    Py_XDECREF(val);
> > -                    Py_XDECREF(dict);
> > -                    return NULL;
> > -                }
> > -
> > -                Py_XDECREF(key);
> > -                Py_XDECREF(val);
> > -            }
> > -            return dict;
> > -        }
> > -    case JSON_ARRAY:{
> > -            int i;
> > -            PyObject *arr = PyList_New(json->array.n);
> > -
> > -            if (arr == NULL) {
> > -                return PyErr_NoMemory();
> > -            }
> > -            for (i = 0; i < json->array.n; i++) {
> > -                PyObject *item = json_to_python(json->array.elems[i]);
> > -
> > -                if (!item || PyList_SetItem(arr, i, item)) {
> > -                    Py_XDECREF(arr);
> > -                    return NULL;
> > -                }
> > -            }
> > -            return arr;
> > -        }
> > -    case JSON_REAL:
> > -        if (json->real != 0) {
> > -            return PyFloat_FromDouble(json->real);
> > -        } /* fall through to treat 0 as int */
> > -    case JSON_INTEGER:
> > -#ifdef IS_PY3K
> > -        return PyLong_FromLong((long) json->integer);
> > -#else
> > -        return PyInt_FromLong((long) json->integer);
> > -#endif
> > -
> > -    case JSON_STRING:
> > -        return PyUnicode_FromString(json->string);
> > -    default:
> > -        return NULL;
> > -    }
> > -}
> > -
> > -static PyObject *
> > -Parser_finish(json_ParserObject * self)
> > -{
> > -    struct json *json;
> > -    PyObject *obj;
> > -
> > -    if (self->_parser == NULL) {
> > -        return NULL;
> > -    }
> > -
> > -    json = json_parser_finish(self->_parser);
> > -    self->_parser = NULL;
> > -    obj = json_to_python(json);
> > -    json_destroy(json);
> > -    return obj;
> > -}
> > -
> > -static PyMethodDef Parser_methods[] = {
> > -    {"feed", (PyCFunction) Parser_feed, METH_VARARGS,
> > -     "Feed data to the parser and return the index of the last
> object."},
> > -    {"is_done", (PyCFunction) Parser_is_done, METH_NOARGS,
> > -     "Whether the parser has finished decoding an object."},
> > -    {"finish", (PyCFunction) Parser_finish, METH_NOARGS,
> > -     "Finish parsing and return Python object parsed."},
> > -    {NULL},
> > -};
> > -
> > -static PyTypeObject json_ParserType = {
> > -    PyVarObject_HEAD_INIT(NULL, 0)
> > -        "ovs._json.Parser",     /* tp_name */
> > -    sizeof (json_ParserObject), /* tp_basicsize */
> > -    0,                          /* tp_itemsize */
> > -    (destructor) Parser_dealloc,        /* tp_dealloc */
> > -    0,                          /* tp_print */
> > -    0,                          /* tp_getattr */
> > -    0,                          /* tp_setattr */
> > -    0,                          /* tp_compare */
> > -    0,                          /* tp_repr */
> > -    0,                          /* tp_as_number */
> > -    0,                          /* tp_as_sequence */
> > -    0,                          /* tp_as_mapping */
> > -    0,                          /* tp_hash */
> > -    0,                          /* tp_call */
> > -    0,                          /* tp_str */
> > -    0,                          /* tp_getattro */
> > -    0,                          /* tp_setattro */
> > -    0,                          /* tp_as_buffer */
> > -    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */
> > -    "Parser objects",           /* tp_doc */
> > -    0,                          /* tp_traverse */
> > -    0,                          /* tp_clear */
> > -    0,                          /* tp_richcompare */
> > -    0,                          /* tp_weaklistoffset */
> > -    0,                          /* tp_iter */
> > -    0,                          /* tp_iternext */
> > -    Parser_methods,             /* tp_methods */
> > -    0,                          /* tp_members */
> > -    0,                          /* tp_getset */
> > -    0,                          /* tp_base */
> > -    0,                          /* tp_dict */
> > -    0,                          /* tp_descr_get */
> > -    0,                          /* tp_descr_set */
> > -    0,                          /* tp_dictoffset */
> > -    0,                          /* tp_init */
> > -    0,                          /* tp_alloc */
> > -    Parser_new,                 /* tp_new */
> > -};
> > -
> > -#ifdef IS_PY3K
> > -static struct PyModuleDef moduledef = {
> > -    PyModuleDef_HEAD_INIT,
> > -    "ovs._json",                /* m_name */
> > -    "OVS JSON Parser module",   /* m_doc */
> > -    0,                          /* m_size */
> > -    0,                          /* m_methods */
> > -    0,                          /* m_slots */
> > -    0,                          /* m_traverse */
> > -    0,                          /* m_clear */
> > -    0,                          /* m_free */
> > -};
> > -
> > -#define INITERROR return NULL
> > -#else /* !IS_PY3K */
> > -#define INITERROR return
> > -#endif
> > -
> > -PyMODINIT_FUNC
> > -#ifdef IS_PY3K
> > -PyInit__json(void)
> > -#else
> > -init_json(void)
> > -#endif
> > -{
> > -    PyObject *m;
> > -
> > -    if (PyType_Ready(&json_ParserType) < 0) {
> > -        INITERROR;
> > -    }
> > -#ifdef IS_PY3K
> > -    m = PyModule_Create(&moduledef);
> > -#else
> > -    m = Py_InitModule3("ovs._json", NULL, "OVS JSON Parser module");
> > -#endif
> > -
> > -    Py_INCREF(&json_ParserType);
> > -    PyModule_AddObject(m, "Parser", (PyObject *) & json_ParserType);
> > -#ifdef IS_PY3K
> > -    return m;
> > -#endif
> > -}
> > diff --git a/python/ovs/compat/__init__.py
> b/python/ovs/compat/__init__.py
> > deleted file mode 100644
> > index e69de29bb..000000000
> > diff --git a/python/ovs/compat/sortedcontainers/LICENSE
> b/python/ovs/compat/sortedcontainers/LICENSE
> > deleted file mode 100644
> > index 8794014e0..000000000
> > --- a/python/ovs/compat/sortedcontainers/LICENSE
> > +++ /dev/null
> > @@ -1,13 +0,0 @@
> > -Copyright 2014-2016 Grant Jenks
> > -
> > -Licensed under the Apache License, Version 2.0 (the "License");
> > -you may not use this file except in compliance with the License.
> > -You may obtain a copy of the License at
> > -
> > -    http://www.apache.org/licenses/LICENSE-2.0
> > -
> > -Unless required by applicable law or agreed to in writing, software
> > -distributed under the License is distributed on an "AS IS" BASIS,
> > -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> > -See the License for the specific language governing permissions and
> > -limitations under the License.
> > diff --git a/python/ovs/compat/sortedcontainers/__init__.py
> b/python/ovs/compat/sortedcontainers/__init__.py
> > deleted file mode 100644
> > index 392adfad6..000000000
> > --- a/python/ovs/compat/sortedcontainers/__init__.py
> > +++ /dev/null
> > @@ -1,52 +0,0 @@
> > -"""Sorted Container Types: SortedList, SortedDict, SortedSet
> > -
> > -SortedContainers is an Apache2 licensed containers library, written in
> > -pure-Python, and fast as C-extensions.
> > -
> > -
> > -Python's standard library is great until you need a sorted collections
> > -type. Many will attest that you can get really far without one, but the
> moment
> > -you **really need** a sorted list, dict, or set, you're faced with a
> dozen
> > -different implementations, most using C-extensions without great
> documentation
> > -and benchmarking.
> > -
> > -In Python, we can do better. And we can do it in pure-Python!
> > -
> > -::
> > -
> > -    >>> from sortedcontainers import SortedList, SortedDict, SortedSet
> > -    >>> sl = SortedList(xrange(10000000))
> > -    >>> 1234567 in sl
> > -    True
> > -    >>> sl[7654321]
> > -    7654321
> > -    >>> sl.add(1234567)
> > -    >>> sl.count(1234567)
> > -    2
> > -    >>> sl *= 3
> > -    >>> len(sl)
> > -    30000003
> > -
> > -SortedContainers takes all of the work out of Python sorted types -
> making your
> > -deployment and use of Python easy. There's no need to install a C
> compiler or
> > -pre-build and distribute custom extensions. Performance is a feature and
> > -testing has 100% coverage with unit tests and hours of stress.
> > -
> > -:copyright: (c) 2016 by Grant Jenks.
> > -:license: Apache 2.0, see LICENSE for more details.
> > -
> > -"""
> > -
> > -
> > -from .sortedlist import SortedList, SortedListWithKey
> > -from .sortedset import SortedSet
> > -from .sorteddict import SortedDict
> > -
> > -__all__ = ['SortedList', 'SortedSet', 'SortedDict', 'SortedListWithKey']
> > -
> > -__title__ = 'sortedcontainers'
> > -__version__ = '1.5.9'
> > -__build__ = 0x010509
> > -__author__ = 'Grant Jenks'
> > -__license__ = 'Apache 2.0'
> > -__copyright__ = 'Copyright 2016 Grant Jenks'
> > diff --git a/python/ovs/compat/sortedcontainers/sorteddict.py
> b/python/ovs/compat/sortedcontainers/sorteddict.py
> > deleted file mode 100644
> > index 5d425fee6..000000000
> > --- a/python/ovs/compat/sortedcontainers/sorteddict.py
> > +++ /dev/null
> > @@ -1,741 +0,0 @@
> > -"""Sorted dictionary implementation.
> > -
> > -"""
> > -
> > -from collections import Set, Sequence
> > -from collections import KeysView as AbstractKeysView
> > -from collections import ValuesView as AbstractValuesView
> > -from collections import ItemsView as AbstractItemsView
> > -from sys import hexversion
> > -
> > -from .sortedlist import SortedList, recursive_repr, SortedListWithKey
> > -from .sortedset import SortedSet
> > -
> > -NONE = object()
> > -
> > -
> > -class _IlocWrapper(object):
> > -    "Positional indexing support for sorted dictionary objects."
> > -    # pylint: disable=protected-access, too-few-public-methods
> > -    def __init__(self, _dict):
> > -        self._dict = _dict
> > -    def __len__(self):
> > -        return len(self._dict)
> > -    def __getitem__(self, index):
> > -        """
> > -        Very efficiently return the key at index *index* in iteration.
> Supports
> > -        negative indices and slice notation. Raises IndexError on
> invalid
> > -        *index*.
> > -        """
> > -        return self._dict._list[index]
> > -    def __delitem__(self, index):
> > -        """
> > -        Remove the ``sdict[sdict.iloc[index]]`` from *sdict*. Supports
> negative
> > -        indices and slice notation. Raises IndexError on invalid
> *index*.
> > -        """
> > -        _dict = self._dict
> > -        _list = _dict._list
> > -        _delitem = _dict._delitem
> > -
> > -        if isinstance(index, slice):
> > -            keys = _list[index]
> > -            del _list[index]
> > -            for key in keys:
> > -                _delitem(key)
> > -        else:
> > -            key = _list[index]
> > -            del _list[index]
> > -            _delitem(key)
> > -
> > -
> > -class SortedDict(dict):
> > -    """SortedDict provides the same methods as a dict.  Additionally,
> SortedDict
> > -    efficiently maintains its keys in sorted order. Consequently, the
> keys
> > -    method will return the keys in sorted order, the popitem method
> will remove
> > -    the item with the highest key, etc.
> > -
> > -    """
> > -    def __init__(self, *args, **kwargs):
> > -        """SortedDict provides the same methods as a dict.
> Additionally, SortedDict
> > -        efficiently maintains its keys in sorted order. Consequently,
> the keys
> > -        method will return the keys in sorted order, the popitem method
> will
> > -        remove the item with the highest key, etc.
> > -
> > -        An optional *key* argument defines a callable that, like the
> `key`
> > -        argument to Python's `sorted` function, extracts a comparison
> key from
> > -        each dict key. If no function is specified, the default
> compares the
> > -        dict keys directly. The `key` argument must be provided as a
> positional
> > -        argument and must come before all other arguments.
> > -
> > -        An optional *iterable* argument provides an initial series of
> items to
> > -        populate the SortedDict.  Each item in the series must itself
> contain
> > -        two items.  The first is used as a key in the new dictionary,
> and the
> > -        second as the key's value. If a given key is seen more than
> once, the
> > -        last value associated with it is retained in the new dictionary.
> > -
> > -        If keyword arguments are given, the keywords themselves with
> their
> > -        associated values are added as items to the dictionary. If a
> key is
> > -        specified both in the positional argument and as a keyword
> argument, the
> > -        value associated with the keyword is retained in the
> dictionary. For
> > -        example, these all return a dictionary equal to ``{"one": 2,
> "two":
> > -        3}``:
> > -
> > -        * ``SortedDict(one=2, two=3)``
> > -        * ``SortedDict({'one': 2, 'two': 3})``
> > -        * ``SortedDict(zip(('one', 'two'), (2, 3)))``
> > -        * ``SortedDict([['two', 3], ['one', 2]])``
> > -
> > -        The first example only works for keys that are valid Python
> > -        identifiers; the others work with any valid keys.
> > -
> > -        """
> > -        # pylint: disable=super-init-not-called
> > -        if args and (args[0] is None or callable(args[0])):
> > -            self._key = args[0]
> > -            args = args[1:]
> > -        else:
> > -            self._key = None
> > -
> > -        if self._key is None:
> > -            self._list = SortedList()
> > -        else:
> > -            self._list = SortedListWithKey(key=self._key)
> > -
> > -        # Cache function pointers to dict methods.
> > -
> > -        _dict = super(SortedDict, self)
> > -        self._dict = _dict
> > -        self._clear = _dict.clear
> > -        self._delitem = _dict.__delitem__
> > -        self._iter = _dict.__iter__
> > -        self._pop = _dict.pop
> > -        self._setdefault = _dict.setdefault
> > -        self._setitem = _dict.__setitem__
> > -        self._dict_update = _dict.update
> > -
> > -        # Cache function pointers to SortedList methods.
> > -
> > -        _list = self._list
> > -        self._list_add = _list.add
> > -        self.bisect_left = _list.bisect_left
> > -        self.bisect = _list.bisect_right
> > -        self.bisect_right = _list.bisect_right
> > -        self._list_clear = _list.clear
> > -        self.index = _list.index
> > -        self._list_pop = _list.pop
> > -        self._list_remove = _list.remove
> > -        self._list_update = _list.update
> > -        self.irange = _list.irange
> > -        self.islice = _list.islice
> > -        self._reset = _list._reset  # pylint: disable=protected-access
> > -
> > -        if self._key is not None:
> > -            self.bisect_key_left = _list.bisect_key_left
> > -            self.bisect_key_right = _list.bisect_key_right
> > -            self.bisect_key = _list.bisect_key
> > -            self.irange_key = _list.irange_key
> > -
> > -        self.iloc = _IlocWrapper(self)
> > -
> > -        self._update(*args, **kwargs)
> > -
> > -    @property
> > -    def key(self):
> > -        """Key function used to extract comparison key for sorting."""
> > -        return self._key
> > -
> > -    def clear(self):
> > -        """Remove all elements from the dictionary."""
> > -        self._clear()
> > -        self._list_clear()
> > -
> > -    def __delitem__(self, key):
> > -        """
> > -        Remove ``d[key]`` from *d*.  Raises a KeyError if *key* is not
> in the
> > -        dictionary.
> > -        """
> > -        self._delitem(key)
> > -        self._list_remove(key)
> > -
> > -    def __iter__(self):
> > -        """
> > -        Return an iterator over the sorted keys of the dictionary.
> > -
> > -        Iterating the Mapping while adding or deleting keys may raise a
> > -        `RuntimeError` or fail to iterate over all entries.
> > -        """
> > -        return iter(self._list)
> > -
> > -    def __reversed__(self):
> > -        """
> > -        Return a reversed iterator over the sorted keys of the
> dictionary.
> > -
> > -        Iterating the Mapping while adding or deleting keys may raise a
> > -        `RuntimeError` or fail to iterate over all entries.
> > -        """
> > -        return reversed(self._list)
> > -
> > -    def __setitem__(self, key, value):
> > -        """Set `d[key]` to *value*."""
> > -        if key not in self:
> > -            self._list_add(key)
> > -        self._setitem(key, value)
> > -
> > -    def copy(self):
> > -        """Return a shallow copy of the sorted dictionary."""
> > -        return self.__class__(self._key, self._iteritems())
> > -
> > -    __copy__ = copy
> > -
> > -    @classmethod
> > -    def fromkeys(cls, seq, value=None):
> > -        """
> > -        Create a new dictionary with keys from *seq* and values set to
> *value*.
> > -        """
> > -        return cls((key, value) for key in seq)
> > -
> > -    if hexversion < 0x03000000:
> > -        def items(self):
> > -            """
> > -            Return a list of the dictionary's items (``(key, value)``
> pairs).
> > -            """
> > -            return list(self._iteritems())
> > -    else:
> > -        def items(self):
> > -            """
> > -            Return a new ItemsView of the dictionary's items.  In
> addition to
> > -            the methods provided by the built-in `view` the ItemsView is
> > -            indexable (e.g. ``d.items()[5]``).
> > -            """
> > -            return ItemsView(self)
> > -
> > -    def iteritems(self):
> > -        """
> > -        Return an iterator over the items (``(key, value)`` pairs).
> > -
> > -        Iterating the Mapping while adding or deleting keys may raise a
> > -        `RuntimeError` or fail to iterate over all entries.
> > -        """
> > -        return iter((key, self[key]) for key in self._list)
> > -
> > -    _iteritems = iteritems
> > -
> > -    if hexversion < 0x03000000:
> > -        def keys(self):
> > -            """Return a SortedSet of the dictionary's keys."""
> > -            return SortedSet(self._list, key=self._key)
> > -    else:
> > -        def keys(self):
> > -            """
> > -            Return a new KeysView of the dictionary's keys.  In
> addition to the
> > -            methods provided by the built-in `view` the KeysView is
> indexable
> > -            (e.g. ``d.keys()[5]``).
> > -            """
> > -            return KeysView(self)
> > -
> > -    def iterkeys(self):
> > -        """
> > -        Return an iterator over the sorted keys of the Mapping.
> > -
> > -        Iterating the Mapping while adding or deleting keys may raise a
> > -        `RuntimeError` or fail to iterate over all entries.
> > -        """
> > -        return iter(self._list)
> > -
> > -    if hexversion < 0x03000000:
> > -        def values(self):
> > -            """Return a list of the dictionary's values."""
> > -            return list(self._itervalues())
> > -    else:
> > -        def values(self):
> > -            """
> > -            Return a new :class:`ValuesView` of the dictionary's values.
> > -            In addition to the methods provided by the built-in `view`
> the
> > -            ValuesView is indexable (e.g., ``d.values()[5]``).
> > -            """
> > -            return ValuesView(self)
> > -
> > -    def itervalues(self):
> > -        """
> > -        Return an iterator over the values of the Mapping.
> > -
> > -        Iterating the Mapping while adding or deleting keys may raise a
> > -        `RuntimeError` or fail to iterate over all entries.
> > -        """
> > -        return iter(self[key] for key in self._list)
> > -
> > -    _itervalues = itervalues
> > -
> > -    def pop(self, key, default=NONE):
> > -        """
> > -        If *key* is in the dictionary, remove it and return its value,
> > -        else return *default*. If *default* is not given and *key* is
> not in
> > -        the dictionary, a KeyError is raised.
> > -        """
> > -        if key in self:
> > -            self._list_remove(key)
> > -            return self._pop(key)
> > -        else:
> > -            if default is NONE:
> > -                raise KeyError(key)
> > -            else:
> > -                return default
> > -
> > -    def popitem(self, last=True):
> > -        """
> > -        Remove and return a ``(key, value)`` pair from the dictionary.
> If
> > -        last=True (default) then remove the *greatest* `key` from the
> > -        diciontary. Else, remove the *least* key from the dictionary.
> > -
> > -        If the dictionary is empty, calling `popitem` raises a
> > -        KeyError`.
> > -        """
> > -        if not self:
> > -            raise KeyError('popitem(): dictionary is empty')
> > -
> > -        key = self._list_pop(-1 if last else 0)
> > -        value = self._pop(key)
> > -
> > -        return (key, value)
> > -
> > -    def peekitem(self, index=-1):
> > -        """Return (key, value) item pair at index.
> > -
> > -        Unlike ``popitem``, the sorted dictionary is not modified. Index
> > -        defaults to -1, the last/greatest key in the dictionary. Specify
> > -        ``index=0`` to lookup the first/least key in the dictiony.
> > -
> > -        If index is out of range, raise IndexError.
> > -
> > -        """
> > -        key = self._list[index]
> > -        return key, self[key]
> > -
> > -    def setdefault(self, key, default=None):
> > -        """
> > -        If *key* is in the dictionary, return its value.  If not,
> insert *key*
> > -        with a value of *default* and return *default*.  *default*
> defaults to
> > -        ``None``.
> > -        """
> > -        if key in self:
> > -            return self[key]
> > -
> > -        self._setitem(key, default)
> > -        self._list_add(key)
> > -        return default
> > -
> > -    def update(self, *args, **kwargs):
> > -        """
> > -        Update the dictionary with the key/value pairs from *other*,
> overwriting
> > -        existing keys.
> > -
> > -        *update* accepts either another dictionary object or an
> iterable of
> > -        key/value pairs (as a tuple or other iterable of length two).
> If
> > -        keyword arguments are specified, the dictionary is then updated
> with
> > -        those key/value pairs: ``d.update(red=1, blue=2)``.
> > -        """
> > -        if not self:
> > -            self._dict_update(*args, **kwargs)
> > -            self._list_update(self._iter())
> > -            return
> > -
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to