diff --git a/README.md b/README.md index 259437d..ebdfaeb 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ subtleties. If you have unusual requirements, it is better to write the proxy sc ## I would still like to implement this - [x] ~~automatic sorting with overlapping hostnames~~ +- [x] ~~implement include and exclude filter at output~~ - [ ] automatic sorting with overlapping network masks - [ ] publish on pypi -- [ ] implement filter at output - [ ] add tag to automatically add local networks to the proxy diff --git a/pyproject.toml b/pyproject.toml index fa1bc73..ef17d01 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "pypacer" -version = "0.1.3" +version = "0.1.4" dynamic = ["dependencies"] authors = [ { name = "Heiko Schmidt", email = "73h@gmx.net" }, diff --git a/src/examples/unittests.yaml b/src/examples/unittests.yaml index 7a150db..611f324 100644 --- a/src/examples/unittests.yaml +++ b/src/examples/unittests.yaml @@ -17,6 +17,8 @@ proxies: - "foo.example.net" - route: "PROXY netmask.example.com" description: a proxy for netmask + tags: + - foo targets: - "93.184.0.0/16" - route: "PROXY ip.example.com" diff --git a/src/pypacer/pypacer.py b/src/pypacer/pypacer.py index efcfea1..80f1a43 100644 --- a/src/pypacer/pypacer.py +++ b/src/pypacer/pypacer.py @@ -21,10 +21,46 @@ def load_from_yaml(self, stream: str): y = yaml.safe_load(stream) self.load_from_dict(y) - def output(self) -> str: + def output(self, excludes: list[str] = None, includes: list[str] = None) -> str: + """Returns the finished ProxyScript as a string + + Parameters + ---------- + excludes : list[str], optional + A list of tags. Proxies that have this tag are excluded. + + includes : list[str], optional + A list of tags. Proxies that have this tag are included. Other proxies are not included. + + """ if self.config is None: raise Exception("No config loaded, use load_from_yaml or load_from_dict first.") config = copy.deepcopy(self.config) + + # handle includes + if includes: + proxies = [] + for proxy in config.proxies: + include = False + for tag in proxy.tags: + if tag in includes: + include = True + if include: + proxies.append(proxy) + config.proxies = proxies + + # handle excludes + if excludes: + proxies = [] + for proxy in config.proxies: + exclude = False + for tag in proxy.tags: + if tag in excludes: + exclude = True + if not exclude: + proxies.append(proxy) + config.proxies = proxies + default = config.get_default_proxy() config.reorganize_proxies() config.recognize_overlaps() diff --git a/src/pypacer/pypacerconfig.py b/src/pypacer/pypacerconfig.py index babe91f..4177e06 100644 --- a/src/pypacer/pypacerconfig.py +++ b/src/pypacer/pypacerconfig.py @@ -75,4 +75,8 @@ def recognize_overlaps(self): def get_default_proxy(self) -> Proxy: defaults = [p for p in self.proxies if "default" in p.tags] - return defaults[0] if len(defaults) > 0 else [p for p in self.proxies][0] + if len(defaults) == 0: + if len(self.proxies) == 0: + return Proxy(route="DIRECT") + return self.proxies[0] + return defaults[0] diff --git a/src/tests/pypacer_test.py b/src/tests/pypacer_test.py index 6145059..dcc526d 100644 --- a/src/tests/pypacer_test.py +++ b/src/tests/pypacer_test.py @@ -23,6 +23,32 @@ def test_load_config_from_yaml(self): output = p.output() open(os.path.join(location, "..", "examples", "unittests.pac"), "w").write(output) + def test_exclude_by_tag(self): + p = PyPacer() + p.load_from_yaml(self.pac_file) + output = p.output(excludes=["foo"]) + self.assertTrue("PROXY netmask.example.com" not in output) + + def test_exclude_by_tags(self): + p = PyPacer() + p.load_from_yaml(self.pac_file) + output = p.output(excludes=["foo", "default"]) + self.assertTrue("PROXY netmask.example.com" not in output) + self.assertTrue("PROXY default.example.com" not in output) + + def test_include_by_tag(self): + p = PyPacer() + p.load_from_yaml(self.pac_file) + output = p.output(includes=["foo"]) + self.assertTrue("PROXY netmask.example.com" in output) + + def test_include_by_tags(self): + p = PyPacer() + p.load_from_yaml(self.pac_file) + output = p.output(includes=["foo", "default"]) + self.assertTrue("PROXY netmask.example.com" in output) + self.assertTrue("PROXY default.example.com" in output) + def test_output(self): p = PyPacer() p.load_from_yaml(self.pac_file)