├── tests
├── __init__.py
└── test_braveblock.py
├── images
└── logo.png
├── braveblock
├── easylist.txt.gz
├── easyprivacy.txt.gz
├── braveblock.pyi
└── __init__.py
├── cortex.yaml
├── scripts
└── update_lists.py
├── Cargo.toml
├── LICENSE
├── pyproject.toml
├── .github
└── workflows
│ ├── build.yml
│ └── deploy.yml
├── README.md
├── .gitignore
├── src
└── lib.rs
└── poetry.lock
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Intsights/braveblock/HEAD/images/logo.png
--------------------------------------------------------------------------------
/braveblock/easylist.txt.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Intsights/braveblock/HEAD/braveblock/easylist.txt.gz
--------------------------------------------------------------------------------
/braveblock/easyprivacy.txt.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Intsights/braveblock/HEAD/braveblock/easyprivacy.txt.gz
--------------------------------------------------------------------------------
/braveblock/braveblock.pyi:
--------------------------------------------------------------------------------
1 | import typing
2 |
3 |
4 | class Adblocker:
5 | def __init__(
6 | self,
7 | rules: typing.Optional[typing.List[str]] = None,
8 | include_easylist: bool = True,
9 | include_easyprivacy: bool = True,
10 | ) -> None: ...
11 |
12 | def check_network_urls(
13 | self,
14 | url: str,
15 | source_url: str,
16 | request_type: str,
17 | ) -> bool: ...
18 |
--------------------------------------------------------------------------------
/cortex.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | info:
3 | title: Braveblock
4 | description: A fast and easy adblockplus parser and matcher based on adblock-rust
5 | package
6 | x-cortex-git:
7 | github:
8 | alias: intsightsorg
9 | repository: Intsights/braveblock
10 | x-cortex-tag: braveblock
11 | x-cortex-type: service
12 | x-cortex-domain-parents:
13 | - tag: threatintel-brand-security
14 | x-cortex-groups:
15 | - exposure:internal-ship
16 | - target:library
17 | openapi: 3.0.1
18 | servers:
19 | - url: "/"
20 |
--------------------------------------------------------------------------------
/scripts/update_lists.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import gzip
3 | import pathlib
4 |
5 |
6 | braveblock_dir = pathlib.Path(__file__).parent.parent.joinpath('braveblock')
7 |
8 | easylist_response = requests.get(
9 | url='https://easylist.to/easylist/easylist.txt',
10 | )
11 | with gzip.GzipFile(
12 | filename=braveblock_dir.joinpath('easylist.txt.gz'),
13 | mode='wb',
14 | ) as easylist_file:
15 | easylist_file.write(easylist_response.content)
16 |
17 | easyprivacy_response = requests.get(
18 | url='https://easylist.to/easylist/easyprivacy.txt',
19 | )
20 | with gzip.GzipFile(
21 | filename=braveblock_dir.joinpath('easyprivacy.txt.gz'),
22 | mode='wb',
23 | ) as easyprivacy_file:
24 | easyprivacy_file.write(easyprivacy_response.content)
25 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "braveblock"
3 | version = "0.5.1"
4 | authors = ["Gal Ben David "]
5 | edition = "2021"
6 | description = "A fast and easy adblockplus parser and matcher based on adblock-rust package"
7 | readme = "README.md"
8 | repository = "https://github.com/intsights/braveblock"
9 | homepage = "https://github.com/intsights/braveblock"
10 | license = "MIT"
11 | keywords = [
12 | "adblock",
13 | "ads",
14 | "adblocker",
15 | "rust",
16 | "brave",
17 | "abp",
18 | "pyo3",
19 | ]
20 |
21 | [package.metadata.maturin]
22 |
23 | [lib]
24 | name = "braveblock"
25 | crate-type = ["cdylib"]
26 |
27 | [dependencies.adblock]
28 | version = "0.5"
29 | default-features = false
30 | features = ["full-regex-handling", "embedded-domain-resolver"]
31 |
32 | [dependencies.pyo3]
33 | version = "0.16.5"
34 | features = ["extension-module"]
35 |
36 | [profile.release]
37 | lto = true
38 | panic = "abort"
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Gal Ben David
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["maturin>=0.12,<0.13"]
3 | build-backend = "maturin"
4 |
5 | [tool.maturin]
6 | sdist-include = [
7 | "braveblock/*.py",
8 | "braveblock/*.pyi",
9 | "Cargo.toml",
10 | "pyproject.toml",
11 | "src/*",
12 | ]
13 |
14 | [tool.poetry]
15 | name = "braveblock"
16 | version = "0.5.1"
17 | authors = ["Gal Ben David "]
18 | description = "A fast and easy adblockplus parser and matcher based on adblock-rust package"
19 | readme = "README.md"
20 | repository = "https://github.com/intsights/braveblock"
21 | homepage = "https://github.com/intsights/braveblock"
22 | license = "MIT"
23 | keywords = [
24 | "adblock",
25 | "ads",
26 | "adblocker",
27 | "rust",
28 | "brave",
29 | "abp",
30 | "pyo3"
31 | ]
32 | classifiers = [
33 | "License :: OSI Approved :: MIT License",
34 | "Operating System :: MacOS",
35 | "Operating System :: Microsoft",
36 | "Operating System :: POSIX :: Linux",
37 | "Programming Language :: Python :: 3.7",
38 | "Programming Language :: Python :: 3.8",
39 | "Programming Language :: Python :: 3.9",
40 | "Programming Language :: Python :: 3.10",
41 | "Programming Language :: Python :: 3.11",
42 | "Programming Language :: Rust",
43 | ]
44 |
45 | [tool.poetry.dependencies]
46 | python = "^3.7"
47 |
48 | [tool.poetry.dev-dependencies]
49 | pytest = "*"
50 | wheel = "*"
51 | pytest-runner = "*"
52 | maturin = "*"
53 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 | on:
3 | - push
4 | - pull_request
5 | jobs:
6 | lint:
7 | if: github.event_name == 'push' && !startsWith(github.event.ref, 'refs/tags')
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: Checkout
11 | uses: actions/checkout@v3
12 | - name: Install latest rust
13 | uses: actions-rs/toolchain@v1
14 | with:
15 | toolchain: stable
16 | profile: minimal
17 | override: true
18 | components: clippy
19 | - name: Lint with clippy
20 | uses: actions-rs/cargo@v1
21 | with:
22 | command: clippy
23 | args: --all-targets --all-features
24 | test:
25 | runs-on: ${{ matrix.os }}
26 | needs: lint
27 | strategy:
28 | fail-fast: false
29 | matrix:
30 | python-version:
31 | - '3.7'
32 | - '3.8'
33 | - '3.9'
34 | - '3.10'
35 | - '3.11'
36 | os:
37 | - ubuntu-latest
38 | - macos-latest
39 | - windows-latest
40 | steps:
41 | - name: Checkout
42 | uses: actions/checkout@v3
43 | - name: Set up Python ${{ matrix.python-version }}
44 | uses: actions/setup-python@v3
45 | with:
46 | python-version: ${{ matrix.python-version }}
47 | - name: Install Poetry
48 | uses: abatilo/actions-poetry@v2.1.3
49 | - name: Install Rust
50 | uses: actions-rs/toolchain@v1
51 | with:
52 | profile: minimal
53 | toolchain: stable
54 | override: true
55 | - name: Install dependencies
56 | run: poetry install
57 | - name: Build Python package
58 | run: poetry run maturin develop
59 | - name: Test
60 | run: poetry run pytest -Werror tests
61 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy
2 | on:
3 | release:
4 | types:
5 | - released
6 | jobs:
7 | deploy:
8 | runs-on: ${{ matrix.os }}
9 | strategy:
10 | fail-fast: false
11 | matrix:
12 | python-version:
13 | - '3.7'
14 | - '3.8'
15 | - '3.9'
16 | - '3.10'
17 | - '3.11'
18 | os:
19 | - ubuntu-latest
20 | - macos-latest
21 | - windows-latest
22 | steps:
23 | - name: Checkout
24 | uses: actions/checkout@v3
25 | - name: Set up Python ${{ matrix.python-version }}
26 | uses: actions/setup-python@v4
27 | with:
28 | python-version: ${{ matrix.python-version }}
29 | - name: Install Rust
30 | uses: actions-rs/toolchain@v1
31 | with:
32 | profile: minimal
33 | toolchain: stable
34 | override: true
35 | - name: Install Cross-compilers (macOS)
36 | if: matrix.os == 'macos-latest'
37 | run: |
38 | rustup target add x86_64-apple-darwin
39 | rustup target add aarch64-apple-darwin
40 | - name: Publish Package
41 | uses: PyO3/maturin-action@v1
42 | with:
43 | command: publish
44 | args: --username=__token__ ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.7' && '' || '--no-sdist' }} --interpreter=python${{ !startsWith(matrix.os, 'windows') && matrix.python-version || '' }}
45 | env:
46 | MATURIN_PASSWORD: ${{ secrets.pypi_password }}
47 | if: matrix.os != 'macos-latest'
48 | - name: Publish macOS (x86_64) Package
49 | if: matrix.os == 'macos-latest'
50 | uses: PyO3/maturin-action@v1
51 | with:
52 | command: publish
53 | args: --username=__token__ --interpreter=python${{ matrix.python-version }} --target=x86_64-apple-darwin --no-sdist
54 | env:
55 | MATURIN_PASSWORD: ${{ secrets.pypi_password }}
56 | - name: Publish macOS (arm64) Package
57 | if: matrix.os == 'macos-latest'
58 | uses: PyO3/maturin-action@v1
59 | with:
60 | command: publish
61 | args: --username=__token__ --interpreter=python${{ matrix.python-version }} --target=aarch64-apple-darwin --no-sdist
62 | env:
63 | MATURIN_PASSWORD: ${{ secrets.pypi_password }}
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | A fast and easy adblockplus parser and matcher based on adblock-rust package
7 |
8 |
9 |
10 |
11 | 
12 | 
13 | 
14 | 
15 | [](https://pypi.org/project/Braveblock/)
16 |
17 | ## Table of Contents
18 |
19 | - [Table of Contents](#table-of-contents)
20 | - [About The Project](#about-the-project)
21 | - [Built With](#built-with)
22 | - [Installation](#installation)
23 | - [Usage](#usage)
24 | - [License](#license)
25 | - [Contact](#contact)
26 |
27 |
28 | ## About The Project
29 |
30 | This library is a Python binding to the [adblock-rust](https://github.com/brave/adblock-rust) library that was written by Brave's browser team. The binding uses [pyo3](https://github.com/PyO3/pyo3) to interact with the rust package.
31 |
32 |
33 | ### Built With
34 |
35 | * [pyo3](https://github.com/PyO3/pyo3)
36 | * [adblock-rust](https://github.com/brave/adblock-rust)
37 |
38 |
39 | ### Installation
40 |
41 | ```sh
42 | pip3 install braveblock
43 | ```
44 |
45 |
46 | ## Usage
47 |
48 | ```python
49 | import braveblock
50 |
51 |
52 | # Initialize the engine loaded with a rules list
53 | # One can download easylist and load its lines into the engine
54 | braveblock.Adblocker(
55 | rules=[
56 | "-advertisement-icon.",
57 | "-advertisement/script.",
58 | ]
59 | )
60 |
61 | # This function checks whether the specified url should be blocked
62 | adblocker.check_network_urls(
63 | url="http://example.com/-advertisement-icon.",
64 | source_url="http://example.com/helloworld",
65 | request_type="image",
66 | )
67 | ```
68 |
69 |
70 | ## License
71 |
72 | Distributed under the MIT License. See `LICENSE` for more information.
73 |
74 |
75 | ## Contact
76 |
77 | Gal Ben David - gal@intsights.com
78 |
79 | Project Link: [https://github.com/intsights/Braveblock](https://github.com/intsights/Braveblock)
80 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 |
5 | # C extensions
6 | *.so
7 | # Distribution / packaging
8 | .Python
9 | env/
10 | build/
11 | develop-eggs/
12 | dist/
13 | downloads/
14 | eggs/
15 | .eggs/
16 | lib/
17 | lib64/
18 | parts/
19 | sdist/
20 | var/
21 | *.egg-info/
22 | .installed.cfg
23 | *.egg
24 |
25 | # PyInstaller
26 | # Usually these files are written by a python script from a template
27 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
28 | *.manifest
29 | *.spec
30 |
31 | # conflict temp files
32 | *.py.orig
33 | *.mock
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | coverage_html_report/
42 | .tox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *,cover
49 | .pytest_cache/
50 |
51 | # Translations
52 | *.mo
53 | *.pot
54 |
55 | # Django stuff:
56 | *.log
57 |
58 | # Sphinx documentation
59 | docs/_build/
60 |
61 | # PyBuilder
62 | target/
63 |
64 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
65 |
66 | *.iml
67 |
68 | ## Directory-based project format:
69 | .idea/
70 |
71 | # Tests
72 | generic_tests.py
73 | cloudflare_test.py
74 |
75 | ############################
76 | #Eclipse Specific GitIgnore#
77 | ############################
78 | *.pydevproject
79 | .project
80 | .metadata
81 | bin/**
82 | tmp/**
83 | tmp/**/*
84 | *.tmp
85 | *.bak
86 | *.swp
87 | *~.nib
88 | local.properties
89 | .classpath
90 | .settings/
91 | .loadpath
92 |
93 |
94 | # Git mergetool traces
95 | *.orig
96 |
97 | # VS Code internal directory
98 | .vscode/
99 |
100 | *.dat
101 | *.code-workspace
102 | .history
103 |
104 | # Intsights development playground
105 | playground/
106 |
107 | pytest-report\.csv
108 | *.cppimporthash
109 | .rendered.*
110 | Databases.db
111 |
112 | # Node.js
113 | dist/
114 | node_modules/
115 | coverage/
116 |
117 | # Generated by Cargo
118 | # will have compiled files and executables
119 | /target/
120 |
121 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
122 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
123 | Cargo.lock
124 |
125 | # These are backup files generated by rustfmt
126 | **/*.rs.bk
127 |
--------------------------------------------------------------------------------
/braveblock/__init__.py:
--------------------------------------------------------------------------------
1 | import gzip
2 | import sys
3 | import importlib.resources
4 | import typing
5 |
6 | from . import braveblock
7 |
8 | PY_VERSION_MAJOR = sys.version_info.major
9 | PY_VERSION_MINOR = sys.version_info.minor
10 |
11 |
12 | class Adblocker:
13 |
14 | @staticmethod
15 | def read_gz_binary(
16 | file_name: str
17 | ) -> bytes:
18 | if PY_VERSION_MAJOR < 3 or PY_VERSION_MINOR < 11:
19 | return importlib.resources.read_binary(
20 | package=__package__,
21 | resource=file_name,
22 | )
23 | with importlib.resources.files(
24 | __package__,
25 | ).joinpath(
26 | file_name,
27 | ).open(
28 | 'rb',
29 | ) as _word_frequencies_binary:
30 | return _word_frequencies_binary.read()
31 |
32 | def __init__(
33 | self,
34 | rules: typing.Optional[typing.List[str]] = None,
35 | include_easylist: bool = True,
36 | include_easyprivacy: bool = True,
37 | ) -> None:
38 | combined_rules = []
39 |
40 | if rules is not None:
41 | combined_rules.extend(
42 | rules
43 | )
44 |
45 | if include_easylist:
46 | easylist_compressed_data = self.read_gz_binary(
47 | file_name='easylist.txt.gz',
48 | )
49 | easylist_data = gzip.decompress(
50 | easylist_compressed_data
51 | ).decode()
52 | easylist_rules = easylist_data.splitlines()
53 | combined_rules.extend(
54 | easylist_rules
55 | )
56 |
57 | if include_easyprivacy:
58 | easyprivacy_compressed_data = self.read_gz_binary(
59 | file_name='easyprivacy.txt.gz',
60 | )
61 |
62 | easyprivacy_data = gzip.decompress(
63 | easyprivacy_compressed_data
64 | ).decode()
65 | easyprivacy_rules = easyprivacy_data.splitlines()
66 | combined_rules.extend(
67 | easyprivacy_rules
68 | )
69 |
70 | self.engine = braveblock.Adblocker(
71 | rules=combined_rules,
72 | )
73 |
74 | def check_network_urls(
75 | self,
76 | url: str,
77 | source_url: str,
78 | request_type: str,
79 | ) -> bool:
80 | return self.engine.check_network_urls(
81 | url=url,
82 | source_url=source_url,
83 | request_type=request_type,
84 | )
85 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | use adblock::engine::Engine;
2 | use adblock::lists::ParseOptions;
3 | use pyo3::prelude::*;
4 |
5 | /// Adblocker class
6 | /// Hold the adblocker engine loaded with the rules
7 | ///
8 | /// input:
9 | /// rules: List[str] -> list of strings that represent the rules to be applied
10 | ///
11 | /// example:
12 | /// braveblock.Adblocker(
13 | /// rules=[
14 | /// "-advertisement-icon.",
15 | /// "-advertisement/script.",
16 | /// ]
17 | /// )
18 | #[pyclass]
19 | struct Adblocker {
20 | engine: Engine,
21 | }
22 |
23 | #[pymethods]
24 | impl Adblocker {
25 | #[new]
26 | fn new(rules: Vec) -> Self {
27 | Adblocker { engine: Engine::from_rules(&rules, ParseOptions::default()) }
28 | }
29 |
30 | /// The function that should tell whether a specific request should be blocked according to the loaded rules
31 | ///
32 | /// input:
33 | /// url: str -> The inspected url that should be tested
34 | /// source_url: str -> The source url that made the request to the inspected url
35 | /// request_type: str -> The type of the resource that is being requested. Can be one of the following:
36 | /// "beacon", "csp_report", "document", "font", "image", "imageset", "main_frame",
37 | /// "media", "object_subrequest", "object", "other", "ping", "script", "speculative",
38 | /// "stylesheet", "sub_frame", "subdocument", "web_manifest", "websocket", "xbl",
39 | /// "xhr", "xml_dtd", "xmlhttprequest", "xslt"
40 | ///
41 | /// returns:
42 | /// bool -> Whether the request should be blocked or not
43 | ///
44 | /// example:
45 | /// adblocker.check_network_urls(
46 | /// url="http://example.com/-advertisement-icon.",
47 | /// source_url="http://example.com/",
48 | /// request_type="image",
49 | /// )
50 | fn check_network_urls(
51 | &mut self,
52 | url: &str,
53 | source_url: &str,
54 | request_type: &str,
55 | ) -> PyResult {
56 | let blocker_result = self.engine.check_network_urls(
57 | url,
58 | source_url,
59 | request_type
60 | );
61 |
62 | Ok(blocker_result.matched)
63 | }
64 | }
65 |
66 | /// Braveblock is a python library that implemented an adblocker based on Brave's browser adblocker written in Rust
67 | /// This library is a bindings for the original adblocker written by Brave's team
68 | /// Original code can be found here https://github.com/brave/adblock-rust
69 | #[pymodule]
70 | fn braveblock(_py: Python, m: &PyModule) -> PyResult<()> {
71 | m.add_class::()?;
72 |
73 | Ok(())
74 | }
75 |
--------------------------------------------------------------------------------
/tests/test_braveblock.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | import braveblock
4 |
5 |
6 | class BraveblockTestCase(
7 | unittest.TestCase,
8 | ):
9 | def test_adblocker_default_rules(
10 | self,
11 | ):
12 | adblocker = braveblock.Adblocker()
13 |
14 | self.assertFalse(
15 | expr=adblocker.check_network_urls(
16 | url='http://some-website.com/image.jpg',
17 | source_url='http://some-website.com/',
18 | request_type='image',
19 | ),
20 | )
21 | self.assertTrue(
22 | expr=adblocker.check_network_urls(
23 | url='http://some-google-ads.com/image.jpg',
24 | source_url='http://some-google-ads.com/',
25 | request_type='image',
26 | ),
27 | )
28 | self.assertTrue(
29 | expr=adblocker.check_network_urls(
30 | url='http://some-google-analytics.com/image.jpg',
31 | source_url='http://some-google-analytics.com/',
32 | request_type='image',
33 | ),
34 | )
35 |
36 | def test_adblocker_custom_rules(
37 | self,
38 | ):
39 | adblocker = braveblock.Adblocker(
40 | rules=[
41 | '-advertisement-icon.',
42 | ],
43 | include_easylist=False,
44 | include_easyprivacy=False,
45 | )
46 |
47 | self.assertTrue(
48 | expr=adblocker.check_network_urls(
49 | url='http://domain.com/some-advertisement-icon.',
50 | source_url='http://domain.com/',
51 | request_type='image',
52 | ),
53 | )
54 | self.assertFalse(
55 | expr=adblocker.check_network_urls(
56 | url='http://domain.com/other-icon.ico',
57 | source_url='http://domain.com/',
58 | request_type='image',
59 | ),
60 | )
61 |
62 | self.assertFalse(
63 | expr=adblocker.check_network_urls(
64 | url='http://some-website.com/image.jpg',
65 | source_url='http://some-website.com/',
66 | request_type='image',
67 | ),
68 | )
69 |
70 | self.assertFalse(
71 | expr=adblocker.check_network_urls(
72 | url='http://google-ads.com/image.jpg',
73 | source_url='http://google-ads.com/',
74 | request_type='image',
75 | ),
76 | )
77 | self.assertFalse(
78 | expr=adblocker.check_network_urls(
79 | url='http://some-google-analytics.com/image.jpg',
80 | source_url='http://some-google-analytics.com/',
81 | request_type='image',
82 | ),
83 | )
84 |
85 | def test_adblocker_custom_rules_plus_default(
86 | self,
87 | ):
88 | adblocker = braveblock.Adblocker(
89 | rules=[
90 | '-advertisement-icon.',
91 | ],
92 | )
93 |
94 | self.assertTrue(
95 | expr=adblocker.check_network_urls(
96 | url='http://legitimate.com/some-advertisement-icon.',
97 | source_url='http://legitimate.com/',
98 | request_type='image',
99 | ),
100 | )
101 | self.assertFalse(
102 | expr=adblocker.check_network_urls(
103 | url='http://legitimate.com/other-icon.ico',
104 | source_url='http://legitimate.com/',
105 | request_type='image',
106 | ),
107 | )
108 |
109 | self.assertFalse(
110 | expr=adblocker.check_network_urls(
111 | url='http://legitimate.com/image.jpg',
112 | source_url='http://legitimate.com/',
113 | request_type='image',
114 | ),
115 | )
116 |
117 | self.assertTrue(
118 | expr=adblocker.check_network_urls(
119 | url='http://google-ads.com/image.jpg',
120 | source_url='http://google-ads.com/',
121 | request_type='image',
122 | ),
123 | )
124 | self.assertTrue(
125 | expr=adblocker.check_network_urls(
126 | url='http://some-google-analytics.com/image.jpg',
127 | source_url='http://some-google-analytics.com/',
128 | request_type='image',
129 | ),
130 | )
131 |
--------------------------------------------------------------------------------
/poetry.lock:
--------------------------------------------------------------------------------
1 | [[package]]
2 | name = "colorama"
3 | version = "0.4.6"
4 | description = "Cross-platform colored terminal text."
5 | category = "dev"
6 | optional = false
7 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
8 |
9 | [[package]]
10 | name = "exceptiongroup"
11 | version = "1.2.0"
12 | description = "Backport of PEP 654 (exception groups)"
13 | category = "dev"
14 | optional = false
15 | python-versions = ">=3.7"
16 |
17 | [package.extras]
18 | test = ["pytest (>=6)"]
19 |
20 | [[package]]
21 | name = "importlib-metadata"
22 | version = "6.7.0"
23 | description = "Read metadata from Python packages"
24 | category = "dev"
25 | optional = false
26 | python-versions = ">=3.7"
27 |
28 | [package.dependencies]
29 | typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
30 | zipp = ">=0.5"
31 |
32 | [package.extras]
33 | docs = ["sphinx (>=3.5)", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "furo", "sphinx-lint", "jaraco.tidelift (>=1.4)"]
34 | perf = ["ipython"]
35 | testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-ruff", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"]
36 |
37 | [[package]]
38 | name = "iniconfig"
39 | version = "2.0.0"
40 | description = "brain-dead simple config-ini parsing"
41 | category = "dev"
42 | optional = false
43 | python-versions = ">=3.7"
44 |
45 | [[package]]
46 | name = "maturin"
47 | version = "1.4.0"
48 | description = "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages"
49 | category = "dev"
50 | optional = false
51 | python-versions = ">=3.7"
52 |
53 | [package.dependencies]
54 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
55 |
56 | [package.extras]
57 | zig = ["ziglang (>=0.10.0,<0.11.0)"]
58 | patchelf = ["patchelf"]
59 |
60 | [[package]]
61 | name = "packaging"
62 | version = "23.2"
63 | description = "Core utilities for Python packages"
64 | category = "dev"
65 | optional = false
66 | python-versions = ">=3.7"
67 |
68 | [[package]]
69 | name = "pluggy"
70 | version = "1.2.0"
71 | description = "plugin and hook calling mechanisms for python"
72 | category = "dev"
73 | optional = false
74 | python-versions = ">=3.7"
75 |
76 | [package.dependencies]
77 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
78 |
79 | [package.extras]
80 | dev = ["pre-commit", "tox"]
81 | testing = ["pytest", "pytest-benchmark"]
82 |
83 | [[package]]
84 | name = "pytest"
85 | version = "7.4.4"
86 | description = "pytest: simple powerful testing with Python"
87 | category = "dev"
88 | optional = false
89 | python-versions = ">=3.7"
90 |
91 | [package.dependencies]
92 | colorama = {version = "*", markers = "sys_platform == \"win32\""}
93 | exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
94 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
95 | iniconfig = "*"
96 | packaging = "*"
97 | pluggy = ">=0.12,<2.0"
98 | tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
99 |
100 | [package.extras]
101 | testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
102 |
103 | [[package]]
104 | name = "pytest-runner"
105 | version = "6.0.1"
106 | description = "Invoke py.test as distutils command with dependency resolution"
107 | category = "dev"
108 | optional = false
109 | python-versions = ">=3.7"
110 |
111 | [package.extras]
112 | docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"]
113 | testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-virtualenv", "types-setuptools", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"]
114 |
115 | [[package]]
116 | name = "tomli"
117 | version = "2.0.1"
118 | description = "A lil' TOML parser"
119 | category = "dev"
120 | optional = false
121 | python-versions = ">=3.7"
122 |
123 | [[package]]
124 | name = "typing-extensions"
125 | version = "4.7.1"
126 | description = "Backported and Experimental Type Hints for Python 3.7+"
127 | category = "dev"
128 | optional = false
129 | python-versions = ">=3.7"
130 |
131 | [[package]]
132 | name = "zipp"
133 | version = "3.15.0"
134 | description = "Backport of pathlib-compatible object wrapper for zip files"
135 | category = "dev"
136 | optional = false
137 | python-versions = ">=3.7"
138 |
139 | [package.extras]
140 | docs = ["sphinx (>=3.5)", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "furo", "sphinx-lint", "jaraco.tidelift (>=1.4)"]
141 | testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "flake8 (<5)", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "jaraco.functools", "more-itertools", "big-o", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "pytest-flake8"]
142 |
143 | [metadata]
144 | lock-version = "1.1"
145 | python-versions = "^3.7"
146 | content-hash = "d3751775f5a48f55874329689185792d15525d44f15678cc3bfeb66b5dea0d3d"
147 |
148 | [metadata.files]
149 | colorama = []
150 | exceptiongroup = []
151 | importlib-metadata = []
152 | iniconfig = []
153 | maturin = []
154 | packaging = []
155 | pluggy = []
156 | pytest = []
157 | pytest-runner = []
158 | tomli = []
159 | typing-extensions = []
160 | zipp = []
161 |
--------------------------------------------------------------------------------