Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Please login to access the resource
home:crameleon:misc
python-aggregate6
_service:obs_scm:aggregate6-1.0.12+git37.3ef93a...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:aggregate6-1.0.12+git37.3ef93ac.obscpio of Package python-aggregate6
07070100000000000081A4000000000000000000000001650CAEE4000000B4000000000000000000000000000000000000002C00000000aggregate6-1.0.12+git37.3ef93ac/.coveragerc# .coveragerc to control coverage.py [run] branch = True source = . [report] omit = */python?.?/* */site-packages/* *__init__* tests/* setup.py aggregate6/__init__.py 07070100000001000041ED000000000000000000000003650CAEE400000000000000000000000000000000000000000000002800000000aggregate6-1.0.12+git37.3ef93ac/.github07070100000002000041ED000000000000000000000002650CAEE400000000000000000000000000000000000000000000003200000000aggregate6-1.0.12+git37.3ef93ac/.github/workflows07070100000003000081A4000000000000000000000001650CAEE400000322000000000000000000000000000000000000004700000000aggregate6-1.0.12+git37.3ef93ac/.github/workflows/codeql-analysis.yamlname: CodeQL analysis on: push: pull_request: schedule: # build the main branch every Sunday evening - cron: '19 19 * * 0' workflow_dispatch: jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: language: [ 'python' ] steps: - name: Checkout repository uses: actions/checkout@v3 - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - name: Autobuild uses: github/codeql-action/autobuild@v2 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 with: category: "/language:${{matrix.language}}" 07070100000004000081A4000000000000000000000001650CAEE400000668000000000000000000000000000000000000004600000000aggregate6-1.0.12+git37.3ef93ac/.github/workflows/python-package.yamlname: Python package on: push: pull_request: workflow_dispatch: jobs: build: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12.0-rc.1"] exclude: - os: ubuntu-latest python-version: 3.6 - os: macos-latest python-version: 3.7 - os: macos-latest python-version: 3.8 - os: macos-latest python-version: 3.9 - os: macos-latest python-version: 3.10 - os: macos-latest python-version: 3.11 - os: macos-latest python-version: 3.12.0-rc.1 steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip pip install flake8 pytest if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Lint with flake8 run: | # Stop the build if there are Python syntax errors or undefined names flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # For now, treat all errors as warnings using --exit-zero flake8 . --count --exit-zero --max-complexity=10 --statistics - name: Set $PYTHONPATH run: echo "PYTHONPATH=$RUNNER_WORKSPACE/aggregate6" >> $GITHUB_ENV - name: Test with pytest run: pytest 07070100000005000081A4000000000000000000000001650CAEE4000002A3000000000000000000000000000000000000002B00000000aggregate6-1.0.12+git37.3ef93ac/.gitignore# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .cache nosetests.xml coverage.xml # Translations *.mo *.pot # Django stuff: *.log # Sphinx documentation docs/_build/ # PyBuilder target/ 07070100000006000081A4000000000000000000000001650CAEE400000525000000000000000000000000000000000000002800000000aggregate6-1.0.12+git37.3ef93ac/LICENSECopyright (c) 2014-2017, Job Snijders <job@instituut.net>. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 07070100000007000081A4000000000000000000000001650CAEE40000005D000000000000000000000000000000000000002C00000000aggregate6-1.0.12+git37.3ef93ac/MANIFEST.ininclude README.md include aggregate6.7 include requirements.txt recursive-include tests *.py 07070100000008000081A4000000000000000000000001650CAEE400000098000000000000000000000000000000000000002900000000aggregate6-1.0.12+git37.3ef93ac/Makefileall: cp README.md aggregate6.7.ronn ronn -r --pipe aggregate6.7.ronn > aggregate6.7 rm aggregate6.7.ronn clean: rm -rf *.egg *.egg-info dist build 07070100000009000081A4000000000000000000000001650CAEE400000B40000000000000000000000000000000000000002A00000000aggregate6-1.0.12+git37.3ef93ac/README.md[![Requirements Status](https://requires.io/github/job/aggregate6/requirements.svg?branch=master)](https://requires.io/github/job/aggregate6/requirements/?branch=master) [![Coverage Status](https://coveralls.io/repos/github/job/aggregate6/badge.svg?branch=master)](https://coveralls.io/github/job/aggregate6?branch=master) aggregate6 ========== aggregate6 will compress an unsorted list of IP prefixes (both IPv4 and IPv6). Description ----------- Takes a list of IPv6 prefixes in conventional format on stdin, and performs two optimisations to attempt to reduce the length of the prefix list. The first optimisation is to remove any supplied prefixes which are superfluous because they are already included in another supplied prefix. For example, `2001:67c:208c:10::/64` would be removed if `2001:67c:208c::/48` was also supplied. The second optimisation identifies adjacent prefixes that can be combined under a single, shorter-length prefix. For example, `2001:67c:208c::/48` and `2001:67c:208d::/48` can be combined into the single prefix `2001:67c:208c::/47`. The above optimalisation steps are often useful in context of compressing firewall rules or BGP prefix-list filters. The following command line options are available: ``` -4 Only output IPv4 prefixes -6 Only output IPv6 prefixes -h, --help show help message and exit -m N Sets the maximum prefix length for entries read, longer prefixes will be discarded prior to processing -t truncate IP/mask to network/mask -v Display verbose information about the optimisations -V Display aggregate6 version ``` Installation ------------ OpenBSD: `$ doas pkg_add aggregate6` CentOS/RHEL/Rocky: `$ yum install epel-release` `$ yum install aggregate6` Fedora: `$ dnf install aggregate6` Other platforms: `$ pip3 install aggregate6` CLI Usage --------- Either provide the list of IPv4 and IPv6 prefixes on STDIN, or give filenames containing lists of IPv4 and IPv6 prefixes as arguments. ``` $ # via STDIN $ cat file_with_list_of_prefixes | aggregate6 ... output ... $ # with a filename as argument $ aggregate6 file_with_list_of_prefixes [ ... optional_other_prefix_lists ] ... output ... $ # Whitespace separated works too $ echo 2001:67c:208c::/48 2000::/3 | aggregate6 2000::/3 $ # You can combine IPv4 and IPv6 $ echo 10.0.0.0/16 10.0.0.0/24 2000::/3 | aggregate6 10.0.0.0/16 2000::/3 ``` Library Usage ------------- Aggregate6 can be used in your own pyp/python2/python3 project as python module. Currently there is just one simple public function: `aggregate()` which takes a list as parameter. ``` >>> from aggregate6 import aggregate >>> aggregate(["10.0.0.0/8", "10.0.0.0/24"]) ['10.0.0.0/8'] >>> ``` Bugs ---- Please report bugs at https://github.com/job/aggregate6/issues Author ------ Job Snijders <job@instituut.net> 0707010000000A000041ED000000000000000000000002650CAEE400000000000000000000000000000000000000000000002B00000000aggregate6-1.0.12+git37.3ef93ac/aggregate60707010000000B000081A4000000000000000000000001650CAEE400000AB8000000000000000000000000000000000000002D00000000aggregate6-1.0.12+git37.3ef93ac/aggregate6.7.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "AGGREGATE6" "7" "December 2017" "" "" aggregate6 will compress an unsorted list of IP prefixes (both IPv4 and IPv6)\. . .SH "Description" Takes a list of IPv6 prefixes in conventional format on stdin, and performs two optimisations to attempt to reduce the length of the prefix list\. The first optimisation is to remove any supplied prefixes which are superfluous because they are already included in another supplied prefix\. For example, \fB2001:67c:208c:10::/64\fR would be removed if \fB2001:67c:208c::/48\fR was also supplied\. . .P The second optimisation identifies adjacent prefixes that can be combined under a single, shorter\-length prefix\. For example, \fB2001:67c:208c::/48\fR and \fB2001:67c:208d::/48\fR can be combined into the single prefix \fB2001:67c:208c::/47\fR\. . .P The above optimalisation steps are often useful in context of compressing firewall rules or BGP prefix\-list filters\. . .P The following command line options are available: . .IP "" 4 . .nf \-4 Only output IPv4 prefixes \-6 Only output IPv6 prefixes \-h, \-\-help show help message and exit \-m N Sets the maximum prefix length for entries read, longer prefixes will be discarded prior to processing \-t truncate IP/mask to network/mask \-v Display verbose information about the optimisations \-V Display aggregate6 version . .fi . .IP "" 0 . .SH "Installation" OpenBSD 6\.3: . .P \fB$ doas pkg_add aggregate6\fR . .P Other platforms: . .P \fB$ pip3 install aggregate6\fR . .SH "CLI Usage" Either provide the list of IPv4 and IPv6 prefixes on STDIN, or give filenames containing lists of IPv4 and IPv6 prefixes as arguments\. . .IP "" 4 . .nf $ # via STDIN $ cat file_with_list_of_prefixes | aggregate6 \.\.\. output \.\.\. $ # with a filename as argument $ aggregate6 file_with_list_of_prefixes [ \.\.\. optional_other_prefix_lists ] \.\.\. output \.\.\. $ # Whitespace separated works too $ echo 2001:67c:208c::/48 2000::/3 | aggregate6 2000::/3 $ # You can combine IPv4 and IPv6 $ echo 10\.0\.0\.0/16 10\.0\.0\.0/24 2000::/3 | aggregate6 10\.0\.0\.0/16 2000::/3 . .fi . .IP "" 0 . .SH "Library Usage" Aggregate6 can be used in your own pyp/python2/python3 project as python module\. Currently there is just one simple public function: \fBaggregate()\fR which takes a list as parameter\. . .IP "" 4 . .nf >>> import from aggregate6 import aggregate >>> aggregate(["10\.0\.0\.0/8", "10\.0\.0\.0/24"]) [\'10\.0\.0\.0/8\'] >>> . .fi . .IP "" 0 . .SH "Bugs" Please report bugs at https://github\.com/job/aggregate6/issues . .SH "Author" Job Snijders \fIjob@instituut\.net\fR 0707010000000C000081A4000000000000000000000001650CAEE400000117000000000000000000000000000000000000003700000000aggregate6-1.0.12+git37.3ef93ac/aggregate6/__init__.py__version__ = "1.0.12" __author__ = "Job Snijders" __author_email__ = "job@instituut.net" __copyright__ = "Copyright 2014-2017, Job Snijders" __license__ = "BSD 2-Clause" __status__ = "Development" __url__ = "https://github.com/job/aggregate6" from .aggregate6 import aggregate 0707010000000D000081A4000000000000000000000001650CAEE400000024000000000000000000000000000000000000003700000000aggregate6-1.0.12+git37.3ef93ac/aggregate6/__main__.pyfrom .aggregate6 import main main() 0707010000000E000081ED000000000000000000000001650CAEE400001A9A000000000000000000000000000000000000003900000000aggregate6-1.0.12+git37.3ef93ac/aggregate6/aggregate6.py#!/usr/bin/env python # Copyright (C) 2014-2017 Job Snijders <job@instituut.net> # # This file is part of aggregate6 # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. from __future__ import print_function from __future__ import unicode_literals try: from builtins import str as text except: # Python2.7 compatibility from __builtin__ import unicode as text from ipaddress import ip_network, ip_interface import aggregate6 import radix import sys def aggregate(l): """Aggregate a `list` of prefixes. Keyword arguments: l -- a python list of prefixes Example use: >>> aggregate(["10.0.0.0/8", "10.0.0.0/24"]) ['10.0.0.0/8'] """ tree = radix.Radix() for item in l: try: tree.add(item) except (ValueError) as err: raise Exception("ERROR: invalid IP prefix: {}".format(item)) return aggregate_tree(tree).prefixes() def aggregate_tree(l_tree): """Walk a py-radix tree and aggregate it. Arguments l_tree -- radix.Radix() object """ def _aggregate_phase1(tree): # phase1 removes any supplied prefixes which are superfluous because # they are already included in another supplied prefix. For example, # 2001:67c:208c:10::/64 would be removed if 2001:67c:208c::/48 was # also supplied. n_tree = radix.Radix() for prefix in tree.prefixes(): if tree.search_worst(prefix).prefix == prefix: n_tree.add(prefix) return n_tree def _aggregate_phase2(tree): # phase2 identifies adjacent prefixes that can be combined under a # single, shorter-length prefix. For example, 2001:67c:208c::/48 and # 2001:67c:208d::/48 can be combined into the single prefix # 2001:67c:208c::/47. n_tree = radix.Radix() aggregations = 0 for rnode in tree: p = text(ip_network(text(rnode.prefix)).supernet()) r = tree.search_covered(p) if len(r) == 2 and r[0].prefixlen == r[1].prefixlen == rnode.prefixlen: n_tree.add(p) aggregations += 1 else: n_tree.add(rnode.prefix) return aggregations, n_tree l_tree = _aggregate_phase1(l_tree) potential = len(l_tree.prefixes()) while potential: potential, l_tree = _aggregate_phase2(l_tree) return l_tree def parse_args(args): import argparse p = argparse.ArgumentParser(description="Aggregate lists of IP prefixes", epilog=""" Copyright 2014-2017 Job Snijders <job@instituut.net> Project website: https://github.com/job/aggregate6 """, formatter_class=argparse.RawTextHelpFormatter) p.add_argument('-v', dest='verbose', action='store_true', help="Display verbose information about the optimisations") p.add_argument('-t', dest='truncate', action='store_true', help="truncate IP/mask to network/mask") p.add_argument('-m', dest='max_length', metavar='N', type=int, default=0, help="Sets the maximum prefix length for \ entries read, longer prefixes will be discarded prior to processing") p.add_argument('-V', dest='version', action='store_true', help="Display aggregate6 version") afi_group = p.add_mutually_exclusive_group() afi_group.add_argument('-4', dest='ipv4_only', action='store_true', default=False, help="Only output IPv4 prefixes") afi_group.add_argument('-6', dest='ipv6_only', action='store_true', default=False, help="Only output IPv6 prefixes") p.add_argument('args', nargs=argparse.REMAINDER, help='[file ...] or STDIN') return p.parse_args(args) def main(): import fileinput args = parse_args(sys.argv[1:]) if args.version: # pragma: no cover print("aggregate6 %s" % aggregate6.__version__) sys.exit() p_tree = radix.Radix() for line in fileinput.input(args.args): if not line.strip(): # pragma: no cover continue for elem in line.strip().split(): try: if args.truncate: prefix_obj = ip_interface(text(elem.strip())).network else: prefix_obj = ip_network(text(elem.strip())) prefix = text(prefix_obj) except (ValueError) as err: sys.stderr.write("ERROR: '%s' is not a valid IP network, \ ignoring.\n" % elem.strip()) continue if args.max_length > 0: if prefix_obj.prefixlen > args.max_length: continue if args.ipv4_only and prefix_obj.version == 4: p_tree.add(prefix) elif args.ipv6_only and prefix_obj.version == 6: p_tree.add(prefix) elif not args.ipv4_only and not args.ipv6_only: p_tree.add(prefix) if args.verbose: input_list = p_tree.prefixes() output_list = aggregate_tree(p_tree).prefixes() for p in sorted(set(input_list + output_list)): if p in input_list and p not in output_list: print("- ", end='') elif p in output_list and p not in input_list: print("+ ", end='') else: print(" ", end='') print(p) else: for prefix in aggregate_tree(p_tree).prefixes(): print(prefix) 0707010000000F000081A4000000000000000000000001650CAEE400000011000000000000000000000000000000000000003100000000aggregate6-1.0.12+git37.3ef93ac/requirements.txtpy-radix==0.10.0 07070100000010000081A4000000000000000000000001650CAEE400000DB7000000000000000000000000000000000000002900000000aggregate6-1.0.12+git37.3ef93ac/setup.py#!/usr/bin/env python # Copyright (C) 2014-2017 Job Snijders <job@instituut.net> # # This file is part of aggregate6 # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import codecs import os import re import sys from setuptools import setup, find_packages from os.path import abspath, dirname, join here = abspath(dirname(__file__)) version = re.search(r'^__version__\s*=\s*"(.*)"', open('aggregate6/__init__.py').read(), re.M).group(1) with codecs.open(join(here, 'README.md'), encoding='utf-8') as f: README = f.read() if sys.argv[-1] == 'publish': os.system('python3 setup.py sdist upload') print("You probably want to also tag the version now:") print(" git tag -a %s -m 'version %s'" % (version, version)) print(" git push --tags") print(" git push") sys.exit() setup( name='aggregate6', version=version, maintainer="Job Snijders", maintainer_email='job@instituut.net', url='https://github.com/job/aggregate6', description='IPv4 and IPv6 prefix list compressor', long_description=README, license='BSD 2-Clause', keywords='ipv4 and ipv6 prefix routing networking', classifiers=[ 'Intended Audience :: Developers', 'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: System :: Networking', 'License :: OSI Approved :: BSD License', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12' ], tests_require=["mock;python_version<'3.3'", "coverage"], install_requires=["py-radix==0.10.0"] + ( ["future", "ipaddress"] if sys.version_info.major == 2 else [] ), packages=find_packages(exclude=['tests', 'tests.*']), entry_points={'console_scripts': ['aggregate6 = aggregate6.aggregate6:main']}, data_files=[('man/man7', ['aggregate6.7'])], test_suite='nose.collector' ) 07070100000011000041ED000000000000000000000002650CAEE400000000000000000000000000000000000000000000002600000000aggregate6-1.0.12+git37.3ef93ac/tests07070100000012000081A4000000000000000000000001650CAEE400001392000000000000000000000000000000000000003900000000aggregate6-1.0.12+git37.3ef93ac/tests/test_regression.py#!/usr/bin/env python from aggregate6 import aggregate from aggregate6.aggregate6 import parse_args from aggregate6.aggregate6 import main as agg_main try: from unittest.mock import patch except ImportError: from mock import patch import io import sys import unittest def stub_stdin(testcase_inst, inputs): stdin = sys.stdin def cleanup(): sys.stdin = stdin testcase_inst.addCleanup(cleanup) sys.stdin = StringIO(inputs) def stub_stdouts(testcase_inst): stderr = sys.stderr stdout = sys.stdout def cleanup(): sys.stderr = stderr sys.stdout = stdout testcase_inst.addCleanup(cleanup) sys.stderr = StringIO() sys.stdout = StringIO() class TestAggregate(unittest.TestCase): def test_00__default_wins(self): self.assertEqual(aggregate(["0.0.0.0/0", "10.0.0.0/16"]), ["0.0.0.0/0"]) def test_01__join_two(self): self.assertEqual(aggregate(["10.0.0.0/8", "11.0.0.0/8"]), ["10.0.0.0/7"]) def test_03__mix_v4_v6_default(self): self.assertEqual(aggregate(["0.0.0.0/0", "::/0"]), ["0.0.0.0/0", "::/0"]) def test_04__lot_of_ipv4(self): pfxs = [] for i in range(0, 256): pfxs.append("{}.0.0.0/8".format(i)) self.assertEqual(aggregate(pfxs), ["0.0.0.0/0"]) def test_05__lot_of_ipv4_holes(self): pfxs = [] for i in range(5, 200): pfxs.append("{}.0.0.0/8".format(i)) outcome = ["5.0.0.0/8", "6.0.0.0/7", "8.0.0.0/5", "16.0.0.0/4", "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/2", "192.0.0.0/5"] self.assertEqual(aggregate(pfxs), outcome) def test_06__reduce_dups(self): self.assertEqual(aggregate(["2001:db8::/32", "2001:db8::/32"]), ["2001:db8::/32"]) def test_07__non_ip_input(self): stub_stdouts(self) with self.assertRaises(Exception) as context: aggregate(["this_is_no_prefix", "10.0.0.0/24"]) self.assertTrue('ERROR: invalid IP prefix: this_is_no_prefix' in str(context.exception)) def test_08__test_args_v4(self): self.assertEqual(parse_args(["-4"]).ipv4_only, True) def test_09__main(self): stub_stdin(self, '1.1.1.24/29\n1.1.1.0/24\n1.1.1.1/32\n1.1.0.0/24\n\n') stub_stdouts(self) with patch.object(sys, 'argv', [""]): agg_main() self.assertEqual(sys.stdout.getvalue(), '1.1.0.0/23\n') def test_10__main(self): stub_stdin(self, '2001:db8::/32\n2001:db8::/128\n10.0.0.0/8\n') stub_stdouts(self) with patch.object(sys, 'argv', ["prog.py", "-6"]): agg_main() self.assertEqual(sys.stdout.getvalue(), '2001:db8::/32\n') def test_11_main(self): stub_stdin(self, 'not_a_prefix\n2001:db8::/32\n2001:db8::/128\n' '10.0.0.0/8\n10.1.2.3/32') stub_stdouts(self) with patch.object(sys, 'argv', ["prog.py", "-4"]): agg_main() self.assertEqual(sys.stdout.getvalue(), '10.0.0.0/8\n') self.assertEqual(sys.stderr.getvalue(), "ERROR: 'not_a_prefix' is not a valid IP network, " "ignoring.\n") def test_12__use_space_in_stdin(self): stub_stdin(self, '2001:db8::/32 2001:db8::/128\n10.0.0.0/8\n') stub_stdouts(self) with patch.object(sys, 'argv', ["prog.py", "-6"]): agg_main() self.assertEqual(sys.stdout.getvalue(), '2001:db8::/32\n') def test_13_truncate(self): stub_stdin(self, '2001:db8::1/32 2001:db9::1/32\n10.5.5.5/8\n') stub_stdouts(self) with patch.object(sys, 'argv', ["prog.py", "-t"]): agg_main() self.assertEqual(sys.stdout.getvalue(), '10.0.0.0/8\n2001:db8::/31\n') def test_14_maxlength(self): stub_stdin(self, '10.0.0.0/24 10.0.1.0/25 10.0.1.128/25\n') stub_stdouts(self) with patch.object(sys, 'argv', ["prog.py", "-m", "24"]): agg_main() self.assertEqual(sys.stdout.getvalue(), '10.0.0.0/24\n') def test_15_verbose(self): stub_stdin(self, '10.0.0.0/24 10.0.1.0/24 172.16.0.0/24 10.0.0.0/32\n') stub_stdouts(self) with patch.object(sys, 'argv', ["prog.py", "-v"]): agg_main() self.assertEqual(sys.stdout.getvalue(), "+ 10.0.0.0/23\n- " "10.0.0.0/24\n- 10.0.0.0/32\n- 10.0.1.0/24\n " "172.16.0.0/24\n") class StringIO(io.StringIO): """ A "safely" wrapped version """ def __init__(self, value=''): value = value.encode('utf8', 'backslashreplace').decode('utf8') io.StringIO.__init__(self, value) def write(self, msg): io.StringIO.write(self, msg.encode( 'utf8', 'backslashreplace').decode('utf8')) def main(): unittest.main() if __name__ == '__main__': main() 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!58 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor