pax_global_header00006660000000000000000000000064146746215210014522gustar00rootroot0000000000000052 comment=e8a597629050d199d21c7d5b3b94c2e35c72cd20 PyFunceble-4.2.29.dev/000077500000000000000000000000001467462152100144315ustar00rootroot00000000000000PyFunceble-4.2.29.dev/.all-contributorsrc000066400000000000000000000227601467462152100202710ustar00rootroot00000000000000{ "projectName": "PyFunceble", "projectOwner": "funilrys", "repoType": "github", "repoHost": "https://github.com", "files": [ "README.md", "CONTRIBUTORS.md", "docs/about/contributors.md" ], "imageSize": 100, "commit": false, "commitConvention": "gitmoji", "contributors": [ { "login": "avatartw", "name": "avatartw", "avatar_url": "https://avatars.githubusercontent.com/u/69660730?v=4", "profile": "https://github.com/avatartw", "contributions": [ "bug" ] }, { "login": "AvinashReddy3108", "name": "Avinash Reddy", "avatar_url": "https://avatars.githubusercontent.com/u/27774996?v=4", "profile": "https://github.com/AvinashReddy3108", "contributions": [ "bug" ] }, { "login": "bigdargon", "name": "BigDargon", "avatar_url": "https://avatars.githubusercontent.com/u/10969626?v=4", "profile": "https://github.com/bigdargon", "contributions": [ "bug", "ideas", "question", "review", "data", "test" ] }, { "login": "gwarser", "name": "gwarser", "avatar_url": "https://avatars.githubusercontent.com/u/886325?v=4", "profile": "https://github.com/gwarser", "contributions": [ "bug", "data", "test" ] }, { "login": "hawkeye116477", "name": "hawkeye116477", "avatar_url": "https://avatars.githubusercontent.com/u/19818572?v=4", "profile": "https://github.com/hawkeye116477", "contributions": [ "bug" ] }, { "login": "T145", "name": "T145", "avatar_url": "https://avatars.githubusercontent.com/u/1214129?v=4", "profile": "https://github.com/T145", "contributions": [ "bug", "ideas" ] }, { "login": "DandelionSprout", "name": "Imre Eilertsen", "avatar_url": "https://avatars.githubusercontent.com/u/22780683?v=4", "profile": "https://github.com/DandelionSprout", "contributions": [ "a11y", "bug", "data", "example", "financial", "ideas", "promotion", "question", "review", "tool", "test", "userTesting" ] }, { "login": "dnmTX", "name": "dnmTX", "avatar_url": "https://avatars.githubusercontent.com/u/34774426?v=4", "profile": "https://github.com/dnmTX", "contributions": [ "bug", "ideas", "question", "review", "data", "test" ] }, { "login": "veracioux", "name": "Haris Guลกiฤ‡", "avatar_url": "https://avatars.githubusercontent.com/u/29044423?v=4", "profile": "https://github.com/veracioux", "contributions": [ "doc", "a11y", "tool", "test", "video", "tutorial", "code" ] }, { "login": "jawz101", "name": "jawz101", "avatar_url": "https://avatars.githubusercontent.com/u/14151703?v=4", "profile": "https://github.com/jawz101", "contributions": [ "bug", "ideas", "question", "data" ] }, { "login": "keczuppp", "name": "keczuppp", "avatar_url": "https://avatars.githubusercontent.com/u/74409207?v=4", "profile": "https://github.com/keczuppp", "contributions": [ "bug", "ideas", "question", "test", "data" ] }, { "login": "kowith337", "name": "Kowith Singkornkeeree", "avatar_url": "https://avatars.githubusercontent.com/u/16535467?v=4", "profile": "https://github.com/kowith337", "contributions": [ "bug" ] }, { "login": "mitchellkrogza", "name": "Mitchell Krog", "avatar_url": "https://avatars.githubusercontent.com/u/9961541?v=4", "profile": "https://ubuntu101.co.za/", "contributions": [ "a11y", "bug", "blog", "code", "content", "data", "doc", "design", "example", "fundingFinding", "ideas", "infra", "mentoring", "platform", "plugin", "promotion", "question", "review", "tool", "test", "tutorial", "talk", "userTesting" ] }, { "login": "NeolithEra", "name": "watchman-pypi", "avatar_url": "https://avatars.githubusercontent.com/u/52778917?v=4", "profile": "https://github.com/NeolithEra", "contributions": [ "bug" ] }, { "login": "Nilsonfsilva", "name": "Nilsonfsilva", "avatar_url": "https://avatars.githubusercontent.com/u/91392383?v=4", "profile": "https://github.com/Nilsonfsilva", "contributions": [ "bug", "infra", "platform", "tool", "test" ] }, { "login": "Odyseus", "name": "Odyseus", "avatar_url": "https://avatars.githubusercontent.com/u/3822556?v=4", "profile": "https://github.com/Odyseus", "contributions": [ "bug", "test" ] }, { "login": "opav", "name": "opav", "avatar_url": "https://avatars.githubusercontent.com/u/6770347?v=4", "profile": "https://github.com/opav", "contributions": [ "bug", "test" ] }, { "login": "rusty-snake", "name": "rusty-snake", "avatar_url": "https://avatars.githubusercontent.com/u/41237666?v=4", "profile": "https://github.com/rusty-snake", "contributions": [ "bug", "doc" ] }, { "login": "ScriptTiger", "name": "ScriptTiger", "avatar_url": "https://avatars.githubusercontent.com/u/29940916?v=4", "profile": "https://scripttiger.github.io/", "contributions": [ "bug", "ideas", "test" ] }, { "login": "sjhgvr", "name": "Stephan van Ruth", "avatar_url": "https://avatars.githubusercontent.com/u/51121527?v=4", "profile": "https://github.com/sjhgvr", "contributions": [ "bug", "test" ] }, { "login": "smed79", "name": "smed79", "avatar_url": "https://avatars.githubusercontent.com/u/1873139?v=4", "profile": "https://github.com/smed79", "contributions": [ "bug", "ideas", "code", "question", "test" ] }, { "login": "speedmann", "name": "speedmann", "avatar_url": "https://avatars.githubusercontent.com/u/424659?v=4", "profile": "https://speedmann.de/", "contributions": [ "bug", "test" ] }, { "login": "spirillen", "name": "spirillen", "avatar_url": "https://avatars.githubusercontent.com/u/44526987?v=4", "profile": "https://www.mypdns.org/", "contributions": [ "a11y", "bug", "code", "content", "data", "doc", "example", "ideas", "maintenance", "mentoring", "promotion", "question", "review", "tool", "test", "tutorial", "talk", "userTesting" ] }, { "login": "WaLLy3K", "name": "WaLLy3K", "avatar_url": "https://avatars.githubusercontent.com/u/3049142?v=4", "profile": "https://infosec.exchange/@wally3k", "contributions": [ "bug", "ideas" ] }, { "login": "xxcriticxx", "name": "xxcriticxx", "avatar_url": "https://avatars.githubusercontent.com/u/15007183?v=4", "profile": "https://github.com/xxcriticxx", "contributions": [ "bug", "ideas", "test" ] }, { "login": "ybreza", "name": "Reza Rizqullah", "avatar_url": "https://avatars.githubusercontent.com/u/35470865?v=4", "profile": "https://github.com/ybreza", "contributions": [ "design", "code" ] }, { "login": "Yuki2718", "name": "Yuki2718", "avatar_url": "https://avatars.githubusercontent.com/u/58900598?v=4", "profile": "https://github.com/Yuki2718", "contributions": [ "bug", "test" ] }, { "login": "Zachinquarantine", "name": "Zachinquarantine", "avatar_url": "https://avatars.githubusercontent.com/u/69423184?v=4", "profile": "https://github.com/Zachinquarantine", "contributions": [ "code" ] }, { "login": "ZeroDot1", "name": "ZeroDot1", "avatar_url": "https://avatars.githubusercontent.com/u/28985171?v=4", "profile": "http://bit.ly/cBWeb", "contributions": [ "bug", "ideas", "question", "test", "code" ] }, { "login": "ryanbr", "name": "Fanboynz", "avatar_url": "https://avatars.githubusercontent.com/u/1659004?v=4", "profile": "http://www.fanboy.co.nz/", "contributions": [ "bug", "ideas", "financial", "test", "userTesting" ] }, { "login": "StevenBlack", "name": "Steven Black", "avatar_url": "https://avatars.githubusercontent.com/u/80144?v=4", "profile": "http://stevenblack.com/", "contributions": [ "ideas", "financial" ] } ], "contributorsPerLine": 7, "contributorsSortAlphabetically": true, "linkToUsage": false } PyFunceble-4.2.29.dev/.coveragerc000066400000000000000000000026631467462152100165610ustar00rootroot00000000000000[run] branch = False omit = # omit the following directory */pbr/* */site-packages/* /home/travis/virtualenv/* *.eggs/* */distutils/* # omit the following file PyFunceble/dataset/mariadb_base.py PyFunceble/dataset/*/mariadb.py PyFunceble/dataset/*/mysql.py PyFunceble/checker/availability/extra_rules.py PyFunceble/__init__.py PyFunceble/logger.py PyFunceble/database/* PyFunceble/cli/* [report] # This should be False one we move into production skip_covered = False # Regexes for lines to exclude from consideration exclude_lines = # Have to re-enable the standard pragma pragma: no cover # Never cover __init__ def __init__ # Don't complain about missing debug-only code: def __repr__ # Don't complain if tests don't hit defensive assertion code: raise AssertionError raise NotImplementedError # Don't complain if non-runnable code isn't run: if __name__ == .__main__.: # Don't complain for those blocks PyFunceble\.storage\.CONFIGURATION\.cli_testing\.db_type == "mariadb" PyFunceble\.storage\.CONFIGURATION\.cli_testing\.db_type == "mysql" # Don't complain about those. to_json\( _mysql\( _mariadb\( PyFunceble\.facility\.Logger\. # Manual handling of imports. except\sModuleNotFoundError\: except\sImportError: ignore_errors = True fail_under = 70 [html] directory = coverage_html_report PyFunceble-4.2.29.dev/.github/000077500000000000000000000000001467462152100157715ustar00rootroot00000000000000PyFunceble-4.2.29.dev/.github/FUNDING.yml000066400000000000000000000003621467462152100176070ustar00rootroot00000000000000# These are supported funding model platforms github: [funilrys] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] ko_fi: funilrys # Replace with a single Ko-fi username custom: ["https://www.paypal.me/funilrys"] PyFunceble-4.2.29.dev/.github/ISSUE_TEMPLATE/000077500000000000000000000000001467462152100201545ustar00rootroot00000000000000PyFunceble-4.2.29.dev/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000016701467462152100226520ustar00rootroot00000000000000--- name: Bug report about: Create a bug report to help us improve and fix undocumented or unknown issues. title: "BUG: " labels: bug assignees: funilrys --- ## Description ## Configuration ## Reproduction ## Expected behavior ## Screenshots ## Versions **OS:** **Python Version:** **PyFunceble Version:** ## Additional context PyFunceble-4.2.29.dev/.github/ISSUE_TEMPLATE/config.yaml000066400000000000000000000000331467462152100223010ustar00rootroot00000000000000blank_issues_enabled: true PyFunceble-4.2.29.dev/.github/ISSUE_TEMPLATE/documentation.md000066400000000000000000000005501467462152100233470ustar00rootroot00000000000000--- name: Documentation about: Create a report to help us improve the documentation. title: 'DOC: ' labels: documentation assignees: funilrys --- ## Description ## Suggestion / Improvement PyFunceble-4.2.29.dev/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000011401467462152100236750ustar00rootroot00000000000000--- name: Feature request about: Suggest a feature or an idea for this project. title: 'FEATURE: ' labels: features, enhancement assignees: funilrys --- ## Description ## Possible Solution ## Considered Alternative ## Additional context PyFunceble-4.2.29.dev/.github/ISSUE_TEMPLATE/help.md000066400000000000000000000002611467462152100214250ustar00rootroot00000000000000--- name: Help Wanted about: Ask for help. title: "HELP: " labels: help wanted assignees: funilrys --- ## Description PyFunceble-4.2.29.dev/.github/workflows/000077500000000000000000000000001467462152100200265ustar00rootroot00000000000000PyFunceble-4.2.29.dev/.github/workflows/branches.yml000066400000000000000000000145501467462152100223430ustar00rootroot00000000000000name: Branches Development Workflow on: pull_request: branches: - "**" - "!dev" - "!master" push: branches: - "**" - "!dev" - "!master" schedule: - cron: "0 0 * * *" jobs: lint: name: Lint PyFunceble runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install pylint - name: Lint PyFunceble with Pylint run: pylint PyFunceble - name: Lint tests with Pylint run: pylint tests test: needs: [lint] name: "[${{ matrix.os }}-py${{ matrix.python_version }}] Test PyFunceble" runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" os: - ubuntu-latest - macos-latest - windows-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install tox coveralls - name: Test PyFunceble as defined by tox.ini run: | tox -c tox.ini - name: Upload Coverage continue-on-error: true run: | coveralls env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} COVERALLS_PARALLEL: true coveralls: needs: test name: Finish Coveralls runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest steps: - name: Sending finish flag to coveralls.io uses: coverallsapp/github-action@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel-finished: true run_cli: needs: test name: "[${{ matrix.os }}-py${{ matrix.python_version }}] Run PyFunceble" runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" os: - ubuntu-latest - macos-latest - windows-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install tox - name: Run PyFunceble as defined by tox_run.ini run: tox -c tox_run.ini run_cli_mariadb: needs: test name: "[${{ matrix.os }}-py${{ matrix.python_version }}] Run PyFunceble (with mariadb)" runs-on: "${{ matrix.os }}" services: mariadb: image: ghcr.io/pyfunceble/mariadb/mariadb:latest ports: - 3306:3306 env: MYSQL_USER: pyfunceble MYSQL_PASSWORD: my_pyfunceble_password MYSQL_DATABASE: pyfunceble MYSQL_ROOT_PASSWORD: my_awesome_root_password options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3 env: PYFUNCEBLE_DB_CHARSET: utf8mb4 PYFUNCEBLE_DB_HOST: "127.0.0.1" PYFUNCEBLE_DB_NAME: pyfunceble PYFUNCEBLE_DB_PASSWORD: my_pyfunceble_password PYFUNCEBLE_DB_PORT: "3306" PYFUNCEBLE_DB_USERNAME: pyfunceble strategy: fail-fast: false matrix: python_version: - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install tox - name: Run PyFunceble as defined by tox_run_mariadb.ini run: tox -c tox_run_mariadb.ini run_cli_postgresql: needs: test name: "[${{ matrix.os }}-py${{ matrix.python_version }}] Run PyFunceble (with postgresql)" runs-on: "${{ matrix.os }}" services: mariadb: image: postgres:latest ports: - 5432:5432 env: POSTGRES_USER: pyfunceble POSTGRES_PASSWORD: my_pyfunceble_password POSTGRES_DB: pyfunceble MYSQL_ROOT_PASSWORD: my_awesome_root_password options: --health-cmd="pg_isready --host=localhost --username=pyfunceble --port=5432" --health-interval=5s --health-timeout=2s --health-retries=3 env: PYFUNCEBLE_DB_CHARSET: utf8 PYFUNCEBLE_DB_HOST: "127.0.0.1" PYFUNCEBLE_DB_NAME: pyfunceble PYFUNCEBLE_DB_PASSWORD: my_pyfunceble_password PYFUNCEBLE_DB_PORT: "3306" PYFUNCEBLE_DB_USERNAME: pyfunceble strategy: fail-fast: false matrix: python_version: - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install tox psycopg2 - name: Run PyFunceble as defined by tox_run_postgresql.ini run: tox -c tox_run_postgresql.ini PyFunceble-4.2.29.dev/.github/workflows/dev.yml000066400000000000000000000377011467462152100213370ustar00rootroot00000000000000name: Dev Deployment Workflow on: pull_request: branches: - dev push: branches: - dev schedule: - cron: "0 0 * * *" jobs: lint: name: Lint PyFunceble runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install pylint - name: Lint PyFunceble with Pylint run: pylint PyFunceble - name: Lint tests with Pylint run: pylint tests deps_safety_check: name: Check the safety of our dependencies. runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install safety - name: Check the safety of our dependencies. run: safety check -i 51668 -i 62044 -i 67599 -i 70612 test: needs: [lint, deps_safety_check] name: "[${{ matrix.os }}-py${{ matrix.python_version }}] Test PyFunceble" runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" os: - ubuntu-latest - macos-latest - windows-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install tox coveralls - name: Test PyFunceble as defined by tox.ini run: | tox -c tox.ini - name: Upload Coverage continue-on-error: true run: | coveralls env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} COVERALLS_PARALLEL: true coveralls: continue-on-error: true needs: test name: Finish Coveralls runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest steps: - name: Sending finish flag to coveralls.io uses: coverallsapp/github-action@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel-finished: true run_cli: needs: test name: "[${{ matrix.os }}-py${{ matrix.python_version }}] Run PyFunceble" runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" os: - ubuntu-latest - macos-latest - windows-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install tox - name: Run PyFunceble as defined by tox_run.ini run: tox -c tox_run.ini run_cli_mariadb: needs: test name: "[${{ matrix.os }}-py${{ matrix.python_version }}] Run PyFunceble (with mariadb)" runs-on: "${{ matrix.os }}" services: mariadb: image: ghcr.io/pyfunceble/mariadb/mariadb:latest ports: - 3306:3306 env: MYSQL_USER: pyfunceble MYSQL_PASSWORD: my_pyfunceble_password MYSQL_DATABASE: pyfunceble MYSQL_ROOT_PASSWORD: my_awesome_root_password options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3 env: PYFUNCEBLE_DB_CHARSET: utf8mb4 PYFUNCEBLE_DB_HOST: "127.0.0.1" PYFUNCEBLE_DB_NAME: pyfunceble PYFUNCEBLE_DB_PASSWORD: my_pyfunceble_password PYFUNCEBLE_DB_PORT: "3306" PYFUNCEBLE_DB_USERNAME: pyfunceble strategy: fail-fast: false matrix: python_version: - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install tox - name: Run PyFunceble as defined by tox_run_mariadb.ini run: tox -c tox_run_mariadb.ini run_cli_postgresql: needs: test name: "[${{ matrix.os }}-py${{ matrix.python_version }}] Run PyFunceble (with postgresql)" runs-on: "${{ matrix.os }}" services: mariadb: image: postgres:latest ports: - 5432:5432 env: POSTGRES_USER: pyfunceble POSTGRES_PASSWORD: my_pyfunceble_password POSTGRES_DB: pyfunceble MYSQL_ROOT_PASSWORD: my_awesome_root_password options: --health-cmd="pg_isready --host=localhost --username=pyfunceble --port=5432" --health-interval=5s --health-timeout=2s --health-retries=3 env: PYFUNCEBLE_DB_CHARSET: utf8 PYFUNCEBLE_DB_HOST: "127.0.0.1" PYFUNCEBLE_DB_NAME: pyfunceble PYFUNCEBLE_DB_PASSWORD: my_pyfunceble_password PYFUNCEBLE_DB_PORT: "5432" PYFUNCEBLE_DB_USERNAME: pyfunceble strategy: fail-fast: false matrix: python_version: - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install tox psycopg2 - name: Run PyFunceble as defined by tox_run_postgresql.ini run: tox -c tox_run_postgresql.ini deploy_to_pypi: needs: [run_cli, run_cli_mariadb, run_cli_postgresql] name: "Deploy ๐Ÿ“ฆ to the PyPi" if: github.event_name == 'push' && github.ref == 'refs/heads/dev' runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install twine wheel setuptools - name: Build ๐Ÿ“ฆ run: | python setup.py sdist bdist_wheel - name: Check ๐Ÿ“ฆ run: | twine check dist/* - name: Publish ๐Ÿ“ฆ to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: password: ${{ secrets.PYPI_DEV_API_TOKEN }} skip-existing: true deploy_docs_container: needs: [run_cli, run_cli_mariadb, run_cli_postgresql] name: "Deploy ๐Ÿ—Ž (๐Ÿ“ฆ)" if: github.event_name == 'push' && github.ref == 'refs/heads/dev' runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest env: DOCKER_PYTHON_VERSION: "3.12" BUILDER_CLONE_DIRNAME: pyfunceble_docker steps: - uses: actions/checkout@v4 name: Clone repository - uses: actions/checkout@v4 name: Clone docker ๐Ÿ“ฆ repository with: repository: PyFunceble/docker path: ${{ env.BUILDER_CLONE_DIRNAME }}/ - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install setuptools wheel pip install ${{ env.BUILDER_CLONE_DIRNAME }}/. - name: Get version of builder run: | pyfunceble-docker-builder --version - name: Read package name run: | python setup.py --name - name: Read package version run: | python setup.py --version - name: Read commit ID run: | git log -1 --format=format:'%H' - name: Build, Check and Publish ๐Ÿ“ฆ to Docker Hub run: > set -x ; pyfunceble-docker-builder -b ${{ env.BUILDER_CLONE_DIRNAME }}/docs_builder -p docs --pyfunceble-version="$(python setup.py --version)" --python-version="${DOCKER_PYTHON_VERSION}" --is-latest --publish --commit="$(git log -1 --format=format:'%H')" env: OUR_DOCKER_USERNAME: ${{ secrets.OUR_DOCKER_USERNAME }} OUR_DOCKER_PASSWORD: ${{ secrets.OUR_DOCKER_PASSWORD }} OUR_DOCKER_EMAIL: ${{ secrets.OUR_DOCKER_EMAIL }} - name: Build, Check and Publish ๐Ÿ“ฆ to Internal Hub run: > set -x ; pyfunceble-docker-builder -b ${{ env.BUILDER_CLONE_DIRNAME }}/docs_builder -p docs --pyfunceble-version="$(python setup.py --version)" --python-version="${DOCKER_PYTHON_VERSION}" --is-latest --publish --commit="$(git log -1 --format=format:'%H')" env: OUR_DOCKER_USERNAME: ${{ secrets.INTERNAL_DOCKER_USERNAME }} OUR_DOCKER_PASSWORD: ${{ secrets.INTERNAL_DOCKER_PASSWORD }} OUR_DOCKER_REGISTRY: ${{ secrets.INTERNAL_DOCKER_REGISTRY }} deploy_to_docker_hub: needs: [run_cli, run_cli_mariadb, run_cli_postgresql] name: "Deploy ๐Ÿ“ฆ to the Docker Hub" if: github.event_name == 'push' && github.ref == 'refs/heads/dev' runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest env: DOCKER_PYTHON_VERSION: "3.12" BUILDER_CLONE_DIRNAME: pyfunceble_docker OUR_DOCKER_USERNAME: ${{ secrets.OUR_DOCKER_USERNAME }} OUR_DOCKER_PASSWORD: ${{ secrets.OUR_DOCKER_PASSWORD }} OUR_DOCKER_EMAIL: ${{ secrets.OUR_DOCKER_EMAIL }} steps: - uses: actions/checkout@v4 name: Clone repository - uses: actions/checkout@v4 name: Clone docker ๐Ÿ“ฆ repository with: repository: PyFunceble/docker path: ${{ env.BUILDER_CLONE_DIRNAME }}/ - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install setuptools wheel pip install ${{ env.BUILDER_CLONE_DIRNAME }}/. - name: Get version of builder run: | pyfunceble-docker-builder --version - name: Read package name run: | python setup.py --name - name: Read package version run: | python setup.py --version - name: Read commit ID run: | git log -1 --format=format:'%H' - name: Build, Check and Publish ๐Ÿ“ฆ run: > set -x ; pyfunceble-docker-builder -b ${{ env.BUILDER_CLONE_DIRNAME }}/builder -p "$(python setup.py --name)" --pyfunceble-version="$(python setup.py --version)" --python-version="${DOCKER_PYTHON_VERSION}" --is-latest --publish --commit="$(git log -1 --format=format:'%H')" deploy_to_aur: needs: deploy_to_pypi name: "Deploy ๐Ÿ“ฆ to the AUR" if: github.event_name == 'push' && github.ref == 'refs/heads/dev' runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: os: - ubuntu-latest container: image: archlinux steps: - name: Store the SSH key run: | echo "${{ secrets.AUR_SSH_KEY }}" | install -Dm600 /dev/stdin /root/.ssh/id_rsa - name: Get time for cache id: cache_time run: echo "time=$(date +%F-%T)" >> ${GITHUB_OUTPUT} - name: Set up cache uses: actions/cache@master with: path: /var/cache/pacman/pkg key: pacman-cache-x86_64-${{ steps.cache_time.outputs.time }} restore-keys: pacman-cache-x86_64- - name: Install dependencies run: | pacman -Syu --needed --noconfirm && \ pacman -S --needed --noconfirm git binutils pacman-contrib openssh rsync python python-setuptools jq - uses: actions/checkout@v4 name: Clone repository - name: Publish ๐Ÿ“ฆ to the AUR - if necessary env: GIT_SSH_COMMAND: "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" run: | aurRepoDir=/tmp/pyfunceble-dev githubRepoDir="${PWD}" buildDir="/tmp/build" latest=$(python3 setup.py --version) if [[ $(python3 setup.py --name) == "PyFunceble-dev" ]] then licenseURL="https://raw.githubusercontent.com/funilrys/PyFunceble/dev/LICENSE" newURL=$(curl -s https://pypi.org/pypi/PyFunceble-dev/json | jq -r ".releases.\"${latest}\"[] | select(.filename | strings | test(\".tar\")).url") else licenseURL="https://raw.githubusercontent.com/funilrys/PyFunceble/master/LICENSE" newURL=$(curl -s https://pypi.org/pypi/PyFunceble/json | jq -r ".releases.\"${latest}\"[] | select(.filename | strings | test(\".tar\")).url") fi git config --global --add safe.directory ${GITHUB_WORKSPACE} git config --global --add safe.directory ${aurRepoDir} git config --global --add safe.directory ${githubRepoDir} git config --global user.name ${{ github.actor }} git config --global user.email ${{ secrets.GIT_EMAIL }} git clone ssh://aur@aur.archlinux.org/pyfunceble-dev.git ${aurRepoDir} rsync --progress --delete -r --exclude={'*.gz','*.xz','.github','pkg','src','.git','LICENSE'} ${aurRepoDir}/ ${buildDir}/ cd ${buildDir} current=$(grep -P "^pkgver" PKGBUILD | cut -d= -f2) echo "Previous version: ${current}" echo "New version: ${latest}" useradd makepkg chown makepkg:root . -R sed "/^pkgver=/s/.*/pkgver=${latest}/" -i PKGBUILD sed "/^pkgrel=/s/.*/pkgrel=1/" -i PKGBUILD sed "s,^source=(.*),source=('${newURL}' '${licenseURL}')," -i PKGBUILD su makepkg -c "updpkgsums" su makepkg -c "makepkg --printsrcinfo" > .SRCINFO rsync --progress --delete -r --exclude={'*.gz','*.xz','.github','pkg','src','.git','LICENSE'} ${buildDir}/ ${aurRepoDir}/ cd ${aurRepoDir} git add . git diff --quiet --exit-code --cached || git commit -m "Update PyFunceble-dev to v${latest}" git push origin master PyFunceble-4.2.29.dev/.github/workflows/stable.yml000066400000000000000000000226031467462152100220260ustar00rootroot00000000000000name: Stable Deployment Workflow on: pull_request: branches: - master push: branches: - master schedule: - cron: "0 0 * * *" jobs: lint: name: Lint PyFunceble runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install pylint - name: Lint PyFunceble with Pylint run: pylint PyFunceble - name: Lint tests with Pylint run: pylint tests deps_safety_check: name: Check the safety of our dependencies. runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install safety - name: Check the safety of our dependencies. run: safety check -i 51668 -i 62044 -i 67599 -i 70612 test: needs: [lint, deps_safety_check] name: "[${{ matrix.os }}-py${{ matrix.python_version }}] Test PyFunceble" runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" os: - ubuntu-latest - macos-latest - windows-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install tox coveralls - name: Test PyFunceble as defined by tox.ini run: | tox -c tox.ini - name: Upload Coverage continue-on-error: true run: | coveralls env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} COVERALLS_PARALLEL: true coveralls: continue-on-error: true needs: test name: Finish Coveralls runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest steps: - name: Sending finish flag to coveralls.io uses: coverallsapp/github-action@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel-finished: true deploy_to_pypi: needs: test name: "Deploy ๐Ÿ“ฆ to the PyPi" if: github.event_name == 'push' && github.ref == 'refs/heads/master' runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v4 name: Clone repository - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install twine wheel setuptools - name: Build ๐Ÿ“ฆ run: | python setup.py sdist bdist_wheel - name: Check ๐Ÿ“ฆ run: | twine check dist/* - name: Publish ๐Ÿ“ฆ to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: password: ${{ secrets.PYPI_API_TOKEN }} skip-existing: true deploy_to_docker_hub: needs: test name: "Deploy ๐Ÿ“ฆ to the Docker Hub" if: github.event_name == 'push' && github.ref == 'refs/heads/master' runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest env: DOCKER_PYTHON_VERSION: "3.12" BUILDER_CLONE_DIRNAME: pyfunceble_docker OUR_DOCKER_USERNAME: ${{ secrets.OUR_DOCKER_USERNAME }} OUR_DOCKER_PASSWORD: ${{ secrets.OUR_DOCKER_PASSWORD }} OUR_DOCKER_EMAIL: ${{ secrets.OUR_DOCKER_EMAIL }} steps: - uses: actions/checkout@v4 name: Clone repository - uses: actions/checkout@v4 name: Clone docker ๐Ÿ“ฆ repository with: repository: PyFunceble/docker path: ${{ env.BUILDER_CLONE_DIRNAME }}/ - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install --upgrade pip pip install setuptools wheel pip install ${{ env.BUILDER_CLONE_DIRNAME }}/. - name: Get version of builder run: | pyfunceble-docker-builder --version - name: Read package name run: | python setup.py --name - name: Read package version run: | python setup.py --version - name: Read commit ID run: | git log -1 --format=format:'%H' - name: Build, Check and Publish ๐Ÿ“ฆ run: > pyfunceble-docker-builder -b ${{ env.BUILDER_CLONE_DIRNAME }}/builder -p "$(python setup.py --name)" --pyfunceble-version="$(python setup.py --version)" --python-version="${DOCKER_PYTHON_VERSION}" --is-latest --publish --commit="$(git log -1 --format=format:'%H')" deploy_to_aur: needs: deploy_to_pypi name: "Deploy ๐Ÿ“ฆ to the AUR" if: github.event_name == 'push' && github.ref == 'refs/heads/master' runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: os: - ubuntu-latest container: image: archlinux steps: - name: Store the SSH key run: | echo "${{ secrets.AUR_SSH_KEY }}" | install -Dm600 /dev/stdin /root/.ssh/id_rsa - name: Get time for cache id: cache_time run: echo "time=$(date +%F-%T)" >> ${GITHUB_OUTPUT} - name: Set up cache uses: actions/cache@master with: path: /var/cache/pacman/pkg key: pacman-cache-x86_64-${{ steps.cache_time.outputs.time }} restore-keys: pacman-cache-x86_64- - name: Install dependencies run: | pacman -Syu --needed --noconfirm && \ pacman -S --needed --noconfirm git binutils pacman-contrib openssh rsync python python-setuptools jq - uses: actions/checkout@v4 name: Clone repository - name: Publish ๐Ÿ“ฆ to the AUR - if necessary env: GIT_SSH_COMMAND: "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" run: | aurRepoDir=/tmp/pyfunceble githubRepoDir="${PWD}" buildDir="/tmp/build" latest=$(python3 setup.py --version) if [[ $(python3 setup.py --name) == "PyFunceble-dev" ]] then licenseURL="https://raw.githubusercontent.com/funilrys/PdyFunceble/dev/LICENSE" newURL=$(curl -s https://pypi.org/pypi/PyFunceble-dev/json | jq -r ".releases.\"${latest}\"[] | select(.filename | strings | test(\".tar\")).url") else licenseURL="https://raw.githubusercontent.com/funilrys/PyFunceble/master/LICENSE" newURL=$(curl -s https://pypi.org/pypi/PyFunceble/json | jq -r ".releases.\"${latest}\"[] | select(.filename | strings | test(\".tar\")).url") fi git config --global --add safe.directory ${GITHUB_WORKSPACE} git config --global --add safe.directory ${aurRepoDir} git config --global --add safe.directory ${githubRepoDir} git config --global user.name ${{ github.actor }} git config --global user.email ${{ secrets.GIT_EMAIL }} git clone ssh://aur@aur.archlinux.org/pyfunceble.git ${aurRepoDir} rsync --progress --delete -r --exclude={'*.gz','*.xz','.github','pkg','src','.git','LICENSE'} ${aurRepoDir}/ ${buildDir}/ cd ${buildDir} current=$(grep -P "^pkgver" PKGBUILD | cut -d= -f2) echo "Previous version: ${current}" echo "New version: ${latest}" useradd makepkg chown makepkg:root . -R sed "/^pkgver=/s/.*/pkgver=${latest}/" -i PKGBUILD sed "/^pkgrel=/s/.*/pkgrel=1/" -i PKGBUILD sed "s,^source=(.*),source=('${newURL}' '${licenseURL}')," -i PKGBUILD su makepkg -c "updpkgsums" su makepkg -c "makepkg --printsrcinfo" > .SRCINFO rsync --progress --delete -r --exclude={'*.gz','*.xz','.github','pkg','src','.git','LICENSE'} ${buildDir}/ ${aurRepoDir}/ cd ${aurRepoDir} git add . git diff --quiet --exit-code --cached || git commit -m "Update PyFunceble to v${latest}" git push origin master PyFunceble-4.2.29.dev/.gitignore000066400000000000000000000030151467462152100164200ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # 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 .coverage.* .cache nosetests.xml coverage.xml *.cover .hypothesis/ # Translations *.mo *.pot # Django stuff: *.log .static_storage/ .media/ local_settings.py # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # pyenv .python-version # celery beat schedule file celerybeat-schedule # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ # VSCode (Visual Basic Code) .vscode # Project related .pyfunceble_intern_downtime.json .pyfunceble-env .PyFunceble.yaml .PyFunceble.overwrite.yaml dir_structure.json hashes_tracker.json iana-domains-db.json inactive_db.json inactive.csv ipv4_reputation.data mining.json public-suffix.json pyfunceble.db user_agents.json whois_db.json whois.csv PyFunceble-4.2.29.dev/CODE_OF_CONDUCT.md000066400000000000000000000114771467462152100172420ustar00rootroot00000000000000# Code of Conduct - PyFunceble ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at <>. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant](https://contributor-covenant.org/), version [1.4](https://www.contributor-covenant.org/version/1/4/code-of-conduct/code_of_conduct.md) and [2.0](https://www.contributor-covenant.org/version/2/0/code_of_conduct/code_of_conduct.md), and was generated by [contributing-gen](https://github.com/bttger/contributing-gen).PyFunceble-4.2.29.dev/CONTRIBUTING.md000066400000000000000000000315771467462152100166770ustar00rootroot00000000000000 # Contributing to PyFunceble First off, thanks for taking the time to contribute! โค๏ธ All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. ๐ŸŽ‰ > And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about: > > - Star the project > - Tweet about it > - Refer this project in your project's readme > - Mention the project at local meetups and tell your friends/colleagues ## Table of Contents - [Contributing to PyFunceble](#contributing-to-pyfunceble) - [Table of Contents](#table-of-contents) - [Code of Conduct](#code-of-conduct) - [I Have a Question](#i-have-a-question) - [I Want To Contribute](#i-want-to-contribute) - [Reporting Bugs](#reporting-bugs) - [Before Submitting a Bug Report](#before-submitting-a-bug-report) - [How Do I Submit a Good Bug Report?](#how-do-i-submit-a-good-bug-report) - [Suggesting Enhancements](#suggesting-enhancements) - [Before Submitting an Enhancement](#before-submitting-an-enhancement) - [How Do I Submit a Good Enhancement Suggestion?](#how-do-i-submit-a-good-enhancement-suggestion) - [Your First Code Contribution](#your-first-code-contribution) - [Notes for Code Contributions](#notes-for-code-contributions) - [Improving The Documentation](#improving-the-documentation) - [Styleguides](#styleguides) - [Code Format](#code-format) - [Code Linting](#code-linting) - [Tests Coverage](#tests-coverage) - [Commit Messages](#commit-messages) - [Attribution](#attribution) ## Code of Conduct This project and everyone participating in it is governed by the [PyFunceble Code of Conduct](https://github.com/funilrys/PyFuncebleblob/dev/CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to . ## I Have a Question > If you want to ask a question, we assume that you have read the available [Documentation](https://docs.pyfunceble.com). Before you ask a question, it is best to search for existing [Issues](https://github.com/funilrys/PyFunceble/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first. If you then still feel the need to ask a question and need clarification, we recommend the following: - Open an [Issue](https://github.com/funilrys/PyFunceble/issues/new). - Provide as much context as you can about what you're running into. - Provide project and platform versions (nodejs, npm, etc), depending on what seems relevant. We will then take care of the issue as soon as possible. ## I Want To Contribute > ### Legal Notice > > When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license. ### Reporting Bugs #### Before Submitting a Bug Report A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible. - Make sure that you are using the latest version. - Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://docs.pyfunceble.com). If you are looking for support, you might want to check [this section](#i-have-a-question)). - To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/funilrys/PyFunceble/issues?q=label%3Abug). - Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue. - Collect information about the bug: - Stack trace (Traceback) - OS, Platform and Version (Windows, Linux, macOS, x86, ARM) - Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant. - Possibly your input and the output - Can you reliably reproduce the issue? And can you also reproduce it with older versions? #### How Do I Submit a Good Bug Report? > You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public. Instead sensitive bugs must be sent by email to . We use GitHub issues to track bugs and errors. If you run into an issue with the project: - Open an [Issue](https://github.com/funilrys/PyFunceble/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.) - Explain the behavior you would expect and the actual behavior. - Please provide as much context as possible and describe the _reproduction steps_ that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case. - Provide the information you collected in the previous section. Once it's filed: - The project team will label the issue accordingly. - A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `needs-repro`. Bugs with the `needs-repro` tag will not be addressed until they are reproduced. - If the team is able to reproduce the issue, it will be marked `needs-fix`, as well as possibly other tags (such as `critical`), and the issue will be left to be [implemented by someone](#your-first-code-contribution). ### Suggesting Enhancements This section guides you through submitting an enhancement suggestion for PyFunceble, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions. #### Before Submitting an Enhancement - Make sure that you are using the latest version. - Read the [documentation](https://docs.pyfunceble.com) carefully and find out if the functionality is already covered, maybe by an individual configuration. - Perform a [search](https://github.com/funilrys/PyFunceble/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. - Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library. #### How Do I Submit a Good Enhancement Suggestion? Enhancement suggestions are tracked as [GitHub issues](https://github.com/funilrys/PyFunceble/issues). - Use a **clear and descriptive title** for the issue to identify the suggestion. - Provide a **step-by-step description of the suggested enhancement** in as many details as possible. - **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you. - You may want to **include screenshots and animated GIFs** which help you demonstrate the steps or point out the part which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux. - **Explain why this enhancement would be useful** to most PyFunceble users. You may also want to point out the other projects that solved it better and which could serve as inspiration. ### Your First Code Contribution We do not any constraint regarding the way to use or configure your IDE. But, we compiled some of the necessary steps that you may need before starting to hack PyFunceble. 1. If you haven't already: Clone or Fork the repository. 2. Create a new branch for your change. 3. Create a virtual environment (recommended) ```shell virtualenv -p python3 venv . venv/bin/activate ``` 4. Install the development related dependencies. ```shell # Assuming you activated the environment. pip3 install -e .[dev,test] ``` 5. Test if pyfunceble is running. ```shell pyfunceble --version ``` 6. Test if tests are running. ```shell tox ``` Once you went through all of those steps, you are ready and can start to code. #### Notes for Code Contributions 1. When you are working on a new feature or a bug, make sure to create a new branch. 2. When developing, please keep in mind that your configuration files located in the `~/.config/pyfunceble/` directory will be ignored. Therefore, you may want to create a new configuration file in the root of the repository. You can overwrite it by using the `PYFUNCEBLE_CONFIG_DIR` environment variable. ### Improving The Documentation Maintaining a documentation is rarely a one man action. If you think a paragraph, a section should be improved or a totally new section added, feel free to write a draft and submit your change through a Pull Request. If you want to test your changes locally, some steps are necessary: 1. If you haven't already: Clone or Fork the repository. 2. Create a new branch for your change. 3. Create a virtual environment (recommended) ```shell virtualenv -p python3 venv . venv/bin/activate ``` 4. Install the docs related dependencies. ```shell # Assuming you activated the environment. pip3 install -e .[docs] ``` 5. Serve the documentation for live testing: ```shell mkdocs serve ``` Once you went through all of those steps, you are ready and can start editing the documentation. ## Styleguides ### Code Format We love unique contributions, but we hate to deal with serveral code formats. Therefore, we adopted [Black](https://github.com/ambv/black), _The uncompromising Python code formatter_, to format our code. No more headache or thinking, just apply the `black` command against your change and you are good to go! ### Code Linting We are human and we sometime make mistakes. One way to reduce issues before a change hits a global deployment is through linting. To reduce headeche, the repository is already configured! You can lint your code before commiting them by running `pylint` against your modified files. ### Tests Coverage We want to have a code test coverage of at lease 60%. Therefore, be sure to run `tox` before commiting your changes! ### Commit Messages Your git message should be consice but informative. Therefore, we ask you the follow the following convention: ``` [Verb] [Description] Paragraphs with some details/context (if needed). ``` ## Attribution This guide is based on the **contributing-gen**. [Make your own](https://github.com/bttger/contributing-gen)! PyFunceble-4.2.29.dev/CONTRIBUTORS.md000066400000000000000000000454241467462152100167210ustar00rootroot00000000000000# Contributors Thanks to those awesome peoples for their awesome and crazy idea(s), contribution(s) and or issue report which made or make PyFunceble a better tool.
Avinash Reddy
Avinash Reddy

๐Ÿ›
BigDargon
BigDargon

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ฃ โš ๏ธ
Fanboynz
Fanboynz

๐Ÿ› ๐Ÿค” ๐Ÿ’ต โš ๏ธ ๐Ÿ““
Haris Guลกiฤ‡
Haris Guลกiฤ‡

๐Ÿ“– ๏ธ๏ธ๏ธ๏ธโ™ฟ๏ธ ๐Ÿ”ง โš ๏ธ ๐Ÿ“น โœ… ๐Ÿ’ป
Imre Eilertsen
Imre Eilertsen

๏ธ๏ธ๏ธ๏ธโ™ฟ๏ธ ๐Ÿ› ๐Ÿ”ฃ ๐Ÿ’ก ๐Ÿ’ต ๐Ÿค” ๐Ÿ“ฃ ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ง โš ๏ธ ๐Ÿ““
Kowith Singkornkeeree
Kowith Singkornkeeree

๐Ÿ›
Mitchell Krog
Mitchell Krog

๏ธ๏ธ๏ธ๏ธโ™ฟ๏ธ ๐Ÿ› ๐Ÿ“ ๐Ÿ’ป ๐Ÿ–‹ ๐Ÿ”ฃ ๐Ÿ“– ๐ŸŽจ ๐Ÿ’ก ๐Ÿ” ๐Ÿค” ๐Ÿš‡ ๐Ÿง‘โ€๐Ÿซ ๐Ÿ“ฆ ๐Ÿ”Œ ๐Ÿ“ฃ ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ง โš ๏ธ โœ… ๐Ÿ“ข ๐Ÿ““
Nilsonfsilva
Nilsonfsilva

๐Ÿ› ๐Ÿš‡ ๐Ÿ“ฆ ๐Ÿ”ง โš ๏ธ
Odyseus
Odyseus

๐Ÿ› โš ๏ธ
Reza Rizqullah
Reza Rizqullah

๐ŸŽจ ๐Ÿ’ป
ScriptTiger
ScriptTiger

๐Ÿ› ๐Ÿค” โš ๏ธ
Stephan van Ruth
Stephan van Ruth

๐Ÿ› โš ๏ธ
Steven Black
Steven Black

๐Ÿค” ๐Ÿ’ต
T145
T145

๐Ÿ› ๐Ÿค”
WaLLy3K
WaLLy3K

๐Ÿ› ๐Ÿค”
Yuki2718
Yuki2718

๐Ÿ› โš ๏ธ
Zachinquarantine
Zachinquarantine

๐Ÿ’ป
ZeroDot1
ZeroDot1

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ โš ๏ธ ๐Ÿ’ป
avatartw
avatartw

๐Ÿ›
dnmTX
dnmTX

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ฃ โš ๏ธ
gwarser
gwarser

๐Ÿ› ๐Ÿ”ฃ โš ๏ธ
hawkeye116477
hawkeye116477

๐Ÿ›
jawz101
jawz101

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ ๐Ÿ”ฃ
keczuppp
keczuppp

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ โš ๏ธ ๐Ÿ”ฃ
opav
opav

๐Ÿ› โš ๏ธ
rusty-snake
rusty-snake

๐Ÿ› ๐Ÿ“–
smed79
smed79

๐Ÿ› ๐Ÿค” ๐Ÿ’ป ๐Ÿ’ฌ โš ๏ธ
speedmann
speedmann

๐Ÿ› โš ๏ธ
spirillen
spirillen

๏ธ๏ธ๏ธ๏ธโ™ฟ๏ธ ๐Ÿ› ๐Ÿ’ป ๐Ÿ–‹ ๐Ÿ”ฃ ๐Ÿ“– ๐Ÿ’ก ๐Ÿค” ๐Ÿšง ๐Ÿง‘โ€๐Ÿซ ๐Ÿ“ฃ ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ง โš ๏ธ โœ… ๐Ÿ“ข ๐Ÿ““
watchman-pypi
watchman-pypi

๐Ÿ›
xxcriticxx
xxcriticxx

๐Ÿ› ๐Ÿค” โš ๏ธ
PyFunceble-4.2.29.dev/LICENSE000066400000000000000000000250541467462152100154440ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. PyFunceble-4.2.29.dev/MANIFEST.in000066400000000000000000000003151467462152100161660ustar00rootroot00000000000000graft PyFunceble global-exclude __pycache__ global-exclude *.py[co] include LICENSE include CODE_OF_CONDUCT.md include CONTRIBUTING.md include CONTRIBUTORS.md include requirements*.txt include version.yamlPyFunceble-4.2.29.dev/PyFunceble/000077500000000000000000000000001467462152100164655ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/__init__.py000066400000000000000000000544171467462152100206110ustar00rootroot00000000000000# pylint: disable=invalid-name """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 warnings from typing import List import PyFunceble.storage from PyFunceble.checker.availability.domain import DomainAvailabilityChecker from PyFunceble.checker.availability.domain_and_ip import DomainAndIPAvailabilityChecker from PyFunceble.checker.availability.ip import IPAvailabilityChecker from PyFunceble.checker.availability.status import AvailabilityCheckerStatus from PyFunceble.checker.availability.url import URLAvailabilityChecker from PyFunceble.checker.reputation.domain import DomainReputationChecker from PyFunceble.checker.reputation.domain_and_ip import DomainAndIPReputationChecker from PyFunceble.checker.reputation.ip import IPReputationChecker from PyFunceble.checker.reputation.url import URLReputationChecker from PyFunceble.checker.syntax.domain import DomainSyntaxChecker from PyFunceble.checker.syntax.domain_and_ip import DomainAndIPSyntaxChecker from PyFunceble.checker.syntax.ip import IPSyntaxChecker from PyFunceble.checker.syntax.ipv4 import IPv4SyntaxChecker from PyFunceble.checker.syntax.ipv6 import IPv6SyntaxChecker from PyFunceble.checker.syntax.second_lvl_domain import SecondLvlDomainSyntaxChecker from PyFunceble.checker.syntax.subdomain import SubDomainSyntaxChecker from PyFunceble.checker.syntax.url import URLSyntaxChecker from PyFunceble.converter.subject2complements import Subject2Complements __version__ = PyFunceble.storage.PROJECT_VERSION def load_config(*args, **kwargs) -> None: """ Placeholder before deletion. Since 4.0.0, you are not required to load the configuration before hand. If you still want too because you may want to use a special CLI related method, you can doing it so: :: import PyFunceble.facility PyFunceble.facility.ConfigLoader.start() """ warnings.warn( "PyFunceble.load_config may be removed in the future." "As of today, because the configuration is not necessary (anymore), " "this method does nothing. Consider it a placeholder.I" "Please consider using PyFunceble.facility.ConfigLoader.start instead.", DeprecationWarning, ) _, _ = args, kwargs def test(subject: str, **kwargs) -> AvailabilityCheckerStatus: """ Checks the avaialbility of the given subject assuming that it is a domain or an IP. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import DomainAndIPAvailabilityChecker my_subject = "example.org" the_status = DomainAndIPAvailabilityChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is available. print(f"{my_subject} is available ? {the_status.is_available()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.test may be removed in the future." "Please consider using PyFunceble.DomainAndIPAvailabilityChecker explicitly.", DeprecationWarning, ) return DomainAndIPAvailabilityChecker(subject, **kwargs).get_status() def url_test(subject: str, **kwargs) -> AvailabilityCheckerStatus: """ Checks the availability of the given subject assuming that it is a URL. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import URLAvailabilityChecker my_subject = "http://example.org" the_status = URLAvailabilityChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is available. print(f"{my_subject} is available ? {the_status.is_available()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.test may be removed in the future." "Please consider using PyFunceble.URLAvailabilityChecker explicitly.", DeprecationWarning, ) return URLAvailabilityChecker(subject, **kwargs).get_status() def is_second_level_domain(subject: str, **kwargs) -> bool: """ Checks if the given subject is a syntactically valid second level domain. .. warning:: This method was added for retrocompatibility. It may be removed in the future and is still available for convenience. Please consider the following alternative example: :: from PyFunceble import SecondLvlDomainSyntaxChecker my_subject = "example.org" the_status = SecondLvlDomainSyntaxChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is a second level domain. print(f"{my_subject} is 2nd level domain ? {the_status.is_valid()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.is_second_level_domain was added for retro compatibility. " "It may be removed in the future." "Please consider using PyFunceble.SecondLvlDomainSyntaxChecker explicitly.", ) return SecondLvlDomainSyntaxChecker(subject, **kwargs).is_valid() def is_domain(subject: str, **kwargs) -> bool: """ Checks if the given subject is a syntactically valid second level domain or subdomain. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import DomainSyntaxChecker my_subject = "example.org" the_status = DomainSyntaxChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is a domain (2nd level or subdomain). print(f"{my_subject} is domain ? {the_status.is_valid()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.is_domain may be removed in the future." "Please consider using PyFunceble.DomainSyntaxChecker explicitly.", DeprecationWarning, ) return DomainSyntaxChecker(subject, **kwargs).is_valid() def is_subdomain(subject: str, **kwargs) -> bool: """ Checks if the given subject is a syntactically valid subdomain. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import SubDomainSyntaxChecker my_subject = "hello.example.org" the_status = SubDomainSyntaxChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is a subdomain. print(f"{my_subject} is subdomain ? {the_status.is_valid()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.is_subdomain may be removed in the future." "Please consider using PyFunceble.SubDomainSyntaxChecker explicitly.", DeprecationWarning, ) return SubDomainSyntaxChecker(subject, **kwargs).is_valid() def is_ip(subject: str, **kwargs) -> bool: """ Checks if the given subject is a syntactically valid IP range. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import IPSyntaxChecker my_subject = "192.168.0.0" the_status = IPSyntaxChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is an IP (v4 or v6). print(f"{my_subject} is IP ? {the_status.is_valid()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.is_ip may be removed in the future." "Please consider using PyFunceble.IPSyntaxChecker explicitly.", DeprecationWarning, ) return IPSyntaxChecker(subject, **kwargs).is_valid() def is_ipv4(subject: str, **kwargs) -> bool: """ Checks if the given subject is a syntactically valid IPv4. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import IPSyntaxChecker my_subject = "192.168.0.0" the_status = IPSyntaxChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is an IPv4. print(f"{my_subject} is IPv4 ? {the_status.is_valid_v4()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.is_ipv4 be removed in the future." "Please consider using PyFunceble.IPSyntaxChecker explicitly.", DeprecationWarning, ) return IPSyntaxChecker(subject, **kwargs).is_valid_v4() def is_ipv6(subject: str, **kwargs) -> bool: """ Checks if the given subject is a syntactically valid IPv6. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import IPSyntaxChecker my_subject = "192.168.0.0" the_status = IPSyntaxChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is an IPv6. print(f"{my_subject} is IPv6 ? {the_status.is_valid_v6()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.is_ipv6 be removed in the future." "Please consider using PyFunceble.IPSyntaxChecker explicitly.", DeprecationWarning, ) return IPSyntaxChecker(subject, **kwargs).is_valid_v6() def is_ip_range(subject: str, **kwargs) -> bool: """ Checks if the given subject is a syntactically valid IP range. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import IPSyntaxChecker my_subject = "192.168.0.0" the_status = IPSyntaxChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is an IP range (v4 or v6). print(f"{my_subject} is IP range ? {the_status.is_valid_range()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.is_ip_range may be removed in the future." "Please consider using PyFunceble.IPSyntaxChecker explicitly.", DeprecationWarning, ) return IPSyntaxChecker(subject, **kwargs).is_valid_range() def is_ipv4_range(subject: str, **kwargs) -> bool: """ Checks if the given subject is a syntactically valid IPv4 range. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import IPSyntaxChecker my_subject = "192.168.0.0" the_status = IPSyntaxChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is IPv4 range. print(f"{my_subject} is IPv4 range ? {the_status.is_valid_v4_range()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.is_ipv4_range may be removed in the future." "Please consider using PyFunceble.IPSyntaxChecker explicitly.", DeprecationWarning, ) return IPSyntaxChecker(subject, **kwargs).is_valid_v4_range() def is_ipv6_range(subject: str, **kwargs) -> bool: """ Checks if the given subject is a syntactically valid IPv6 range. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import IPSyntaxChecker my_subject = "::1" the_status = IPSyntaxChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is IPv6 range. print(f"{my_subject} is IPv6 range ? {the_status.is_valid_v6_range()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.is_ipv6_range may be removed in the future." "Please consider using PyFunceble.IPSyntaxChecker explicitly.", DeprecationWarning, ) return IPSyntaxChecker(subject, **kwargs).is_valid_v6_range() def is_url(subject: str, **kwargs) -> bool: """ Checks if the given subject is syntactically a valid URL. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import DomainReputationChecker my_subject = "https://example.org" the_status = URLSyntaxChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is a URL. print(f"{my_subject} is URL ? {the_status.is_valid()}") :parma subject: The subject to check. """ warnings.warn( "PyFunceble.is_url may be removed in the future." "Please consider using PyFunceble.URLSyntaxChecker explicitly.", DeprecationWarning, ) # pylint: disable=no-member return URLSyntaxChecker(subject, **kwargs).get_status().is_valid() def is_domain_malicious(subject: str, **kwargs) -> bool: """ Checks if the given domain is malicious. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import DomainReputationChecker my_subject = "example.org" the_status = DomainReputationChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is malicious. print(f"{my_subject} is Malicious ? {the_status.is_malicious()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.is_domain_malicious may be removed in the future." "Please consider using PyFunceble.DomainReputationChecker explicitly.", DeprecationWarning, ) # pylint: disable=no-member return DomainReputationChecker(subject, **kwargs).get_status().is_malicious() def is_ipv4_malicious(subject: str, **kwargs) -> bool: """ Checks if the given IPv4 is malicious. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import IPReputationChecker my_subject = "192.168.0.1" the_status = IPReputationChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is malicious. print(f"{my_subject} is Malicious ? {the_status.is_malicious()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.is_ipv4_malicious may be removed in the future." "Please consider using PyFunceble.IPReputationChecker explicitly.", DeprecationWarning, ) # pylint: disable=no-member return IPReputationChecker(subject, **kwargs).get_status().is_malicious() def is_url_malicious(subject: str, **kwargs) -> bool: """ Checks if the given URL is malicious. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import URLReputationChecker my_subject = "https://example.org" the_status = URLReputationChecker( my_subject ).get_status() # Get the status in dict format. print(the_status.to_dict()) # Get the status in json format. print(the_status.to_json()) # Check if it is malicious. print(f"{my_subject} is Malicious ? {the_status.is_malicious()}") :param subject: The subject to work with. """ warnings.warn( "PyFunceble.is_url_malicious may be removed in the future." "Please consider using PyFunceble.URLReputationChecker explicitly.", DeprecationWarning, ) # pylint: disable=no-member return URLReputationChecker(subject, **kwargs).get_status().is_malicious() def get_complements(subject: str, include_given: bool = False) -> List[str]: """ Provides the complements of a given subject. A complement is a for example :code:`example.org` if :code:`www.example.org` is given and vice-versa. .. warning:: This method may be removed in the future. It is still available for convenience. Please consider the following alternative example: :: from PyFunceble import Subject2Complements my_subject = "example.org" complements = Subject2Complements( my_subject ).get_converted(include_given=True) :param subject: The subject to work with. :param include_given: Include the given subject in the result. """ warnings.warn( "PyFunceble.get_complements may be removed in the future." "Please consider using PyFunceble.Subject2Complements explicitly", DeprecationWarning, ) return Subject2Complements(subject, include_given=include_given).get_converted() PyFunceble-4.2.29.dev/PyFunceble/checker/000077500000000000000000000000001467462152100200715ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/checker/__init__.py000066400000000000000000000045761467462152100222160ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the checkers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/checker/availability/000077500000000000000000000000001467462152100225435ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/checker/availability/__init__.py000066400000000000000000000046531467462152100246640ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the core of the availablity checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/checker/availability/base.py000066400000000000000000001145541467462152100240410ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all availability checker classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: disable=too-many-lines import multiprocessing from datetime import datetime from typing import Dict, List, Optional from sqlalchemy.orm import Session import PyFunceble.checker.utils.whois import PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.checker.availability.extras.base import ExtraRuleHandlerBase from PyFunceble.checker.availability.extras.dns import DNSRulesHandler from PyFunceble.checker.availability.extras.etoxic import EToxicHandler from PyFunceble.checker.availability.extras.rules import ExtraRulesHandler from PyFunceble.checker.availability.extras.subject_switch import ( SubjectSwitchRulesHandler, ) from PyFunceble.checker.availability.params import AvailabilityCheckerParams from PyFunceble.checker.availability.status import AvailabilityCheckerStatus from PyFunceble.checker.base import CheckerBase from PyFunceble.checker.syntax.domain import DomainSyntaxChecker from PyFunceble.checker.syntax.ip import IPSyntaxChecker from PyFunceble.checker.syntax.url import URLSyntaxChecker from PyFunceble.converter.url2netloc import Url2Netloc from PyFunceble.query.dns.query_tool import DNSQueryTool from PyFunceble.query.http_status_code import HTTPStatusCode from PyFunceble.query.netinfo.address import AddressInfo from PyFunceble.query.netinfo.hostbyaddr import HostByAddrInfo from PyFunceble.query.whois.query_tool import WhoisQueryTool class AvailabilityCheckerBase(CheckerBase): """ Provides the base of all our availability checker classes. :param str subject: Optional, The subject to work with. :param bool use_extra_rules: Optional, Activates/Disables the usage of our own set of extra rules. :param bool use_whois_lookup: Optional, Activates/Disables the usage of the WHOIS lookup to gather the status of the given :code:`subject`. :param bool use_dns_lookup: Optional, Activates/Disables the usage of the DNS lookup to gather the status of the given :code:`subject`. :param bool use_netinfo_lookup: Optional, Activates/Disables the usage of the network information lookup module to gather the status of the given :code:`subject`. :param bool use_http_code_lookup: Optional, Activates/Disables the usage of the HTTP status code lookup to gather the status of the given :code:`subject`. :param bool use_reputation_lookup: Optional, Activates/Disables the usage of the reputation dataset lookup to gather the status of the given :code:`subject`. :param bool do_syntax_check_first: Optional, Activates/Disables the check of the status before the actual status gathering. :param bool use_whois_db: Optional, Activates/Disable the usage of a local database to store the WHOIS datasets. """ # pylint: disable=too-many-public-methods, too-many-instance-attributes STD_USE_EXTRA_RULES: bool = True STD_USE_WHOIS_LOOKUP: bool = True STD_USE_DNS_LOOKUP: bool = True STD_USE_NETINFO_LOOKUP: bool = True STD_USE_HTTP_CODE_LOOKUP: bool = True STD_USE_REPUTATION_LOOKUP: bool = False STD_USE_WHOIS_DB: bool = True dns_query_tool: Optional[DNSQueryTool] = None whois_query_tool: Optional[WhoisQueryTool] = None addressinfo_query_tool: Optional[AddressInfo] = None hostbyaddr_query_tool: Optional[HostByAddrInfo] = None http_status_code_query_tool: Optional[HTTPStatusCode] = None domain_syntax_checker: Optional[DomainSyntaxChecker] = None ip_syntax_checker: Optional[IPSyntaxChecker] = None url_syntax_checker: Optional[URLSyntaxChecker] = None extra_rules_handlers: Optional[List[ExtraRuleHandlerBase]] = None url2netloc: Optional[Url2Netloc] = None _use_extra_rules: bool = False _use_whois_lookup: bool = False _use_dns_lookup: bool = False _use_netinfo_lookup: bool = False _use_http_code_lookup: bool = False _use_reputation_lookup: bool = False _use_whois_db: bool = False status: Optional[AvailabilityCheckerStatus] = None params: Optional[AvailabilityCheckerParams] = None def __init__( self, subject: Optional[str] = None, *, use_extra_rules: Optional[bool] = None, use_whois_lookup: Optional[bool] = None, use_dns_lookup: Optional[bool] = None, use_netinfo_lookup: Optional[bool] = None, use_http_code_lookup: Optional[bool] = None, use_reputation_lookup: Optional[bool] = None, do_syntax_check_first: Optional[bool] = None, db_session: Optional[Session] = None, use_whois_db: Optional[bool] = None, use_platform: Optional[bool] = None, ) -> None: self.dns_query_tool = DNSQueryTool() self.whois_query_tool = WhoisQueryTool() self.addressinfo_query_tool = AddressInfo() self.hostbyaddr_query_tool = HostByAddrInfo() self.http_status_code_query_tool = HTTPStatusCode() self.domain_syntax_checker = DomainSyntaxChecker() self.ip_syntax_checker = IPSyntaxChecker() self.url_syntax_checker = URLSyntaxChecker() # WARNING: Put the aggressive one first! self.extra_rules_handlers = [ SubjectSwitchRulesHandler(), DNSRulesHandler(), EToxicHandler(), ExtraRulesHandler(), ] self.db_session = db_session self.params = AvailabilityCheckerParams() self.status = AvailabilityCheckerStatus() self.status.params = self.params self.status.dns_lookup_record = self.dns_query_tool.lookup_record self.status.whois_lookup_record = self.whois_query_tool.lookup_record if use_extra_rules is not None: self.use_extra_rules = use_extra_rules else: self.guess_and_set_use_extra_rules() if use_whois_lookup is not None: self.use_whois_lookup = use_whois_lookup else: self.guess_and_set_use_whois_lookup() if use_dns_lookup is not None: self.use_dns_lookup = use_dns_lookup else: self.guess_and_set_dns_lookup() if use_netinfo_lookup is not None: self.use_netinfo_lookup = use_netinfo_lookup else: self.guess_and_set_use_netinfo_lookup() if use_http_code_lookup is not None: self.use_http_code_lookup = use_http_code_lookup else: self.guess_and_set_use_http_code_lookup() if use_reputation_lookup is not None: self.use_reputation_lookup = use_reputation_lookup else: self.guess_and_set_use_reputation_lookup() if use_whois_db is not None: self.use_whois_db = use_whois_db else: self.guess_and_set_use_whois_db() super().__init__( subject, do_syntax_check_first=do_syntax_check_first, db_session=db_session, use_platform=use_platform, ) @property def use_extra_rules(self) -> bool: """ Provides the current value of the :code:`_use_extra_rules` attribute. """ return self._use_extra_rules @use_extra_rules.setter def use_extra_rules(self, value: bool) -> None: """ Sets the value which authorizes the usage of the special rule. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._use_extra_rules = self.params.use_extra_rules = value def set_use_extra_rules(self, value: bool) -> "AvailabilityCheckerBase": """ Sets the value which authorizes the usage of the special rule. :param value: The value to set. """ self.use_extra_rules = value return self @property def use_whois_lookup(self) -> bool: """ Provides the current value of the :code:`_use_whois_lookup` attribute. """ return self._use_whois_lookup @use_whois_lookup.setter def use_whois_lookup(self, value: bool) -> None: """ Sets the value which authorizes the usage of the WHOIS lookup. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._use_whois_lookup = self.params.use_whois_lookup = value def set_use_whois_lookup(self, value: bool) -> "AvailabilityCheckerBase": """ Sets the value which authorizes the usage of the WHOIS lookup. :param value: The value to set. """ self.use_whois_lookup = value return self @property def use_dns_lookup(self) -> bool: """ Provides the current value of the :code:`_use_dns_lookup` attribute. """ return self._use_dns_lookup @use_dns_lookup.setter def use_dns_lookup(self, value: bool) -> None: """ Sets the value which authorizes the usage of the DNS Lookup. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._use_dns_lookup = self.params.use_dns_lookup = value def set_use_dns_lookup(self, value: bool) -> "AvailabilityCheckerBase": """ Sets the value which authorizes the usage of the DNS Lookup. :param value: The value to set. """ self.use_dns_lookup = value return self @property def use_netinfo_lookup(self) -> bool: """ Provides the current value of the :code:`_use_netinfo_lookup` attribute. """ return self._use_netinfo_lookup @use_netinfo_lookup.setter def use_netinfo_lookup(self, value: bool) -> None: """ Sets the value which authorizes the usage of the network information lookup. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._use_netinfo_lookup = self.params.use_netinfo_lookup = value def set_use_netinfo_lookup(self, value: bool) -> "AvailabilityCheckerBase": """ Sets the value which authorizes the usage of the network information lookup. :param value: The value to set. """ self.use_netinfo_lookup = value return self @property def use_http_code_lookup(self) -> None: """ Provides the current value of the :code:`_use_http_code_lookup` attribute. """ return self._use_http_code_lookup @use_http_code_lookup.setter def use_http_code_lookup(self, value: bool) -> None: """ Sets the value which authorizes the usage of the HTTP status code lookup. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._use_http_code_lookup = self.params.use_http_code_lookup = value def set_use_http_code_lookup(self, value: bool) -> "AvailabilityCheckerBase": """ Sets the value which authorizes the usage of the HTTP status code lookup. :param value: The value to set. """ self.use_http_code_lookup = value return self @property def use_reputation_lookup(self) -> bool: """ Provides the current value of the :code:`_use_reputation_lookup` attribute. """ return self._use_reputation_lookup @use_reputation_lookup.setter def use_reputation_lookup(self, value: bool) -> None: """ Sets the value which authorizes the usage of the reputation lookup. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._use_reputation_lookup = self.params.use_reputation_lookup = value def set_use_reputation_lookup(self, value: bool) -> "AvailabilityCheckerBase": """ Sets the value which authorizes the usage of the reputation lookup. :param value: The value to set. """ self.use_reputation_lookup = value return self @property def use_whois_db(self) -> bool: """ Provides the current value of the :code:`_use_whois_db` attribute. """ return self._use_whois_db @use_whois_db.setter def use_whois_db(self, value: bool) -> None: """ Sets the value which authorizes the usage of the WHOIS DB. :param value: The value to set. :param TypeError: When the given :code:`use_whois_db` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._use_whois_db = self.params.use_whois_db = value def set_use_whois_db(self, value: bool) -> "AvailabilityCheckerBase": """ Sets the value which authorizes the usage of the WHOIS DB. :param value: The value to set. """ self.use_whois_db = value return self def subject_propagator(self) -> "CheckerBase": """ Propagate the currently set subject. .. warning:: You are not invited to run this method directly. """ self.dns_query_tool.set_subject(self.idna_subject) self.whois_query_tool.set_subject(self.idna_subject) self.addressinfo_query_tool.set_subject(self.idna_subject) self.hostbyaddr_query_tool.set_subject(self.idna_subject) self.http_status_code_query_tool.set_subject(self.idna_subject) self.domain_syntax_checker.subject = self.idna_subject self.ip_syntax_checker.subject = self.idna_subject self.url_syntax_checker.subject = self.idna_subject self.status = AvailabilityCheckerStatus() self.status.params = self.params self.status.dns_lookup_record = self.dns_query_tool.lookup_record self.status.whois_lookup_record = self.whois_query_tool.lookup_record return super().subject_propagator() def should_we_continue_test(self, status_post_syntax_checker: str) -> bool: """ Checks if we are allowed to continue a standard testing. Rules: 1. No status available yet. Continue to next test method. 2. Status is/still INVALID. Continue to next test method. 3. Above are False. Not allowed to continue to next test method. """ if not self.status.status: return True if ( status_post_syntax_checker == PyFunceble.storage.STATUS.invalid and self.status.status == PyFunceble.storage.STATUS.invalid ): return True return False def guess_and_set_use_extra_rules(self) -> "AvailabilityCheckerBase": """ Try to guess and set the value of the :code:`use_extra_rules` attribute from the configuration file. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.use_extra_rules = PyFunceble.storage.CONFIGURATION.lookup.special else: self.use_extra_rules = self.STD_USE_EXTRA_RULES return self def guess_and_set_use_whois_lookup(self) -> "AvailabilityCheckerBase": """ Try to guess and set the value of the :code:`use_whois` attribute from the configuration file. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.use_whois_lookup = PyFunceble.storage.CONFIGURATION.lookup.whois else: self.use_whois_lookup = self.STD_USE_WHOIS_LOOKUP return self def guess_and_set_dns_lookup(self) -> "AvailabilityCheckerBase": """ Try to guess and set the value of the :code:`use_dns_lookup` attribute from the configuration file. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.use_dns_lookup = PyFunceble.storage.CONFIGURATION.lookup.dns else: self.use_dns_lookup = self.STD_USE_DNS_LOOKUP return self def guess_and_set_use_netinfo_lookup(self) -> "AvailabilityCheckerBase": """ Try to guess and set the value of the :code:`use_netinfo_lookup` attribute from the configuration file. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.use_netinfo_lookup = PyFunceble.storage.CONFIGURATION.lookup.netinfo else: self.use_netinfo_lookup = self.STD_USE_NETINFO_LOOKUP return self def guess_and_set_use_http_code_lookup(self) -> "AvailabilityCheckerBase": """ Try to guess and set the value of the :code:`use_http_code_lookup` attribute from the configuration file. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.use_http_code_lookup = ( PyFunceble.storage.CONFIGURATION.lookup.http_status_code ) else: self.use_http_code_lookup = self.STD_USE_HTTP_CODE_LOOKUP return self def guess_and_set_use_reputation_lookup(self) -> "AvailabilityCheckerBase": """ Try to guess and set the value of the :code:`use_reputation_lookup` attribute from the configuration file. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.use_reputation_lookup = ( PyFunceble.storage.CONFIGURATION.lookup.reputation ) else: self.use_reputation_lookup = self.STD_USE_REPUTATION_LOOKUP return self def guess_and_set_use_whois_db(self) -> "AvailabilityCheckerBase": """ Try to guess and set the value of the :code:`use_whois_db` attribute. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.use_whois_db = PyFunceble.storage.CONFIGURATION.cli_testing.whois_db else: self.use_whois_db = self.STD_USE_WHOIS_DB def guess_all_settings( self, ) -> "AvailabilityCheckerBase": # pragma: no cover ## Method are more important """ Try to guess all settings. """ to_ignore = ["guess_all_settings"] for method in dir(self): if method in to_ignore or not method.startswith("guess_"): continue getattr(self, method)() return self def query_common_checker(self) -> "AvailabilityCheckerBase": """ Queries the syntax checker. """ PyFunceble.facility.Logger.info( "Started to check the syntax of %r", self.status.idna_subject ) self.status.second_level_domain_syntax = ( self.domain_syntax_checker.is_valid_second_level() ) self.status.subdomain_syntax = self.domain_syntax_checker.is_valid_subdomain() self.status.domain_syntax = bool(self.status.subdomain_syntax) or bool( self.status.second_level_domain_syntax ) self.status.ipv4_syntax = self.ip_syntax_checker.is_valid_v4() self.status.ipv6_syntax = self.ip_syntax_checker.is_valid_v6() self.status.ipv4_range_syntax = self.ip_syntax_checker.is_valid_v4_range() self.status.ipv6_range_syntax = self.ip_syntax_checker.is_valid_v6_range() self.status.ip_syntax = bool(self.status.ipv4_syntax or self.status.ipv6_syntax) self.status.url_syntax = self.url_syntax_checker.is_valid() PyFunceble.facility.Logger.info( "Finished to check the syntax of %r", self.status.idna_subject ) return super().query_common_checker() @CheckerBase.ensure_subject_is_given def query_dns_record(self) -> Optional[Dict[str, Optional[List[str]]]]: """ Tries to query the DNS record(s) of the given subject. .. versionchanged:: 4.1.0b8.dev Lookup order relative to actual subject. """ PyFunceble.facility.Logger.info( "Started to try to query the DNS record of %r.", self.status.idna_subject, ) result = {} if self.status.idna_subject != self.dns_query_tool.subject: self.domain_syntax_checker.set_subject(self.dns_query_tool.subject) self.ip_syntax_checker.set_subject(self.dns_query_tool.subject) if self.domain_syntax_checker.is_valid_subdomain(): lookup_order = ["NS", "A", "AAAA", "CNAME", "DNAME"] elif self.ip_syntax_checker.is_valid(): lookup_order = ["PTR"] else: lookup_order = ["NS", "CNAME", "A", "AAAA", "DNAME"] if lookup_order: for record_type in lookup_order: local_result = self.dns_query_tool.set_query_record_type( record_type ).query() if local_result: result[record_type] = local_result break if self.status.idna_subject != self.dns_query_tool.subject: # Switch back subject because we don't want to break subsequential calls. self.domain_syntax_checker.set_subject(self.status.idna_subject) self.ip_syntax_checker.set_subject(self.status.idna_subject) PyFunceble.facility.Logger.debug("DNS Record:\n%r", result) PyFunceble.facility.Logger.info( "Finished to try to query the DNS record of %r", self.status.idna_subject, ) return result def try_to_query_status_from_whois( self, ) -> "AvailabilityCheckerBase": """ Tries to get and the status from the WHOIS record. .. warning:: If the configuration is loaded, this method try to query from the best database first. If it's not found it will try to query it from the best WHOIS server then add it into the database (if the expiration date extraction is successful). .. note:: The addition into the WHOIS database is only done if this method is running in a process with a name that does not starts with :code:`PyFunceble` (case sensitive). """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: WHOIS Lookup", self.status.idna_subject, ) if ( PyFunceble.facility.ConfigLoader.is_already_loaded() and self.use_whois_db ): # pragma: no cover ## Not interesting enough to spend time on it. whois_object = PyFunceble.checker.utils.whois.get_whois_dataset_object( db_session=self.db_session ) known_record = whois_object[self.subject] if known_record and not isinstance(known_record, dict): # Comes from DB engine. known_record = known_record.to_dict() if not known_record: # We assume that expired dataset are never saved into the # dataset. self.status.expiration_date = self.whois_query_tool.expiration_date self.status.registrar = self.whois_query_tool.lookup_record.registrar self.status.whois_record = self.whois_query_tool.lookup_record.record if ( self.status.expiration_date and not multiprocessing.current_process().name.startswith( PyFunceble.storage.PROJECT_NAME.lower() ) ): whois_object.update( { "subject": self.subject, "idna_subject": self.idna_subject, "expiration_date": self.status.expiration_date, "epoch": str( datetime.strptime( self.status.expiration_date, "%d-%b-%Y" ).timestamp() ), } ) else: # We pass the known record to the lookup record - so that other # methods can use it. self.whois_query_tool.lookup_record.record = known_record.get( "record", None ) self.whois_query_tool.lookup_record.expiration_date = known_record.get( "expiration_date", None ) self.whois_query_tool.lookup_record.registrar = known_record.get( "registrar", None ) self.status.whois_lookup_record = self.whois_query_tool.lookup_record self.status.expiration_date = known_record.get("expiration_date", None) self.status.registrar = known_record.get("registrar", None) self.status.whois_record = None else: self.status.expiration_date = self.whois_query_tool.expiration_date self.status.registrar = self.whois_query_tool.lookup_record.registrar self.status.whois_record = self.whois_query_tool.lookup_record.record if self.status.expiration_date: self.status.status = PyFunceble.storage.STATUS.up self.status.status_source = "WHOIS" PyFunceble.facility.Logger.info( "Could define the status of %r from: WHOIS Lookup", self.status.idna_subject, ) PyFunceble.facility.Logger.info( "Finished to try to query the status of %r from: WHOIS Lookup", self.status.idna_subject, ) return self def try_to_query_status_from_dns(self) -> "AvailabilityCheckerBase": """ Tries to query the status from the DNS lookup. .. versionchanged:: 4.1.0b7.dev Logging return the correct subject. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: DNS Lookup", self.dns_query_tool.subject, ) lookup_result = self.query_dns_record() if lookup_result: self.status.dns_lookup = lookup_result self.status.status = PyFunceble.storage.STATUS.up self.status.status_source = "DNSLOOKUP" PyFunceble.facility.Logger.info( "Could define the status of %r from: DNS Lookup", self.dns_query_tool.subject, ) PyFunceble.facility.Logger.info( "Finished to try to query the status of %r from: DNS Lookup", self.dns_query_tool.subject, ) return self def try_to_query_status_from_netinfo(self) -> "AvailabilityCheckerBase": """ Tries to query the status from the network information. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: NETINFO Lookup", self.status.idna_subject, ) if self.status.domain_syntax: lookup_result = self.addressinfo_query_tool.get_info() elif self.status.ip_syntax: lookup_result = self.hostbyaddr_query_tool.get_info() elif self.status.idna_subject.isdigit(): lookup_result = None else: lookup_result = self.addressinfo_query_tool.get_info() if lookup_result: self.status.netinfo = lookup_result self.status.status = PyFunceble.storage.STATUS.up self.status.status_source = "NETINFO" PyFunceble.facility.Logger.info( "Could define the status of %r from: NETINFO Lookup", self.status.idna_subject, ) PyFunceble.facility.Logger.info( "Finished to try to query the status of %r from: NETINFO Lookup", self.status.idna_subject, ) return self def try_to_query_status_from_http_status_code( self, *, from_domain_test: bool = False ) -> "AvailabilityCheckerBase": """ Tries to query the status from the HTTP status code. :param bool from_domain_test: Whether we wanted to test a test - actually. Setting this argument to :py:class:`True` will exit the http_status_code test if the given subject is already a URL. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: HTTP Status code Lookup", self.status.idna_subject, ) if from_domain_test and self.status.url_syntax: return self if not self.status.url_syntax and not self.idna_subject.startswith("http"): self.http_status_code_query_tool.set_subject( f"http://{self.idna_subject}:80" ) lookup_result = self.http_status_code_query_tool.get_status_code() if ( lookup_result and lookup_result != self.http_status_code_query_tool.STD_UNKNOWN_STATUS_CODE ): self.status.http_status_code = lookup_result if ( PyFunceble.facility.ConfigLoader.is_already_loaded() ): # pragma: no cover ## Special behavior. dataset = PyFunceble.storage.HTTP_CODES else: dataset = PyFunceble.storage.STD_HTTP_CODES if ( not self.status.status or self.status.status == PyFunceble.storage.STATUS.down ) and ( self.status.http_status_code in dataset.list.up or self.status.http_status_code in dataset.list.potentially_up ): self.status.status = PyFunceble.storage.STATUS.up self.status.status_source = "HTTP CODE" PyFunceble.facility.Logger.info( "Could define the status of %r from: HTTP Status code Lookup", self.status.idna_subject, ) else: self.status.http_status_code = None PyFunceble.facility.Logger.info( "Finished to try to query the status of %r from: HTTP Status code Lookup", self.status.idna_subject, ) return self def try_to_query_status_from_syntax_lookup( self, from_domain_test: bool = False, from_url_test: bool = False ) -> "AvailabilityCheckerBase": """ Tries to query the status from the syntax. :param bool from_domain_test: Whether we wanted to test a domain - actually. Setting this argument to :py:class:`True` will assume that we are exclusively checking the syntax of domain/ip. :param bool from_url_test: Whether we wanted to test a url - actually. Setting this argument to :py:class:`True` will assume that we are exclusively checking the syntax of url. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: Syntax Lookup", self.status.idna_subject, ) if from_domain_test: is_invalid = not self.status.domain_syntax and not self.status.ip_syntax elif from_url_test: is_invalid = not self.status.url_syntax else: is_invalid = ( not self.status.domain_syntax and not self.status.ip_syntax and not self.status.url_syntax ) if is_invalid: self.status.status = PyFunceble.storage.STATUS.invalid self.status.status_source = "SYNTAX" PyFunceble.facility.Logger.info( "Could define the status of %r from: Syntax Lookup", self.status.idna_subject, ) PyFunceble.facility.Logger.info( "Finished to try to query the status of %r from: Syntax Lookup", self.status.idna_subject, ) return self def try_to_query_status_from_reputation(self) -> "AvailabilityCheckerBase": """ Tries to query the status from the reputation lookup. """ raise NotImplementedError() def try_to_query_status_from_platform(self) -> "AvailabilityCheckerBase": """ Tries to get and set the status from the platform API. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: Platform Lookup", self.status.idna_subject, ) data = self.platform_query_tool.pull(self.idna_subject) if data and "status" in data: if ( self.platform_query_tool.preferred_status_origin == "frequent" and data["status"]["availability"]["frequent"] ): self.status.status = data["status"]["availability"]["frequent"] self.status.status_source = "PLATFORM" elif ( self.platform_query_tool.preferred_status_origin == "latest" and data["status"]["availability"]["latest"] ): try: # legacy self.status.status = data["status"]["availability"]["latest"][ "status" ] except KeyError: self.status.status = data["status"]["availability"]["latest"] self.status.status_source = "PLATFORM" elif ( self.platform_query_tool.preferred_status_origin == "recommended" and data["status"]["availability"]["recommended"] ): self.status.status = data["status"]["availability"]["recommended"] self.status.status_source = "PLATFORM" PyFunceble.facility.Logger.info( "Could define the status of %r from: Platform Lookup", self.status.idna_subject, ) PyFunceble.facility.Logger.info( "Finished to try to query the status of %r from: Platform Lookup", self.status.idna_subject, ) return self def try_to_query_status_from_extra_rules(self) -> "AvailabilityCheckerBase": """ Tries to query the status from the extra rules. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: Extra Rules Lookup", self.status.idna_subject, ) if self.use_extra_rules: for rule_handler in self.extra_rules_handlers: rule_handler.set_status(self.status).start() if self.status.status_after_extra_rules: PyFunceble.facility.Logger.info( "Could define the status of %r from: Extra Rules Lookup", self.status.idna_subject, ) break PyFunceble.facility.Logger.info( "Finished to try to query the status of %r from: Extra Rules Lookup", self.status.idna_subject, ) return self @CheckerBase.ensure_subject_is_given @CheckerBase.update_status_date_after_query def query_status(self) -> "AvailabilityCheckerBase": """ Queries the status and for for more action. """ raise NotImplementedError() # pylint: disable=useless-super-delegation def get_status(self) -> Optional[AvailabilityCheckerStatus]: return super().get_status() PyFunceble-4.2.29.dev/PyFunceble/checker/availability/domain.py000066400000000000000000000164401467462152100243710ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the domains availability checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.checker.availability.base import AvailabilityCheckerBase from PyFunceble.checker.reputation.domain import DomainReputationChecker class DomainAvailabilityChecker(AvailabilityCheckerBase): """ Provides the interface for checking the availability of a given domain. :param str subject: Optional, The subject to work with. :param bool use_extra_rules: Optional, Activates/Disables the usage of our own set of extra rules. :param bool use_whois_lookup: Optional, Activates/Disables the usage of the WHOIS lookup to gather the status of the given :code:`subject`. :param bool use_dns_lookup: Optional, Activates/Disables the usage of the DNS lookup to gather the status of the given :code:`subject`. :param bool use_netinfo_lookup: Optional, Activates/Disables the usage of the network information lookup module to gather the status of the given :code:`subject`. :param bool use_http_code_lookup: Optional, Activates/Disables the usage of the HTTP status code lookup to gather the status of the given :code:`subject`. :param bool use_reputation_lookup: Optional, Activates/Disables the usage of the reputation dataset lookup to gather the status of the given :code:`subject`. :param bool do_syntax_check_first: Optional, Activates/Disables the check of the status before the actual status gathering. :param bool use_whois_db: Optional, Activates/Disable the usage of a local database to store the WHOIS datasets. """ def try_to_query_status_from_reputation(self) -> "DomainAvailabilityChecker": """ Tries to query the status from the reputation lookup. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: Reputation Lookup", self.status.idna_subject, ) lookup_result = DomainReputationChecker(self.status.idna_subject).get_status() # pylint: disable=no-member if lookup_result and lookup_result.is_malicious(): self.status.status = PyFunceble.storage.STATUS.up self.status.status_source = "REPUTATION" PyFunceble.facility.Logger.info( "Could define the status of %r from: Reputation Lookup", self.status.idna_subject, ) PyFunceble.facility.Logger.info( "Finished to try to query the status of %r from: Reputation Lookup", self.status.idna_subject, ) return self @AvailabilityCheckerBase.ensure_subject_is_given @AvailabilityCheckerBase.update_status_date_after_query def query_status( self, ) -> "DomainAvailabilityChecker": # pragma: no cover """ Queries the result without anything more. """ ## Test Methods are more important. status_post_syntax_checker = None if not self.status.status and self.use_platform: self.try_to_query_status_from_platform() if not self.status.status and self.do_syntax_check_first: self.try_to_query_status_from_syntax_lookup(from_domain_test=True) if self.status.status: status_post_syntax_checker = self.status.status if ( self.use_whois_lookup and self.status.second_level_domain_syntax and self.should_we_continue_test(status_post_syntax_checker) ): self.try_to_query_status_from_whois() if self.use_dns_lookup and self.should_we_continue_test( status_post_syntax_checker ): self.try_to_query_status_from_dns() if self.use_netinfo_lookup and self.should_we_continue_test( status_post_syntax_checker ): self.try_to_query_status_from_netinfo() if self.use_reputation_lookup and self.should_we_continue_test( status_post_syntax_checker ): self.try_to_query_status_from_reputation() if self.use_extra_rules or ( self.use_http_code_lookup and self.should_we_continue_test(status_post_syntax_checker) ): self.try_to_query_status_from_http_status_code(from_domain_test=True) if not self.status.status: self.status.status = PyFunceble.storage.STATUS.down self.status.status_source = "STDLOOKUP" PyFunceble.facility.Logger.info( "Could not define status the status of %r. Setting to %r", self.status.idna_subject, self.status.status, ) if self.use_extra_rules: self.try_to_query_status_from_extra_rules() return self @staticmethod def is_valid() -> bool: # pylint: disable=arguments-differ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/checker/availability/domain_and_ip.py000066400000000000000000000146611467462152100257060ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the domains and IP availability checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Union from PyFunceble.checker.availability.base import AvailabilityCheckerBase from PyFunceble.checker.availability.domain import DomainAvailabilityChecker from PyFunceble.checker.availability.ip import IPAvailabilityChecker class DomainAndIPAvailabilityChecker(AvailabilityCheckerBase): """ Provides the interface for checking the availability of a IP or domain. :param str subject: Optional, The subject to work with. :param bool use_extra_rules: Optional, Activates/Disables the usage of our own set of extra rules. :param bool use_whois_lookup: Optional, Activates/Disables the usage of the WHOIS lookup to gather the status of the given :code:`subject`. :param bool use_dns_lookup: Optional, Activates/Disables the usage of the DNS lookup to gather the status of the given :code:`subject`. :param bool use_netinfo_lookup: Optional, Activates/Disables the usage of the network information lookup module to gather the status of the given :code:`subject`. :param bool use_http_code_lookup: Optional, Activates/Disables the usage of the HTTP status code lookup to gather the status of the given :code:`subject`. :param bool use_reputation_lookup: Optional, Activates/Disables the usage of the reputation dataset lookup to gather the status of the given :code:`subject`. :param bool do_syntax_check_first: Optional, Activates/Disables the check of the status before the actual status gathering. :param bool use_whois_db: Optional, Activates/Disable the usage of a local database to store the WHOIS datasets. """ @AvailabilityCheckerBase.ensure_subject_is_given @AvailabilityCheckerBase.update_status_date_after_query def query_status( self, ) -> "DomainAndIPAvailabilityChecker": # pragma: no cover ## Just a switch. """ Queries the result without anything more. """ query_object: Union[IPAvailabilityChecker, DomainAvailabilityChecker] = None if self.status.ip_syntax: query_object = IPAvailabilityChecker( self.subject, use_extra_rules=self.use_extra_rules, use_whois_lookup=self.use_whois_lookup, use_dns_lookup=self.use_dns_lookup, use_netinfo_lookup=self.use_netinfo_lookup, use_http_code_lookup=self.use_http_code_lookup, use_reputation_lookup=self.use_reputation_lookup, do_syntax_check_first=self.do_syntax_check_first, db_session=self.db_session, use_whois_db=self.use_whois_db, use_platform=self.use_platform, ) else: query_object = DomainAvailabilityChecker( self.subject, use_extra_rules=self.use_extra_rules, use_whois_lookup=self.use_whois_lookup, use_dns_lookup=self.use_dns_lookup, use_netinfo_lookup=self.use_netinfo_lookup, use_http_code_lookup=self.use_http_code_lookup, use_reputation_lookup=self.use_reputation_lookup, do_syntax_check_first=self.do_syntax_check_first, db_session=self.db_session, use_whois_db=self.use_whois_db, use_platform=self.use_platform, ) query_object.dns_query_tool = self.dns_query_tool query_object.whois_query_tool = self.whois_query_tool query_object.platform_query_tool = self.platform_query_tool query_object.hostbyaddr_query_tool = self.hostbyaddr_query_tool query_object.addressinfo_query_tool = self.addressinfo_query_tool query_object.http_status_code_query_tool = self.http_status_code_query_tool result = query_object.query_status() self.__dict__.update(query_object.__dict__) return result @staticmethod def is_valid() -> bool: # pylint: disable=arguments-differ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/checker/availability/extras/000077500000000000000000000000001467462152100240515ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/checker/availability/extras/__init__.py000066400000000000000000000046551467462152100261740ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the extras of the availablity checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/checker/availability/extras/base.py000066400000000000000000000363211467462152100253420ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all extra handlers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools import socket from typing import Callable, Dict, List, Optional, Union import requests import PyFunceble.factory from PyFunceble.checker.availability.status import AvailabilityCheckerStatus from PyFunceble.helpers.regex import RegexHelper from PyFunceble.query.dns.query_tool import DNSQueryTool class ExtraRuleHandlerBase: """ Provides the base of all extra rules handler. :param statatus: The previously gathered status. :type status: :class:`~PyFunceble.checker.availability.status.AvailabilityCheckerStatus` """ _status: Optional[AvailabilityCheckerStatus] = None req: Optional[requests.Response] = None dns_query_tool: Optional[DNSQueryTool] = None regex_helper: Optional[RegexHelper] = None def __init__(self, status: Optional[AvailabilityCheckerStatus] = None) -> None: if status is not None: self.status = status # Be sure that all settings are loaded proprely!! PyFunceble.factory.Requester.guess_all_settings() self.dns_query_tool = DNSQueryTool() self.regex_helper = RegexHelper() def ensure_status_is_given( func: Callable[..., "ExtraRuleHandlerBase"] ): # pylint: disable=no-self-argument """ Ensures that the status is given before running the decorated method. :raise TypeError: If the subject is not a string. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): # pragma: no cover ## Safety! if not self.status: raise TypeError( f" should be {AvailabilityCheckerStatus}, " f"{type(self.status)} given." ) return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def setup_status_before( func: Callable[..., "ExtraRuleHandlerBase"] ): # pylint: disable=no-self-argument """ Ensures that the status is given before running the decorated method. :raise TypeError: If the subject is not a string. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): # pragma: no cover ## Safety! self.status.status_before_extra_rules = self.status.status self.status.status_source_before_extra_rules = self.status.status_source return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def setup_status_after( func: Callable[..., "ExtraRuleHandlerBase"] ): # pylint: disable=no-self-argument """ Ensures that the status is given before running the decorated method. :raise TypeError: If the subject is not a string. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): # pragma: no cover ## Safety! result = func(self, *args, **kwargs) # pylint: disable=not-callable if self.status.status_after_extra_rules: self.status.status = self.status.status_after_extra_rules self.status.status_source = self.status.status_source_after_extra_rules PyFunceble.facility.Logger.info( "Could define the status of %r from our own set of rules.", self.status.idna_subject, ) else: self.status.status_before_extra_rules = None self.status.status_source_before_extra_rules = None self.status.status_after_extra_rules = None self.status.status_source_after_extra_rules = None return result return wrapper @property def req_url(self) -> Optional[str]: """ Provides a viable request URL. """ if any(self.status.idna_subject.startswith(x) for x in ("http:", "https:")): return self.status.idna_subject return f"http://{self.status.idna_subject}:80" @property def req_url_https(self) -> Optional[str]: """ Provides a viable request URL that default to an HTTPS URL. """ if any(self.status.idna_subject.startswith(x) for x in ("http:", "https:")): return self.status.idna_subject return f"https://{self.status.idna_subject}:443" @property def status(self) -> Optional[AvailabilityCheckerStatus]: """ Provides the current state of the :code:`_status` attribute. """ return self._status @status.setter def status(self, value: AvailabilityCheckerStatus) -> None: """ Sets the status to work with. :param value: The status to work with. :raise TypeError: When the given :code:`value` is not a :class:`~PyFunceble.checker.availability.status.AvailabilityCheckerStatus`. """ if not isinstance(value, AvailabilityCheckerStatus): raise TypeError( f" should be {AvailabilityCheckerStatus}, {type(value)} given." ) self._status = value def set_status(self, value: AvailabilityCheckerStatus) -> "ExtraRuleHandlerBase": """ Sets the status to work with. :param value: The status to work with. """ self.status = value return self def do_request(self, *, allow_redirects: bool = True) -> requests.Response: """ Do a request and store its response into the `req` attribute. :param bool allow_redirects: Whether we shoold follow the redirection - or not. """ self.req = PyFunceble.factory.Requester.get( self.req_url, allow_redirects=allow_redirects ) return self def do_on_body_match( self, url: str, matches: List[str], *, method: Callable[..., "ExtraRuleHandlerBase"], match_mode: str = "regex", strict: bool = False, allow_redirects: bool = False, ) -> "ExtraRuleHandlerBase": """ Make a request to the given :code:`url` and run the given :code:`method`, if one of the given :code:`matches` matches. :param url: The URL to query. :param matches: A list of strings to match. :param match_mode: A matching mode. Use :code:`regex` for a regex match, and anything else for a string match. :param strict: Whether we should match any (:code:`False`) or all (:code:`True`). """ matcher = any if not strict else all def handle_regex_match_mode(_req: requests.Response): if matcher( self.regex_helper.set_regex(x).match(_req.text, return_match=False) for x in matches ): method() def handle_string_match_mode(_req: requests.Response): if matcher(x in _req.text for x in matches): method() try: req = PyFunceble.factory.Requester.get(url, allow_redirects=allow_redirects) if match_mode == "regex": handle_regex_match_mode(req) else: handle_string_match_mode(req) except ( PyFunceble.factory.Requester.exceptions.RequestException, PyFunceble.factory.Requester.exceptions.InvalidURL, PyFunceble.factory.Requester.exceptions.Timeout, PyFunceble.factory.Requester.exceptions.ConnectionError, PyFunceble.factory.Requester.urllib3_exceptions.InvalidHeader, socket.timeout, ): pass return self def do_on_header_match( self, url: str, matches: Dict[str, List[str]], *, method: Callable[..., "ExtraRuleHandlerBase"], match_mode: str = "regex", strict: bool = False, allow_redirects: bool = True, ) -> "ExtraRuleHandlerBase": """ Make a request to the given :code:`url` and run the given :code:`method`, if one of the chosen header matches any of the given matches. :param url: The URL to query. :param matches: A dict representing the match. .. example:: { "Location": ["foo", "bar"] // try to match foo or bar } :param match_mode: A matching mode. Use :code:`regex` for a regex match, and anything else for a string match. :param strict: Whether we should match any (:code:`False`) or all (:code:`True`). :param allow_redirects: Whether we should allow redirect. """ matcher = any if not strict else all def handle_regex_match_mode(_req: requests.Response): matches2search_result = {} for header, loc_matches in matches: matches2search_result[header] = False if header not in _req.headers: continue if matcher( self.regex_helper.set_regex(x).match( _req.headers[header], return_match=False ) for x in loc_matches ): matches2search_result[header] = True continue if matcher(x for x in matches2search_result.values()): method() def handle_string_match_mode(_req: requests.Response): matches2search_result = {} for header, loc_matches in matches.items(): matches2search_result[header] = False if header not in _req.headers: continue if matcher(x in _req.headers[header] for x in loc_matches): matches2search_result[header] = True continue if matcher(x for x in matches2search_result.values()): method() try: req = PyFunceble.factory.Requester.get(url, allow_redirects=allow_redirects) if match_mode == "regex": handle_regex_match_mode(req) else: handle_string_match_mode(req) except ( PyFunceble.factory.Requester.exceptions.RequestException, PyFunceble.factory.Requester.exceptions.InvalidURL, PyFunceble.factory.Requester.exceptions.Timeout, PyFunceble.factory.Requester.exceptions.ConnectionError, PyFunceble.factory.Requester.urllib3_exceptions.InvalidHeader, socket.timeout, ): pass return self def do_dns_lookup(self, *, subject: str, query_type: str) -> List[str]: """ Do a DNS lookup and return its response. :param subject: The subject to query. :param query_type: The query type. """ return ( self.dns_query_tool.set_query_record_type(query_type) .set_subject(subject) .query() ) def start(self) -> "ExtraRuleHandlerBase": """ Starts the gathering process. """ raise NotImplementedError() def switch_to_down(self) -> "ExtraRuleHandlerBase": """ Switches the status to inactive. """ self.status.status_after_extra_rules = PyFunceble.storage.STATUS.down self.status.status_source_after_extra_rules = "SPECIAL" return self def switch_to_down_if_status_code( self, status_code: Union[int, List[int]] ) -> "ExtraRuleHandlerBase": """ Switches the status to inactive if the caught status code matches one of the given one. """ if not isinstance(status_code, (list, tuple, set)): status_code = [status_code] if any(self.status.http_status_code == x for x in status_code): self.switch_to_down() return self def switch_down_if_dns_match( self, query_type: str, matches: list ) -> "ExtraRuleHandlerBase": """ Switches the status to inactive if the DNS query of the type :code:`query_type` matches any of the given :code:`matches`. :param query_type: A DNS query type. :param matches: A list of string (not regex) to match. """ for record in ( self.dns_query_tool.set_query_record_type(query_type) .set_subject(self.status.netloc) .query() ): for match in matches: if match in record: self.switch_to_down() break return self def switch_to_up(self) -> "ExtraRuleHandlerBase": """ Switches the status to active. """ self.status.status_after_extra_rules = PyFunceble.storage.STATUS.up self.status.status_source_after_extra_rules = "SPECIAL" PyFunceble-4.2.29.dev/PyFunceble/checker/availability/extras/dns.py000066400000000000000000000152561467462152100252200ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the extra rules handler based on some DNS records. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional import PyFunceble.facility from PyFunceble.checker.availability.extras.base import ExtraRuleHandlerBase from PyFunceble.checker.availability.status import AvailabilityCheckerStatus class DNSRulesHandler(ExtraRuleHandlerBase): """ Provides our very own sets of DNS based rules. :param status: The previously gathered status. :type status: :class:`~PyFunceble.checker.availability.status.AvailabilityCheckerStatus` """ rulesets: dict = {} def __init__(self, status: Optional[AvailabilityCheckerStatus] = None) -> None: self.rulesets = { r"\.(25u\.com|2waky\.com|3-a\.net|4dq\.com|4pu\.com|acmetoy\.com|" r"almostmy\.com|americanunfinished\.com|as19557\.net|" r"authorizeddns\.net|authorizeddns\.org|authorizeddns\.us|" r"b0tnet\.com|bigmoney\.biz|changeip\.biz|changeip\.co|" r"changeip\.net|changeip\.org|changeip\.us|cleansite\.biz|" r"cleansite\.info|cleansite\.us|ddns\.info|ddns\.mobi|ddns\.ms|" r"ddns\.us|dhcp\.biz|dns-dns\.com|dns-report\.com|dns-stuff\.com|" r"dns04\.com|dns05\.com|dns1\.us|dns2\.us|dnset\.com|" r"dnsfailover\.net|dnsrd\.com|dsmtp\.biz|dsmtp\.com|dubya\.biz|" r"dubya\.info|dubya\.net|dubya\.us|dumb1\.com|dynamic-dns\.net|" r"dynamicdns\.biz|dynssl\.com|edns\.biz|esmtp\.biz|ezua\.com|" r"faqserv\.com|fartit\.com|freeddns\.com|freetcp\.com|freewww\.biz|" r"freewww\.info|ftp1\.biz|ftpserver\.biz|gettrials\.com|" r"got-game\.org|gr8domain\.biz|gr8name\.biz|homingbeacon\.net|" r"https443\.net|https443\.org|ikwb\.com|instanthq\.com|iownyour\.biz|" r"iownyour\.org|isasecret\.com|itemdb\.com|itsaol\.com|jetos\.com|" r"jkub\.com|jungleheart\.com|justdied\.com|lflink\.com|lflinkup\.com|" r"lflinkup\.net|lflinkup\.org|longmusic\.com|mefound\.com|" r"misecure\.com|moneyhome\.biz|mrbasic\.com|mrbonus\.com|mrface\.com|" r"mrslove\.com|my03\.com|mydad\.info|myddns\.com|myftp\.info|" r"mylftv\.com|mymom\.info|mynetav\.com|mynetav\.net|mynetav\.org|" r"mynumber\.org|mypicture\.info|mypop3\.net|mypop3\.org|" r"mysecondarydns\.com|mywww\.biz|myz\.info|ninth\.biz|ns01\.biz|" r"ns01\.info|ns01\.us|ns02\.biz|ns02\.info|ns02\.us|ns1\.name|" r"ns2\.name|ns3\.name|ocry\.com|onedumb\.com|onmypc\.biz|" r"onmypc\.info|onmypc\.net|onmypc\.org|onmypc\.us|" r"organiccrap\.com|otzo\.com|ourhobby\.com|port25\.biz|" r"proxydns\.com|qhigh\.com|qpoe\.com|rebatesrule\.net|" r"sendsmtp\.com|serveuser\.com|serveusers\.com|sexidude\.com|" r"sexxxy\.biz|sixth\.biz|squirly\.info|ssl443\.org|ssmailer\.com|" r"toh\.info|toshibanetcam\.com|toythieves\.com|trickip\.net|" r"trickip\.org|vizvaz\.com|wikaba\.com|www1\.biz|" r"wwwhost\.biz|wwwhost\.us|x24hr\.com|xxuz\.com|xxxy\.biz|" r"xxxy\.info|ygto\.com|youdontcare\.com|yourtrap\.com|" r"zyns\.com|zzux\.com)(\.|)$": [ (self.switch_down_if_dns_match, ("SOA", ["abuse.changeip.com."])) ] } super().__init__(status) @ExtraRuleHandlerBase.ensure_status_is_given @ExtraRuleHandlerBase.setup_status_before @ExtraRuleHandlerBase.setup_status_after def start(self) -> "DNSRulesHandler": """ Process the check and handling of the current subject. """ PyFunceble.facility.Logger.info( "Started to check %r against our subject switcher rules.", self.status.idna_subject, ) for regex, rulesets in self.rulesets.items(): if self.status.status_after_extra_rules: break if not self.regex_helper.set_regex(regex).match( self.status.netloc, return_match=False ): break for ruler, params in rulesets: if self.status.status_after_extra_rules: break ruler(*params) PyFunceble.facility.Logger.info( "Finished to check %r against our subject switcher rules.", self.status.idna_subject, ) PyFunceble-4.2.29.dev/PyFunceble/checker/availability/extras/etoxic.py000066400000000000000000000235421467462152100257240ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the extra rules handler for the etoxic infrastructure. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.factory import PyFunceble.storage from PyFunceble.checker.availability.extras.base import ExtraRuleHandlerBase class EToxicHandler(ExtraRuleHandlerBase): """ Provides our very own rulesets for the etoxic infrastructure. :param status: The previously gathered status. :type status: :class:`~PyFunceble.checker.availability.status.AvailabilityCheckerStatus` """ MATCHES = [ ".0wn0.com", ".123.st", ".1forum.biz", ".1fr1.net", ".1talk.net", ".30yearsstillyoung.com", ".3oloum.com", ".3rab.pro", ".4umer.com", ".5turbo.org", ".666forum.com", ".7olm.org", ".ace.st", ".actieforum.com", ".actifforum.com", ".aforumfree.com", ".africamotion.net", ".ahladalil.com", ".ahlamontada.com", ".ahlamontada.net", ".ahlamountada.com", ".airesdelibertad.com", ".alanoblebouffarde.com", ".aldeiarpg.com", ".all-up.com", ".ambiance-varadero.com", ".amoticos.org", ".arabepro.com", ".archeryonline.net", ".argyletd.com", ".artes-ana.com", ".audittpassion.com", ".avenir-vsp.com", ".bachandbachettefans.net", ".banouta.net", ".bbactif.com", ".beagle-attitude.com", ".benimforum.net", ".black-librarium.com", ".boxster-cayman.com", ".briefmarken-forum.com", ".bromptonforum.net", ".caferacerclub.org", ".camperfree.com", ".canadaboard.net", ".canadian-forum.com", ".cantal-leforum.com", ".casatridente.com", ".catsboard.com", ".cdnmilitarycollectors.com", ".chemin-de-memoire-parachutistes.org", ".clooneysopenhouse.com", ".club-bajaj.com", ".clubcb500x.com", ".clubgtipowers.com", ".clubtrackerarg.com", ".contrabaixobr.com", ".corvettepassion.com", ".coxengineforum.com", ".cro-wood.com", ".dan-moc.net", ".darkbb.com", ".deco-moderne-fr.com", ".desforums.net", ".detenteaujardin.com", ".discustoutsimplement.com", ".e30passion.com", ".easyforumpro.com", ".editboard.com", ".enbicielectrica.com", ".entreelles.org", ".exprimetoi.net", ".fcmulhousefans.com", ".filthy-secret.com", ".fmsp.net", ".focusrstteam.com", ".ford100e.org", ".foroactivo.com", ".foroactivo.com.es", ".forseps.org", ".forum-jardins.com", ".forum-zafira.com", ".forum2jeux.com", ".forumactif.com", ".forumactif.fr", ".forumactif.org", ".forumalgerie.net", ".forumattivo.it", ".forumbrasil.net", ".forumegypt.net", ".forumeiros.com", ".forumeiros.net", ".forumgamers.net", ".forumgaming.fr", ".forumgratuit.be", ".forumgratuit.ch", ".forumgratuit.org", ".forumgratuit.ro", ".forumgreek.com", ".forumgsr750.com", ".forumlaguna3.com", ".forumlumix.com", ".forumotion.com", ".forumotion.net", ".forumperso.com", ".forumpro.fr", ".forums-actifs.com", ".forumshiba.com", ".forumvi.com", ".fra.co", ".fritzbox-forum.com", ".fxsforexsrbijaforum.com", ".galoppourlavie.org", ".gid3an.com", ".giocattolivintage.com", ".glory-box-forum.com", ".goldwingpartage.com", ".goodforum.net", ".grisoghetto.com", ".gunetwork.org", ".hareketforum.net", ".hifi4sale.net", ".hooxs.com", ".i-love-harvard.com", ".iftopic.com", ".imperialgunneryforum.com", ".jeun.fr", ".jordanforum.net", ".just-married-rpg.com", ".kanak.fr", ".kawasaki-customs-forum.com", ".keuf.net", ".la-taverne-des-aventuriers.com", ".le-medaillon.org", ".le-site-de-la-citroen-xm.com", ".lebonforum.com", ".leforumlafigurine.com", ".legion-etrangere-munch.com", ".lemondedudiagauto.com", ".letrasyalgomas.com", ".levriers-forever.com", ".lights-camera-action.org", ".longluntan.com", ".magic-tarot58.com", ".mam9.com", ".manager-fifa.com", ".marvelscustoms.net", ".materielceleste.com", ".matostt.com", ".megane4forum.com", ".meilleurforum.com", ".minivanchrysler.com", ".mirbb.com", ".misteria7.com", ".montres-russes.org", ".moseisleyraumhafen.com", ".mundoqashqai.com", ".never-utopia.com", ".niceboard.com", ".novaerarpg.com", ".obd2sos.net", ".onepiece-mangas.com", ".open-consoles.com", ".orizzontescuolaforum.net", ".ottobreaddicts.net", ".own0.com", ".palstani.com", ".passion-harley.net", ".passionmilitaria.com", ".passionphoto-passionmontage.com", ".pblvfrance3.com", ".photos-camions.com", ".planete4x4.com", ".portalmercedes.com", ".portalmercedesbrasil.com", ".pro-forum.fr", ".puntoevoforum.com", ".quilterslastresort.com", ".repartocorse2.com", ".rigala.net", ".roo7.biz", ".rpg-board.net", ".rpghogwarts.org", ".sanata.biz", ".sdvg-deti.com", ".serbianforum.info", ".sgt3r.com", ".shaveua.com", ".sheffieldboardgamers.com", ".small-tracks.org", ".sorcieremonique.com", ".sporepedia2.com", ".stickeristas.com", ".subarashiis.com", ".superforo.net", ".superforum.fr", ".suzuki800.com", ".syriaforums.net", ".t5zone.com", ".team-z1000.com", ".terre-bitume.org", ".tibiaface.com", ".tubelesskite.net", ".ufologie-paranormal.org", ".unimog-mania.com", ".v2-honda.com", ".velovintageagogo.com", ".viterbikers.com", ".vivelecrpe.com", ".vstromhellasforum.com", ".walkingdead-rpg.com", ".warriorcatsnl.com", ".warriors-rpg.com", ".wwrail.net", ".yoo7.com", ".ze-43eme.com", ".zxr7team.com", ] @ExtraRuleHandlerBase.ensure_status_is_given @ExtraRuleHandlerBase.setup_status_before @ExtraRuleHandlerBase.setup_status_after def start(self) -> "EToxicHandler": PyFunceble.facility.Logger.info( "Started to check %r against the eToxic handler.", self.status.idna_subject, ) if self.status.status_before_extra_rules == PyFunceble.storage.STATUS.up: if any(self.status.netloc.endswith(x) for x in self.MATCHES): self.do_on_header_match( self.req_url, matches={"location": [f"/{self.status.netloc}", "/search/"]}, method=self.switch_to_down, allow_redirects=False, match_mode="std", strict=True, ) PyFunceble.facility.Logger.info( "Finished to check %r against our the eToxic handler.", self.status.idna_subject, ) return self PyFunceble-4.2.29.dev/PyFunceble/checker/availability/extras/parked.py000066400000000000000000000122621467462152100256740ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the extra rules handler based on the "parked status" of a subject. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.factory import PyFunceble.storage from PyFunceble.checker.availability.extras.base import ExtraRuleHandlerBase class ParkedRulesHandler(ExtraRuleHandlerBase): """ Provides our very own parked rules handler. This handler will try to check if a subject is parked. :param status: The previously gathered status. :type status: :class:`~PyFunceble.checker.availability.status.AvailabilityCheckerStatus` """ def _switch_down_by_cookie(self) -> "ParkedRulesHandler": """ Tries to switch the status to inactive if some special cookies where found. """ if "parking_session" in self.req.cookies: self.switch_to_down() return self def _swith_down_by_content(self) -> "ParkedRulesHandler": """ Tries to switch the status to inactive if some relative content were found. """ content = self.req.text.lower() if ( # pylint: disable=too-many-boolean-expressions 'class="parked-domains' in content or "buy-domain" in content or "this domain name is parked" in content or "this domain is parked" in content or "interested in this domain" in content or "really cool domain parked" in content or "domain is for sale" in content or '_trackpageview("/parked/[% parked_type %]/' in content or "| parked domain" in content or "parked banner" in content or "contact with domain owner" in content or "web page is parked" in content or "buy or lease this domain" in content or "parked domain name on " in content or "it is currently parked by the owner" in content or "parked page for" in content ): self.switch_to_down() return self @ExtraRuleHandlerBase.ensure_status_is_given @ExtraRuleHandlerBase.setup_status_before @ExtraRuleHandlerBase.setup_status_after def start(self) -> "ParkedRulesHandler": PyFunceble.facility.Logger.info( "Started to check %r against our own set of parked rules.", self.status.idna_subject, ) try: self.do_request() if self.status.status_before_extra_rules == PyFunceble.storage.STATUS.up: self._switch_down_by_cookie() if not self.status.status_after_extra_rules: self._swith_down_by_content() PyFunceble.facility.Logger.info( "Finished to check %r against our own set of parked rules.", self.status.idna_subject, ) except PyFunceble.factory.Requester.exceptions.RequestException: pass return self PyFunceble-4.2.29.dev/PyFunceble/checker/availability/extras/rules.py000066400000000000000000000231741467462152100255640ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the extra rules handler based on the status code. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional from box import Box import PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.checker.availability.extras.base import ExtraRuleHandlerBase from PyFunceble.checker.availability.status import AvailabilityCheckerStatus from PyFunceble.helpers.regex import RegexHelper class ExtraRulesHandler(ExtraRuleHandlerBase): """ Provides our very own extra rules handler. :param status: The previously gathered status. :type status: :class:`~PyFunceble.checker.availability.status.AvailabilityCheckerStatus` """ regex_active2inactive: dict = {} http_codes_dataset: Optional[Box] = None def __init__(self, status: Optional[AvailabilityCheckerStatus] = None) -> None: self.regex_active2inactive = { r"\.000webhostapp\.com": [ (self.switch_to_down_if_status_code, {410, 424}), ], r"\.24\.eu$": [(self.switch_to_down_if_status_code, 503)], r"\.altervista\.org$": [(self.switch_to_down_if_status_code, 403)], r"\.angelfire\.com$": [(self.switch_to_down_if_status_code, 404)], r"\.blogspot\.": [self.handle_blogspot], r"\.canalblog\.com$": [(self.switch_to_down_if_status_code, 404)], r"\.dr\.ag$": [(self.switch_to_down_if_status_code, 503)], r"\.fc2\.com$": [self.handle_fc2_dot_com], r"\.github\.io$": [(self.switch_to_down_if_status_code, 404)], r"\.glitchz\.me$": [(self.switch_to_down_if_status_code, 403)], r"\.godaddysites\.com$": [(self.switch_to_down_if_status_code, 404)], r"\.hpg.com.br$": [(self.switch_to_down_if_status_code, 404)], r"\.imgur\.com$": [self.handle_imgur_dot_com], r"\.liveadvert\.com$": [(self.switch_to_down_if_status_code, 404)], r"\.myhuaweicloudz\.com$": [(self.switch_to_down_if_status_code, 403)], r"\.skyrock\.com$": [(self.switch_to_down_if_status_code, 404)], r"\.sz.id$": [(self.switch_to_down_if_status_code, 302)], r"\.translate\.goog$": [(self.switch_to_down_if_status_code, 403)], r"\.tumblr\.com$": [(self.switch_to_down_if_status_code, 404)], r"\.web\.app$": [(self.switch_to_down_if_status_code, 404)], r"\.wix\.com$": [(self.switch_to_down_if_status_code, 404)], r"^s3\.ap-south-1\.amazonaws\.com$": [ (self.switch_to_down_if_status_code, 403) ], r"^u\.pcloud\.com$": [(self.switch_to_down_if_status_code, 302)], r"\.wordpress\.com$": [ (self.switch_to_down_if_status_code, 410), self.handle_wordpress_dot_com, ], r"\.weebly\.com$": [(self.switch_to_down_if_status_code, {"404", "406"})], r"\.zzz\.com\.ua$": [(self.switch_to_down_if_status_code, {"402"})], } if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.http_codes_dataset = PyFunceble.storage.HTTP_CODES else: self.http_codes_dataset = PyFunceble.storage.STD_HTTP_CODES super().__init__(status) def __regex_registry_handler(self, regex_registry: dict) -> "ExtraRulesHandler": """ Handles the standard regex lookup case. """ regex_helper = RegexHelper() for ( regex, data, ) in regex_registry.items(): broken = False for element in data: if not regex_helper.set_regex(regex).match( self.status.netloc, return_match=False ): continue if isinstance(element, tuple): element[0](*element[1:]) else: element() if self.status.status_after_extra_rules: broken = True break if broken: break return self def handle_blogspot(self) -> "ExtraRulesHandler": """ Handles the :code:`blogspot.*` case. .. warning:: This method assume that we know that we are handling a blogspot domain. """ regex_blogger = [r"create-blog.g?", r"87065", r"doesn’t exist"] self.do_on_body_match( self.req_url, regex_blogger, method=self.switch_to_down, allow_redirects=True, ) return self def handle_wordpress_dot_com(self) -> "ExtraRulesHandler": """ Handles the :code:`wordpress.com` case. .. warning:: This method assume that we know that we are handling a blogspot domain. """ regex_wordpress = [r"doesn’t exist", r"no\slonger\savailable"] self.do_on_body_match( self.req_url, regex_wordpress, method=self.switch_to_down, allow_redirects=True, ) return self def handle_fc2_dot_com(self) -> "ExtraRulesHandler": """ Handles the :code:`fc2.com` case. .. warning:: This method assume that we know that we are handling a fc2 domain. """ self.do_on_header_match( self.req_url, {"location": ["error.fc2.com"]}, method=self.switch_to_down, match_mode="std", strict=True, allow_redirects=False, ) return self def handle_imgur_dot_com(self) -> "ExtraRulesHandler": """ Handles the :code:`imgur.com` case. .. warning:. This method are assuming we are handling a imgur.com subdomain. """ req = PyFunceble.factory.Requester.get( self.req_url_https, allow_redirects=False ) username = self.status.netloc.replace(".imgur.com", "") if "Location" in req.headers: if req.headers["Location"].endswith(("/removed.png", f"/user/{username}")): self.switch_to_down() return self def __handle_active2inactive(self) -> "ExtraRulesHandler": """ Handles the status deescalation. """ if self.status.http_status_code: self.__regex_registry_handler(self.regex_active2inactive) return self @ExtraRuleHandlerBase.ensure_status_is_given @ExtraRuleHandlerBase.setup_status_before @ExtraRuleHandlerBase.setup_status_after def start(self) -> "ExtraRulesHandler": """ Starts the process. """ PyFunceble.facility.Logger.info( "Started to check %r against our own set of extra rules.", self.status.idna_subject, ) if self.status.status_before_extra_rules == PyFunceble.storage.STATUS.up: self.__handle_active2inactive() if ( not self.status.status_after_extra_rules and self.status.status_before_extra_rules in PyFunceble.storage.STATUS.down ): if self.status.ipv4_range_syntax or self.status.ipv6_range_syntax: self.switch_to_up() PyFunceble.facility.Logger.info( "Finished to check %r against our own set of extra rules.", self.status.idna_subject, ) return self PyFunceble-4.2.29.dev/PyFunceble/checker/availability/extras/subject_switch.py000066400000000000000000000133651467462152100274530ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the extra rules handler based on the "switching" domain behavior of some subjects. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional import PyFunceble.facility from PyFunceble.checker.availability.extras.base import ExtraRuleHandlerBase from PyFunceble.checker.availability.status import AvailabilityCheckerStatus from PyFunceble.converter.url2netloc import Url2Netloc class SubjectSwitchRulesHandler(ExtraRuleHandlerBase): """ Provides our very own "subject switch" handler. This handler will be used to detects a subject switch behavior from a server. In other words, this handler should be able to detect the following scenario and switch the original subject to :code:`INACTIVE`. 1. https://www.example.org/hello/world -> https://example.org/hello/world 2. https://m.example.org/hello/world -> https://example.org/hello/world """ url2netloc: Optional[Url2Netloc] = None def __init__(self, status: Optional[AvailabilityCheckerStatus] = None) -> None: self.url2netloc = Url2Netloc() super().__init__(status) def _switch_down_by_history(self) -> "SubjectSwitchRulesHandler": """ Tries to switch the status to :code:`INACTIVE` by following hte history. """ variations = set( [ self.status.netloc.replace("www.", "", 1), self.status.netloc.replace("m.", "", 1), ] ) try: # The current netloc should be included in the variations variations.remove(self.status.netloc) except KeyError: pass start_path = ( self.url2netloc.set_data_to_convert(self.req_url) .parse_url() .parsed_url.path ) for response in self.req.history: if ( not str(response.status_code).startswith("3") or "location" not in response.headers ): continue redirect_url = response.headers["location"] netloc = self.url2netloc.set_data_to_convert(redirect_url).get_converted() local_path = self.url2netloc.parsed_url.path if netloc == self.status.idna_subject and netloc not in variations: continue if not start_path: if local_path != "/": continue elif start_path != local_path: continue self.switch_to_down() break return self @ExtraRuleHandlerBase.ensure_status_is_given @ExtraRuleHandlerBase.setup_status_before @ExtraRuleHandlerBase.setup_status_after def start(self) -> "SubjectSwitchRulesHandler": """ Process the check and handling of the current subject. """ PyFunceble.facility.Logger.info( "Started to check %r against our subject switcher rules.", self.status.idna_subject, ) try: if any(self.status.netloc.startswith(x) for x in ("www.", "m.")): self.do_request() if not self.status.status_after_extra_rules: self._switch_down_by_history() except PyFunceble.factory.Requester.exceptions.RequestException: pass PyFunceble.facility.Logger.info( "Finished to check %r against our subject switcher rules.", self.status.idna_subject, ) return self PyFunceble-4.2.29.dev/PyFunceble/checker/availability/ip.py000066400000000000000000000156131467462152100235330ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the IP availability checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.checker.availability.base import AvailabilityCheckerBase from PyFunceble.checker.reputation.ip import IPReputationChecker class IPAvailabilityChecker(AvailabilityCheckerBase): """ Provides the interface for checking the availability of a given IP. :param str subject: Optional, The subject to work with. :param bool use_extra_rules: Optional, Activates/Disables the usage of our own set of extra rules. :param bool use_whois_lookup: Optional, Activates/Disables the usage of the WHOIS lookup to gather the status of the given :code:`subject`. :param bool use_dns_lookup: Optional, Activates/Disables the usage of the DNS lookup to gather the status of the given :code:`subject`. :param bool use_netinfo_lookup: Optional, Activates/Disables the usage of the network information lookup module to gather the status of the given :code:`subject`. :param bool use_http_code_lookup: Optional, Activates/Disables the usage of the HTTP status code lookup to gather the status of the given :code:`subject`. :param bool use_reputation_lookup: Optional, Activates/Disables the usage of the reputation dataset lookup to gather the status of the given :code:`subject`. :param bool do_syntax_check_first: Optional, Activates/Disables the check of the status before the actual status gathering. :param bool use_whois_db: Optional, Activates/Disable the usage of a local database to store the WHOIS datasets. """ def try_to_query_status_from_reputation(self) -> "IPAvailabilityChecker": """ Tries to query the status from the reputation lookup. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: Reputation Lookup", self.status.idna_subject, ) lookup_result = IPReputationChecker(self.status.idna_subject).get_status() # pylint: disable=no-member if lookup_result and lookup_result.is_malicious(): self.status.status = PyFunceble.storage.STATUS.up self.status.status_source = "REPUTATION" PyFunceble.facility.Logger.info( "Could define the status of %r from: Reputation Lookup", self.status.idna_subject, ) PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: Reputation Lookup", self.status.idna_subject, ) return self @AvailabilityCheckerBase.ensure_subject_is_given @AvailabilityCheckerBase.update_status_date_after_query def query_status( self, ) -> "IPAvailabilityChecker": # pragma: no cover """ Queries the result without anything more. """ ## Test Methods are more important. status_post_syntax_checker = None if self.do_syntax_check_first and self.should_we_continue_test( status_post_syntax_checker ): self.try_to_query_status_from_syntax_lookup() if self.status.status: status_post_syntax_checker = self.status.status if self.use_dns_lookup and self.should_we_continue_test( status_post_syntax_checker ): self.try_to_query_status_from_dns() if self.use_netinfo_lookup and self.should_we_continue_test( status_post_syntax_checker ): self.try_to_query_status_from_netinfo() if self.use_reputation_lookup and self.should_we_continue_test( status_post_syntax_checker ): self.try_to_query_status_from_reputation() if self.use_http_code_lookup and self.should_we_continue_test( status_post_syntax_checker ): self.try_to_query_status_from_http_status_code() if not self.status.status: self.status.status = PyFunceble.storage.STATUS.down self.status.status_source = "STDLOOKUP" PyFunceble.facility.Logger.info( "Could not define status the status of %r. Setting to %r", self.status.idna_subject, self.status.status, ) if self.use_extra_rules: self.try_to_query_status_from_extra_rules() return self @staticmethod def is_valid() -> bool: # pylint: disable=arguments-differ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/checker/availability/params.py000066400000000000000000000062041467462152100244020ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our parameter class. The parameter class is the class that will be provided to end-user. It is only a placeholder and should only be taken as informative. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 dataclasses from typing import Optional from PyFunceble.checker.params_base import CheckerParamsBase @dataclasses.dataclass class AvailabilityCheckerParams(CheckerParamsBase): """ Provides the description of an availability checker paramaters. """ use_extra_rules: Optional[bool] = None use_whois_lookup: Optional[bool] = None use_dns_lookup: Optional[bool] = None use_netinfo_lookup: Optional[bool] = None use_http_code_lookup: Optional[bool] = None use_reputation_lookup: Optional[bool] = None do_syntax_check_first: Optional[bool] = None use_whois_db: Optional[bool] = None PyFunceble-4.2.29.dev/PyFunceble/checker/availability/status.py000066400000000000000000000121541467462152100244430ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our status class. The status class is the class that will be provided to end-user. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 dataclasses from typing import Dict, List, Optional import PyFunceble.storage from PyFunceble.checker.availability.params import AvailabilityCheckerParams from PyFunceble.checker.status_base import CheckerStatusBase from PyFunceble.query.record.dns import DNSQueryToolRecord from PyFunceble.query.record.whois import WhoisQueryToolRecord @dataclasses.dataclass class AvailabilityCheckerStatus(CheckerStatusBase): """ Provides the description of an availablity status. """ # pylint: disable=too-many-instance-attributes checker_type: Optional[str] = "AVAILABILITY" dns_lookup_record: Optional[DNSQueryToolRecord] = None whois_lookup_record: Optional[WhoisQueryToolRecord] = None domain_syntax: Optional[bool] = None second_level_domain_syntax: Optional[bool] = None subdomain_syntax: Optional[bool] = None ip_syntax: Optional[bool] = None ipv4_syntax: Optional[bool] = None ipv6_syntax: Optional[bool] = None ipv4_range_syntax: Optional[bool] = None ipv6_range_syntax: Optional[bool] = None url_syntax: Optional[bool] = None expiration_date: Optional[str] = None registrar: Optional[str] = None whois_record: Optional[str] = None status_before_extra_rules: Optional[str] = None status_after_extra_rules: Optional[str] = None status_source_before_extra_rules: Optional[str] = None status_source_after_extra_rules: Optional[str] = None dns_lookup: Optional[Dict[str, Optional[List[str]]]] = None netinfo: Optional[Dict[str, Optional[List[str]]]] = None http_status_code: Optional[int] = None def __post_init__(self) -> None: self.dns_lookup_record = DNSQueryToolRecord() self.whois_lookup_record = WhoisQueryToolRecord() self.params = AvailabilityCheckerParams() def is_special(self) -> bool: """ Checks if the current status is a SPECIAL one. Meaning that we applied some of our own rules. """ return bool(self.status_after_extra_rules) def is_available(self) -> bool: """ Checks if the current status represent an available subject. """ return self.is_active() def is_active(self) -> bool: """ Checks if the current status is an ACTIVE one. """ return self.status == PyFunceble.storage.STATUS.up def is_inactive(self) -> bool: """ Checks if the current status is an INACTIVE one. """ return self.status == PyFunceble.storage.STATUS.down def is_invalid(self) -> bool: """ Checks if the current status is an INVALID one. """ return self.status == PyFunceble.storage.STATUS.invalid PyFunceble-4.2.29.dev/PyFunceble/checker/availability/url.py000066400000000000000000000261101467462152100237170ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the URL availability checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.checker.availability.base import AvailabilityCheckerBase from PyFunceble.checker.availability.status import AvailabilityCheckerStatus from PyFunceble.checker.reputation.url import URLReputationChecker from PyFunceble.checker.syntax.url import URLSyntaxChecker class URLAvailabilityChecker(AvailabilityCheckerBase): """ Provides the interface for checking the availability of a given URL. :param str subject: Optional, The subject to work with. :param bool use_extra_rules: Optional, Activates/Disables the usage of our own set of extra rules. :param bool use_whois_lookup: Optional, Activates/Disables the usage of the WHOIS lookup to gather the status of the given :code:`subject`. :param bool use_dns_lookup: Optional, Activates/Disables the usage of the DNS lookup to gather the status of the given :code:`subject`. :param bool use_netinfo_lookup: Optional, Activates/Disables the usage of the network information lookup module to gather the status of the given :code:`subject`. :param bool use_http_code_lookup: Optional, Activates/Disables the usage of the HTTP status code lookup to gather the status of the given :code:`subject`. :param bool use_reputation_lookup: Optional, Activates/Disables the usage of the reputation dataset lookup to gather the status of the given :code:`subject`. :param bool do_syntax_check_first: Optional, Activates/Disables the check of the status before the actual status gathering. :param bool use_whois_db: Optional, Activates/Disable the usage of a local database to store the WHOIS datasets. """ def subject_propagator(self) -> "URLAvailabilityChecker": """ Propagate the currently set subject. .. warning:: You are not invited to run this method directly. .. versionchanged:: 4.1.0b7.dev DNS Lookup capability. """ self.http_status_code_query_tool.set_subject(self.idna_subject) self.dns_query_tool.set_subject( URLSyntaxChecker.get_hostname_from_url(self.idna_subject) or self.idna_subject ) self.domain_syntax_checker.subject = self.idna_subject self.ip_syntax_checker.subject = self.idna_subject self.url_syntax_checker.subject = self.idna_subject self.status = AvailabilityCheckerStatus() self.status.params = self.params self.status.dns_lookup_record = self.dns_query_tool.lookup_record self.status.whois_lookup_record = None self.status.subject = self.subject self.status.idna_subject = self.idna_subject self.status.netloc = self.url2netloc.set_data_to_convert( self.idna_subject ).get_converted() self.status.status = None self.query_common_checker() return self def try_to_query_status_from_http_status_code( self, *, from_domain_test: bool = False ) -> "URLAvailabilityChecker": """ Tries to query the status from the network information. :param bool from_domain_test: Whether we wanted to test a test - actually. Setting this argument to :py:class:`True` will exit the http_status_code test if the given subject is already a URL. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: HTTP Status code Lookup", self.status.idna_subject, ) if from_domain_test and self.status.url_syntax: return self lookup_result = self.http_status_code_query_tool.get_status_code() if ( lookup_result and lookup_result != self.http_status_code_query_tool.STD_UNKNOWN_STATUS_CODE ): self.status.http_status_code = lookup_result if ( PyFunceble.facility.ConfigLoader.is_already_loaded() ): # pragma: no cover ## Special behavior dataset = PyFunceble.storage.HTTP_CODES else: dataset = PyFunceble.storage.STD_HTTP_CODES if ( self.status.http_status_code in dataset.list.up or self.status.http_status_code in dataset.list.potentially_up ): self.status.status = PyFunceble.storage.STATUS.up self.status.status_source = "HTTP CODE" PyFunceble.facility.Logger.info( "Could define the status of %r from: HTTP Status code Lookup", self.status.idna_subject, ) else: self.status.http_status_code = None PyFunceble.facility.Logger.info( "Finished to try to query the status of %r from: HTTP Status code Lookup", self.status.idna_subject, ) return self def try_to_query_status_from_reputation(self) -> "URLAvailabilityChecker": """ Tries to query the status from the reputation lookup. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: Reputation Lookup", self.status.idna_subject, ) lookup_result = URLReputationChecker(self.status.idna_subject).get_status() # pylint: disable=no-member if lookup_result and lookup_result.is_malicious(): self.status.status = PyFunceble.storage.STATUS.up self.status.status_source = "REPUTATION" PyFunceble.facility.Logger.info( "Could define the status of %r from: Reputation Lookup", self.status.idna_subject, ) PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: Reputation Lookup", self.status.idna_subject, ) return self def try_to_query_status_from_dns(self) -> "AvailabilityCheckerBase": """ Tries to query the status from the DNS lookup after switching the idna subject to the url base. .. warning:: This method does not answer as you may expect. Indeed, if a DNS lookup failed, this method will overwrite the standard response by setting the status to :code:`INACTIVE` and the status source to :code:`DNSLOOKUP`. .. versionadded:: 4.1.0b7 DNS Lookup as a "down" switcher. """ result = super().try_to_query_status_from_dns() if self.status.status == PyFunceble.storage.STATUS.up: # DNS should only be use to take subject down. # Therefore, switching back as if nothing happened. self.status.status = None self.status.status_source = None else: self.status.status = PyFunceble.storage.STATUS.down self.status.status_source = "DNSLOOKUP" return result @AvailabilityCheckerBase.ensure_subject_is_given @AvailabilityCheckerBase.update_status_date_after_query def query_status( self, ) -> "URLAvailabilityChecker": # pragma: no cover """ Queries the result without anything more. .. versionchanged:: 4.1.0b7.dev DNS Query - first. """ ## Test Methods are more important. status_post_syntax_checker = None if not self.status.status and self.do_syntax_check_first: self.try_to_query_status_from_syntax_lookup(from_url_test=True) if self.status.status: status_post_syntax_checker = self.status.status if self.use_reputation_lookup and self.should_we_continue_test( status_post_syntax_checker ): self.try_to_query_status_from_reputation() if ( self.should_we_continue_test(status_post_syntax_checker) and self.status.url_syntax ): self.try_to_query_status_from_dns() if self.should_we_continue_test(status_post_syntax_checker): self.try_to_query_status_from_http_status_code() if not self.status.status: self.status.status = PyFunceble.storage.STATUS.down self.status.status_source = "STDLOOKUP" PyFunceble.facility.Logger.info( "Could not define status the status of %r. Setting to %r", self.status.idna_subject, self.status.status, ) if self.use_extra_rules: self.try_to_query_status_from_extra_rules() return self @staticmethod def is_valid() -> bool: # pylint: disable=arguments-differ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/checker/base.py000066400000000000000000000324571467462152100213700ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 datetime import functools from typing import Optional import domain2idna from sqlalchemy.orm import Session import PyFunceble.facility import PyFunceble.storage from PyFunceble.checker.params_base import CheckerParamsBase from PyFunceble.checker.status_base import CheckerStatusBase from PyFunceble.converter.url2netloc import Url2Netloc from PyFunceble.query.platform import PlatformQueryTool class CheckerBase: """ Provides the base of all checker. :param str subject: Optional, The subject to work with. :param bool do_syntax_check_first: Optional, Forces the checker to first perform a syntax check, .. warning:: This does not apply to the syntax checker - itself. """ STD_DO_SYNTAX_CHECK_FIRST: bool = False STD_USE_PLATFORM: bool = False _do_syntax_check_first: bool = False _use_platform: bool = False _subject: Optional[str] = None _idna_subject: Optional[str] = None url2netloc: Optional[Url2Netloc] = None db_session: Optional[Session] = None platform_query_tool: Optional[PlatformQueryTool] = None status: Optional[CheckerStatusBase] = None params: Optional[CheckerParamsBase] = None def __init__( self, subject: Optional[str] = None, *, do_syntax_check_first: Optional[bool] = None, db_session: Optional[Session] = None, use_platform: Optional[bool] = None, ) -> None: self.platform_query_tool = PlatformQueryTool() self.url2netloc = Url2Netloc() if self.params is None: self.params = CheckerParamsBase() if self.status is None: self.status = CheckerStatusBase() if subject is not None: self.subject = subject if do_syntax_check_first is not None: self.do_syntax_check_first = do_syntax_check_first else: self.do_syntax_check_first = self.STD_DO_SYNTAX_CHECK_FIRST if use_platform is not None: self.use_platform = use_platform else: self.guess_and_set_use_platform() self.db_session = db_session def propagate_subject(func): # pylint: disable=no-self-argument """ Propagates the subject to the object that need it after launching the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) # pylint: disable=not-callable self.subject_propagator() return result return wrapper def ensure_subject_is_given(func): # pylint: disable=no-self-argument """ Ensures that the subject is given before running the decorated method. :raise TypeError: If the subject is not a string. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): # pragma: no cover ## Safety! if not isinstance(self.subject, str): raise TypeError( f" should be {str}, {type(self.subject)} given." ) return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def query_status_if_missing(func): # pylint: disable=no-self-argument """ Queries the status if it's missing. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): # pragma: no cover ## Safety! if not self.status.status or self.status.status is None: self.query_status() return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def update_status_date_after_query(func): # pylint: disable=no-self-argument """ Updates the status dates after running the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): # pragma: no cover ## Safety! result = func(self, *args, **kwargs) # pylint: disable=not-callable self.status.tested_at = datetime.datetime.now(datetime.timezone.utc) return result return wrapper @property def subject(self) -> Optional[str]: """ Provides the current state of the :code:`_subject` attribute. """ return self._subject @subject.setter @propagate_subject def subject(self, value: str) -> None: """ Sets the subject to work with. :param value: The subject to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._subject = value try: self.idna_subject = domain2idna.domain2idna(value) except ValueError: self.idna_subject = value def set_subject(self, value: str) -> "CheckerBase": """ Sets the subject to work with. :param value: The subject to set. """ self.subject = value return self @property def idna_subject(self) -> Optional[str]: """ Provides the current state of the :code:`_idna_subject` attribute. """ return self._idna_subject @idna_subject.setter def idna_subject(self, value: str) -> None: """ Sets the subject to work with. :param value: The subject to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._idna_subject = value def set_idna_subject(self, value: str) -> "CheckerBase": """ Sets the subject to work with. :param value: The subject to set. """ self.idna_subject = value return self @property def do_syntax_check_first(self) -> None: """ Provides the current state of the :code:`do_syntax_check_first` attribute. """ return self._do_syntax_check_first @do_syntax_check_first.setter def do_syntax_check_first(self, value: bool) -> None: """ Sets the value which allow us to do a syntax check first. :param value: The subject to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {str}, {type(value)} given.") self._do_syntax_check_first = self.params.do_syntax_check_first = value def set_do_syntax_check_first(self, value: bool) -> "CheckerBase": """ Sets the value which allow us to do a syntax check first. :param value: The subject to set. """ self.do_syntax_check_first = value return self @property def use_platform(self) -> bool: """ Provides the current value of the :code:`_use_platform` attribute. """ return self._use_platform @use_platform.setter def use_platform(self, value: bool) -> None: """ Sets the value which authorizes the usage of the platform. :param value: The value to set. :param TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._use_platform = self.params.use_platform = value def set_use_platform(self, value: bool) -> "CheckerBase": """ Sets the value which authorizes the usage of the platform. :param value: The value to set. """ self.use_platform = value return self def guess_and_set_use_platform(self) -> "CheckerBase": """ Try to guess and set the value of the :code:`use_platform` attribute. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if isinstance(PyFunceble.storage.CONFIGURATION.lookup.platform, bool): self.use_platform = PyFunceble.storage.CONFIGURATION.lookup.platform else: self.use_platform = self.STD_USE_PLATFORM else: self.use_platform = self.STD_USE_PLATFORM def subject_propagator(self) -> "CheckerBase": """ Propagate the currently set subject. .. warning:: Be sure to use setup your status first. """ self.status.subject = self.subject self.status.idna_subject = self.idna_subject self.status.netloc = self.url2netloc.set_data_to_convert( self.idna_subject ).get_converted() self.status.status = None return self.query_common_checker() def query_common_checker(self) -> "CheckerBase": """ Queries the common checkers. .. warning:: Be sure to use setup your status first. """ if not self.status.subject_kind: cls_name = self.__class__.__name__.lower() if ( hasattr(self.status, "ip_syntax") and self.status.ip_syntax ) or "ip" in cls_name: self.status.subject_kind = "ip" elif ( hasattr(self.status, "url_syntax") and self.status.url_syntax ) or "url" in cls_name: self.status.subject_kind = "url" elif ( hasattr(self.status, "domain_syntax") and self.status.domain_syntax ) or "domain" in cls_name: self.status.subject_kind = "domain" else: self.status.subject_kind = "unknown" return self @ensure_subject_is_given def is_valid(self) -> bool: """ Provides the result of the validation. """ raise NotImplementedError() @ensure_subject_is_given @update_status_date_after_query def query_status(self) -> "CheckerBase": """ Queries the status. """ raise NotImplementedError() @query_status_if_missing def get_status(self) -> Optional[CheckerStatusBase]: """ Provides the current state of the status. .. note:: This method will automatically query status using the :meth:`PyFunceble.checker.base.CheckerBase.query_status` if the :attr:`PyFunceble.checker.status_base.CheckerStatusBase.status` attribute is not set. """ return self.status PyFunceble-4.2.29.dev/PyFunceble/checker/complex_json_encoder.py000066400000000000000000000061661467462152100246530ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our very own complex JSON encoder. The purpose of this encoder compared to others is that it was built for the conversion of records or statuses provided by the checker(s). Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 dataclasses import datetime import json from typing import Any import dns.name class ComplexJsonEncoder(json.JSONEncoder): """ Provides our very own complex JSON encoder. """ def default(self, o: Any) -> Any: """ Implements our very own conversion. """ if dataclasses.is_dataclass(o): return dataclasses.asdict(o) if isinstance(o, dns.name.Name): return ".".join(x.decode() for x in o.labels) if isinstance(o, datetime.datetime): return o.isoformat() return super().default(o) PyFunceble-4.2.29.dev/PyFunceble/checker/params_base.py000066400000000000000000000063211467462152100227220ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our params classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 dataclasses from typing import Optional from PyFunceble.checker.complex_json_encoder import ComplexJsonEncoder from PyFunceble.helpers.dict import DictHelper @dataclasses.dataclass class CheckerParamsBase: """ Provides the base of all parameters classes. """ do_syntax_check_first: Optional[bool] = None use_platform: Optional[bool] = None def to_dict(self) -> dict: """ Converts the current object to dict. """ return { x: y if not hasattr(y, "to_dict") else y.to_dict() for x, y in self.__dict__.items() if not x.startswith("__") } def to_json(self) -> str: """ Converts the current object to JSON. """ return DictHelper(self.to_dict()).to_json(own_class=ComplexJsonEncoder) PyFunceble-4.2.29.dev/PyFunceble/checker/reputation/000077500000000000000000000000001467462152100222635ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/checker/reputation/__init__.py000066400000000000000000000046521467462152100244030ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the core of the reputation checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/checker/reputation/base.py000066400000000000000000000276151467462152100235620ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all reputation checker classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import List, Optional from sqlalchemy.orm import Session import PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.checker.base import CheckerBase from PyFunceble.checker.reputation.params import ReputationCheckerParams from PyFunceble.checker.reputation.status import ReputationCheckerStatus from PyFunceble.checker.syntax.domain import DomainSyntaxChecker from PyFunceble.checker.syntax.ip import IPSyntaxChecker from PyFunceble.checker.syntax.url import URLSyntaxChecker from PyFunceble.dataset.ipv4_reputation import IPV4ReputationDataset from PyFunceble.query.dns.query_tool import DNSQueryTool class ReputationCheckerBase(CheckerBase): """ Provides the base of all our reputation checker classes. :param str subject: Optional, The subject to work with. :param bool do_syntax_check_first: Optional, Activates/Disables the check of the status before the actual status gathering. """ dns_query_tool: Optional[DNSQueryTool] = None ipv4_reputation_query_tool: Optional[IPV4ReputationDataset] = None domain_syntax_checker: Optional[DomainSyntaxChecker] = None ip_syntax_checker: Optional[IPSyntaxChecker] = None url_syntax_checker: Optional[URLSyntaxChecker] = None status: Optional[ReputationCheckerStatus] = None params: Optional[ReputationCheckerParams] = None def __init__( self, subject: Optional[str] = None, do_syntax_check_first: Optional[bool] = None, db_session: Optional[Session] = None, use_platform: Optional[bool] = None, ) -> None: self.dns_query_tool = DNSQueryTool() self.ipv4_reputation_query_tool = IPV4ReputationDataset() self.domain_syntax_checker = DomainSyntaxChecker() self.ip_syntax_checker = IPSyntaxChecker() self.url_syntax_checker = URLSyntaxChecker() self.params = ReputationCheckerParams() self.status = ReputationCheckerStatus() self.status.params = self.params self.status.dns_lookup_record = self.dns_query_tool.lookup_record super().__init__( subject, do_syntax_check_first=do_syntax_check_first, db_session=db_session, use_platform=use_platform, ) @staticmethod def is_valid() -> bool: # pylint: disable=arguments-differ raise NotImplementedError() def subject_propagator(self) -> "CheckerBase": """ Propagate the currently set subject. .. warning:: You are not invited to run this method directly. """ self.dns_query_tool.set_subject(self.idna_subject) self.domain_syntax_checker.subject = self.idna_subject self.ip_syntax_checker.subject = self.idna_subject self.url_syntax_checker.subject = self.idna_subject self.status = ReputationCheckerStatus() self.status.params = self.params self.status.dns_lookup_record = self.dns_query_tool.lookup_record return super().subject_propagator() def should_we_continue_test(self, status_post_syntax_checker: str) -> bool: """ Checks if we are allowed to continue a standard testing. """ return bool( not self.status.status or status_post_syntax_checker == PyFunceble.storage.STATUS.invalid ) def query_common_checker(self) -> "ReputationCheckerBase": """ Queries the common checkers. """ self.status.second_level_domain_syntax = ( self.domain_syntax_checker.is_valid_second_level() ) self.status.subdomain_syntax = self.domain_syntax_checker.is_valid_subdomain() self.status.domain_syntax = bool(self.status.subdomain_syntax) or bool( self.status.second_level_domain_syntax ) self.status.ipv4_syntax = self.ip_syntax_checker.is_valid_v4() self.status.ipv6_syntax = self.ip_syntax_checker.is_valid_v6() self.status.ipv4_range_syntax = self.ip_syntax_checker.is_valid_v4_range() self.status.ipv6_range_syntax = self.ip_syntax_checker.is_valid_v6_range() self.status.ip_syntax = bool(self.status.ipv4_syntax or self.status.ipv6_syntax) self.status.url_syntax = self.url_syntax_checker.is_valid() return super().query_common_checker() def query_a_record(self) -> Optional[List[str]]: """ Queries all the A record. """ raise NotImplementedError() def try_to_query_status_from_dns_lookup(self) -> "ReputationCheckerBase": """ Tries to query the status from the DNS lookup. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: DNS Lookup", self.status.idna_subject, ) if not self.status.ipv4_syntax: lookup_result = self.query_a_record() self.status.dns_lookup = lookup_result else: lookup_result = [self.status.subject] if lookup_result: for subject in lookup_result: if subject in self.ipv4_reputation_query_tool: self.status.status = PyFunceble.storage.STATUS.malicious self.status.status_source = "REPUTATION" PyFunceble.facility.Logger.info( "Could define the status of %r from: DNS Lookup", self.status.idna_subject, ) break PyFunceble.facility.Logger.info( "Finished to try to query the status of %r from: DNS Lookup", self.status.idna_subject, ) return self def try_to_query_status_from_syntax_lookup(self) -> "ReputationCheckerBase": """ Tries to query the status from the syntax. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: Syntax Lookup", self.status.idna_subject, ) if ( not self.status.domain_syntax and not self.status.ip_syntax and not self.status.url_syntax ): self.status.status = PyFunceble.storage.STATUS.invalid self.status.status_source = "SYNTAX" PyFunceble.facility.Logger.info( "Could define the status of %r from: Syntax Lookup", self.status.idna_subject, ) PyFunceble.facility.Logger.info( "Finished to try to query the status of %r from: Syntax Lookup", self.status.idna_subject, ) return self def try_to_query_status_from_platform(self) -> "ReputationCheckerBase": """ Tries to get and set the status from the Platform API. """ PyFunceble.facility.Logger.info( "Started to try to query the status of %r from: Platform Lookup", self.status.idna_subject, ) data = self.platform_query_tool[self.idna_subject] if data and "status" in data: if ( self.platform_query_tool.preferred_status_origin == "frequent" and data["status"]["reputation"]["frequent"] ): self.status.status = data["status"]["reputation"]["frequent"] self.status.status_source = "PLATFORM" elif ( self.platform_query_tool.preferred_status_origin == "latest" and data["status"]["reputation"]["latest"] ): self.status.status = data["status"]["reputation"]["latest"]["status"] self.status.status_source = "PLATFORM" elif ( self.platform_query_tool.preferred_status_origin == "recommended" and data["status"]["reputation"]["recommended"] ): self.status.status = data["status"]["reputation"]["recommended"] self.status.status_source = "PLATFORM" PyFunceble.facility.Logger.info( "Could define the status of %r from: Platform Lookup", self.status.idna_subject, ) PyFunceble.facility.Logger.info( "Finished to try to query the status of %r from: Platform Lookup", self.status.idna_subject, ) @CheckerBase.ensure_subject_is_given @CheckerBase.update_status_date_after_query def query_status(self) -> "ReputationCheckerBase": """ Queries the status and for for more action. """ status_post_syntax_checker = None if ( not self.status.status and self.use_platform ): # pragma: no cover ## Underlying tested self.try_to_query_status_from_platform() if not self.status.status and self.do_syntax_check_first: self.try_to_query_status_from_syntax_lookup() if self.status.status: status_post_syntax_checker = self.status.status if self.should_we_continue_test(status_post_syntax_checker): self.try_to_query_status_from_dns_lookup() if not self.status.status: self.status.status = PyFunceble.storage.STATUS.sane self.status.status_source = "REPUTATION" PyFunceble.facility.Logger.info( "Could not define the status of %r. Setting to %r", self.status.idna_subject, self.status.status, ) return self # pylint: disable=useless-super-delegation def get_status(self) -> Optional[ReputationCheckerStatus]: return super().get_status() PyFunceble-4.2.29.dev/PyFunceble/checker/reputation/domain.py000066400000000000000000000057111467462152100241100ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides domain reputation checker classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import List, Optional from PyFunceble.checker.reputation.base import ReputationCheckerBase class DomainReputationChecker(ReputationCheckerBase): """ Provides the domain reputation checker classes. :param str subject: Optional, The subject to work with. :param bool do_syntax_check_first: Optional, Activates/Disables the check of the status before the actual status gathering. """ def query_a_record(self) -> Optional[List[str]]: return self.dns_query_tool.set_query_record_type("A").query() PyFunceble-4.2.29.dev/PyFunceble/checker/reputation/domain_and_ip.py000066400000000000000000000100761467462152100254220ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the domains and IP reputation checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.checker.reputation.base import ReputationCheckerBase from PyFunceble.checker.reputation.domain import DomainReputationChecker from PyFunceble.checker.reputation.ip import IPReputationChecker class DomainAndIPReputationChecker(ReputationCheckerBase): """ Provides the interface for checking the reputation of an IP or domain. :param str subject: Optional, The subject to work with. :param bool do_syntax_check_first: Optional, Activates/Disables the check of the status before the actual status gathering. """ @ReputationCheckerBase.ensure_subject_is_given @ReputationCheckerBase.update_status_date_after_query def query_status(self) -> "DomainAndIPReputationChecker": """ Queries the result without anything more. """ if self.status.ip_syntax: query_object = IPReputationChecker( self.subject, do_syntax_check_first=self.do_syntax_check_first, db_session=self.db_session, use_platform=self.use_platform, ) else: query_object = DomainReputationChecker( self.subject, do_syntax_check_first=self.do_syntax_check_first, db_session=self.db_session, use_platform=self.use_platform, ) query_object.ipv4_reputation_query_tool = self.ipv4_reputation_query_tool query_object.platform_query_tool = self.platform_query_tool query_object.dns_query_tool = self.dns_query_tool result = query_object.query_status() self.__dict__.update(query_object.__dict__) return result PyFunceble-4.2.29.dev/PyFunceble/checker/reputation/ip.py000066400000000000000000000064201467462152100232470ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides domain reputation checker classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import List, Optional from PyFunceble.checker.reputation.base import ReputationCheckerBase class IPReputationChecker(ReputationCheckerBase): """ Provides the IP reputation checker. :param str subject: Optional, The subject to work with. :param bool do_syntax_check_first: Optional, Activates/Disables the check of the status before the actual status gathering. """ def query_a_record(self) -> Optional[List[str]]: result = set() for subject in self.dns_query_tool.set_query_record_type("PTR").query(): result.update( self.dns_query_tool.set_subject(subject) .set_query_record_type("A") .query() ) # Do not break future usage of the query tool. self.dns_query_tool.subject = self.idna_subject return list(result) PyFunceble-4.2.29.dev/PyFunceble/checker/reputation/params.py000066400000000000000000000053711467462152100241260ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our parameter class. The parameter class is the class that will be provided to end-user. It is only a placeholder and should only be taken as informative. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 dataclasses from PyFunceble.checker.params_base import CheckerParamsBase @dataclasses.dataclass class ReputationCheckerParams(CheckerParamsBase): """ Provides the description of a reputation checker paramaters. """ PyFunceble-4.2.29.dev/PyFunceble/checker/reputation/status.py000066400000000000000000000077271467462152100241750ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our status class. The status class is the class that will be provided to end-user. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 dataclasses from typing import List, Optional import PyFunceble.storage from PyFunceble.checker.status_base import CheckerStatusBase from PyFunceble.query.record.dns import DNSQueryToolRecord @dataclasses.dataclass class ReputationCheckerStatus(CheckerStatusBase): """ Provides the description of an availablity status. """ # pylint: disable=too-many-instance-attributes checker_type: Optional[str] = "REPUTATION" dns_lookup_record: Optional[DNSQueryToolRecord] = None domain_syntax: Optional[bool] = None second_level_domain_syntax: Optional[bool] = None subdomain_syntax: Optional[bool] = None ip_syntax: Optional[bool] = None ipv4_syntax: Optional[bool] = None ipv6_syntax: Optional[bool] = None ipv4_range_syntax: Optional[bool] = None ipv6_range_syntax: Optional[bool] = None url_syntax: Optional[bool] = None dns_lookup: Optional[List[str]] = None def __post_init__(self) -> None: self.dns_lookup_record = DNSQueryToolRecord() def has_bad_reputation(self) -> bool: """ Checks if the current status represent an available subject. """ return self.is_malicious() def is_sane(self) -> bool: """ Checks if the current status is an SANE one. """ return self.status == PyFunceble.storage.STATUS.sane def is_malicious(self) -> bool: """ Checks if the current status is an MALICIOUS one. """ return self.status == PyFunceble.storage.STATUS.malicious PyFunceble-4.2.29.dev/PyFunceble/checker/reputation/url.py000066400000000000000000000100111467462152100234300ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides URL reputation checker classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import List, Optional from PyFunceble.checker.reputation.base import ReputationCheckerBase from PyFunceble.checker.syntax.ip import IPSyntaxChecker from PyFunceble.converter.url2netloc import Url2Netloc class URLReputationChecker(ReputationCheckerBase): """ Provides the URL reputation checker. :param str subject: Optional, The subject to work with. :param bool do_syntax_check_first: Optional, Activates/Disables the check of the status before the actual status gathering. """ def query_a_record(self) -> Optional[List[str]]: url_base = Url2Netloc(self.status.subject).get_converted() ip_syntax_checker = IPSyntaxChecker(url_base) if ip_syntax_checker.is_valid_v4(): return [url_base] if ip_syntax_checker.is_valid_v6() or ( url_base.startswith("[") and url_base.endswith("]") ): url_base = url_base.replace("[", "").replace("]", "") result = set() for subject in ( self.dns_query_tool.set_query_record_type("PTR") .set_subject(url_base) .query() ): result.update( self.dns_query_tool.set_subject(subject) .set_query_record_type("A") .query() ) self.dns_query_tool.subject = self.idna_subject return result result = ( self.dns_query_tool.set_query_record_type("A").set_subject(url_base).query() ) self.dns_query_tool.subject = self.idna_subject return result PyFunceble-4.2.29.dev/PyFunceble/checker/status_base.py000066400000000000000000000070001467462152100227550ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our status classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 dataclasses import datetime from typing import Optional from PyFunceble.checker.complex_json_encoder import ComplexJsonEncoder from PyFunceble.checker.params_base import CheckerParamsBase from PyFunceble.helpers.dict import DictHelper @dataclasses.dataclass class CheckerStatusBase: """ Provides the base of all status classes. """ subject_kind: Optional[str] = None subject: Optional[str] = None idna_subject: Optional[str] = None netloc: Optional[str] = None status: Optional[str] = None status_source: Optional[str] = None tested_at: Optional[datetime.datetime] = None params: Optional[CheckerParamsBase] = None def to_dict(self) -> dict: """ Converts the current object to dict. """ return { x: y if not hasattr(y, "to_dict") else y.to_dict() for x, y in self.__dict__.items() if not x.startswith("__") } def to_json(self) -> str: """ Converts the current object to JSON. """ return DictHelper(self.to_dict()).to_json(own_class=ComplexJsonEncoder) PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/000077500000000000000000000000001467462152100214175ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/__init__.py000066400000000000000000000046461467462152100235420ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the core of the syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/base.py000066400000000000000000000104671467462152100227130ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all syntax checker classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional from sqlalchemy.orm import Session import PyFunceble.storage from PyFunceble.checker.base import CheckerBase from PyFunceble.checker.syntax.params import SyntaxCheckerParams from PyFunceble.checker.syntax.status import SyntaxCheckerStatus class SyntaxCheckerBase(CheckerBase): """ Provides the base of all our syntax checker classes. :param str subject: Optional, The subject to work with. """ db_session: Optional[Session] = None status: Optional[SyntaxCheckerStatus] = None params: Optional[SyntaxCheckerParams] = None def __init__( self, subject: Optional[str] = None, db_session: Optional[Session] = None, ) -> None: self.params = SyntaxCheckerParams() self.status = SyntaxCheckerStatus() self.status.params = self.params super().__init__(subject=subject, db_session=db_session) def subject_propagator(self) -> "CheckerBase": """ Propagate the currently set subject. .. warning:: You are not invited to run this method directly. """ self.status = SyntaxCheckerStatus() return super().subject_propagator() @CheckerBase.ensure_subject_is_given @CheckerBase.update_status_date_after_query def query_status(self) -> "SyntaxCheckerBase": """ Queries the status. """ if self.is_valid(): self.status.status = PyFunceble.storage.STATUS.valid else: self.status.status = PyFunceble.storage.STATUS.invalid self.status.status_source = "SYNTAX" return self @CheckerBase.ensure_subject_is_given def is_valid(self) -> bool: raise NotImplementedError() # pylint: disable=useless-super-delegation def get_status( self, ) -> Optional[SyntaxCheckerStatus]: # pragma: no cover ## Safety. return super().get_status() PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/domain.py000066400000000000000000000112621467462152100232420ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the general domain syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional from sqlalchemy.orm import Session from PyFunceble.checker.syntax.base import SyntaxCheckerBase from PyFunceble.checker.syntax.domain_base import DomainSyntaxCheckerBase from PyFunceble.checker.syntax.second_lvl_domain import SecondLvlDomainSyntaxChecker from PyFunceble.checker.syntax.status import SyntaxCheckerStatus from PyFunceble.checker.syntax.subdomain import SubDomainSyntaxChecker class DomainSyntaxChecker(DomainSyntaxCheckerBase, SyntaxCheckerBase): """ Provides an interface to check the syntax of a domain. :param str subject: Optional, The subject to work with. """ second_level_checker: Optional[SecondLvlDomainSyntaxChecker] = None subdomain_checker: Optional[SubDomainSyntaxChecker] = None def __init__( self, subject: Optional[str] = None, db_session: Optional[Session] = None ) -> None: self.second_level_checker: SecondLvlDomainSyntaxChecker = ( SecondLvlDomainSyntaxChecker() ) self.subdomain_checker: SubDomainSyntaxChecker = SubDomainSyntaxChecker() self.db_session = db_session super().__init__(subject) def subject_propagator(self) -> "DomainSyntaxChecker": """ Propagate the currently set subject. .. warning:: You are not invited to run this method directly. """ self.second_level_checker.subject = self.idna_subject self.subdomain_checker.subject = self.idna_subject self.status = SyntaxCheckerStatus() self.status.subject_kind = "domain" return super().subject_propagator() @DomainSyntaxCheckerBase.ensure_subject_is_given def is_valid(self) -> bool: """ Validate the given subject if exists. """ return self.is_valid_second_level() or self.is_valid_subdomain() @DomainSyntaxCheckerBase.ensure_subject_is_given def is_valid_second_level(self) -> bool: """ Checks if the given subject is a valid second level demain. """ return self.second_level_checker.is_valid() @DomainSyntaxCheckerBase.ensure_subject_is_given def is_valid_subdomain(self) -> bool: """ Checks if the given subject is a valid subdomain """ return self.subdomain_checker.is_valid() PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/domain_and_ip.py000066400000000000000000000071021467462152100245520ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the domains and IP syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Union from PyFunceble.checker.syntax.base import SyntaxCheckerBase from PyFunceble.checker.syntax.domain import DomainSyntaxChecker from PyFunceble.checker.syntax.ip import IPSyntaxChecker class DomainAndIPSyntaxChecker(SyntaxCheckerBase): """ Provides the interface for checking the syntax of an IP or domain. :param str subject: Optional, The subject to work with. """ @SyntaxCheckerBase.ensure_subject_is_given @SyntaxCheckerBase.update_status_date_after_query def query_status( self, ) -> "DomainAndIPSyntaxChecker": # pragma: no cover ## Just a switch. """ Queries the result without anything more. """ query_object: Union[IPSyntaxChecker, DomainSyntaxChecker] = None ip_checker = IPSyntaxChecker(self.subject) if ip_checker.is_valid(): query_object = ip_checker else: query_object = DomainSyntaxChecker(self.subject, db_session=self.db_session) query_object.platform_query_tool = self.platform_query_tool result = query_object.query_status() self.__dict__.update(query_object.__dict__) return result PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/domain_base.py000066400000000000000000000153551467462152100242430ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all domain syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from typing import Optional, Tuple from PyFunceble.checker.base import CheckerBase from PyFunceble.dataset.iana import IanaDataset from PyFunceble.dataset.public_suffix import PublicSuffixDataset class DomainSyntaxCheckerBase(CheckerBase): """ Provides an interface to check the syntax of a second domain. :param str subject: Optional, The subject to work with. """ # pylint: disable=line-too-long SPECIAL_USE_DOMAIN_NAMES_EXTENSIONS = ["onion"] """ Specifies the extension which are specified as "Special-Use Domain Names" and supported by our project. :type: list .. seealso:: * `RFC6761`_ * `IANA Special-Use Domain Names`_ assignments. * `RFC7686`_ .. _RFC6761: https://tools.ietf.org/html/rfc6761 .. _RFC7686: https://tools.ietf.org/html/rfc6761 .. _IANA Special-Use Domain Names: https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.txt """ last_point_index: Optional[int] = None """ Saves the index of the last point. """ iana_dataset: Optional[IanaDataset] = None public_suffix_dataset: Optional[PublicSuffixDataset] = None def __init__(self, subject: Optional[str] = None) -> None: self.iana_dataset = IanaDataset() self.public_suffix_dataset = PublicSuffixDataset() super().__init__(subject) def reset_last_point_index(func): # pylint: disable=no-self-argument """ Resets the last point index before executing the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): self.last_point_index = None return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def find_last_point_index(func): # pylint: disable=no-self-argument """ Try to find the index of the last point after the execution of the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) # pylint: disable=not-callable self.last_point_index = self.get_last_point_index(self.idna_subject) return result return wrapper @CheckerBase.subject.setter @reset_last_point_index @find_last_point_index def subject(self, value: str): """ Sets the subject to work with. :param value: The subject to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ # pylint: disable=no-member super(DomainSyntaxCheckerBase, self.__class__).subject.fset(self, value) @staticmethod def get_last_point_index(subject: str) -> Optional[int]: """ Provides the index of the last point of the given subject. """ try: if subject.endswith("."): return subject[:-1].rfind(".") return subject.rindex(".") except ValueError: return None def get_subject_without_suffix( self, subject: str, extension: str ) -> Optional[Tuple[Optional[int], Optional[str]]]: """ Provides the given subject without the suffix. :param subject: The subject to work with. :param extension: The extension previously extracted. """ if extension in self.public_suffix_dataset: for suffix in self.public_suffix_dataset.get_available_suffix(extension): try: return subject[: subject.rindex(f".{suffix}")], suffix except ValueError: continue return None, None @CheckerBase.ensure_subject_is_given def get_extension(self) -> Optional[str]: """ Provides the extension to work with (if exists). """ if self.last_point_index is None: return None # Plus one is for the leading point. extension = self.idna_subject[self.last_point_index + 1 :] if extension.endswith("."): extension = extension[:-1] return extension def is_valid(self) -> bool: """ Validate the given subject. """ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/ip.py000066400000000000000000000127401467462152100224050ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the IP (v4 + v6) syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional from PyFunceble.checker.base import CheckerBase from PyFunceble.checker.syntax.base import SyntaxCheckerBase from PyFunceble.checker.syntax.ipv4 import IPv4SyntaxChecker from PyFunceble.checker.syntax.ipv6 import IPv6SyntaxChecker from PyFunceble.checker.syntax.status import SyntaxCheckerStatus class IPSyntaxChecker(SyntaxCheckerBase): """ Provides an interface to check the syntax of an IP (v6 or v4). :param str subject: Optional, The subject to work with. """ ipv4_checker: Optional[IPv4SyntaxChecker] = None ipv6_checker: Optional[IPv6SyntaxChecker] = None def __init__(self, subject: Optional[str] = None) -> None: self.ipv4_checker = IPv4SyntaxChecker() self.ipv6_checker = IPv6SyntaxChecker() super().__init__(subject=subject) def subject_propagator(self) -> "IPSyntaxChecker": """ Propagate the currently set subject. .. warning:: You are not invited to run this method directly. """ self.ipv4_checker.subject = self.idna_subject self.ipv6_checker.subject = self.idna_subject self.status = SyntaxCheckerStatus() self.status.subject_kind = "ip" return super().subject_propagator() @CheckerBase.ensure_subject_is_given def is_valid(self) -> bool: """ Validate the given subject. """ return self.is_valid_v4() or self.is_valid_v6() @CheckerBase.ensure_subject_is_given def is_valid_v4(self) -> bool: """ Checks if the given subject is a valid IPv4. """ return self.ipv4_checker.is_valid() @CheckerBase.ensure_subject_is_given def is_valid_v6(self) -> bool: """ Checks if the given subject is a valid IPv6. """ return self.ipv6_checker.is_valid() @CheckerBase.ensure_subject_is_given def is_valid_range(self) -> bool: """ Checks if the given subject is an IP range. """ return self.is_valid_v4_range() or self.is_valid_v6_range() @CheckerBase.ensure_subject_is_given def is_valid_v4_range(self) -> bool: """ Checks if the given subject is an IPv4 range. """ return self.ipv4_checker.is_valid_range() @CheckerBase.ensure_subject_is_given def is_valid_v6_range(self) -> bool: """ Checks if the given subject is an IPv6 range. """ return self.ipv6_checker.is_valid_range() @CheckerBase.ensure_subject_is_given def is_reserved(self) -> bool: """ Checks if the given subject is a reserved IP. """ return self.is_reserved_v4() or self.is_reserved_v6() @CheckerBase.ensure_subject_is_given def is_reserved_v4(self) -> bool: """ Checks if the given subject is a reserved IPv4. """ return self.ipv4_checker.is_reserved() @CheckerBase.ensure_subject_is_given def is_reserved_v6(self) -> bool: """ Checks if the given subject is a reserved IPv6. """ return self.ipv6_checker.is_reserved() PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/ipv4.py000066400000000000000000000175631467462152100226670ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the IPv4 syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 ipaddress from PyFunceble.checker.base import CheckerBase from PyFunceble.helpers.regex import RegexHelper class IPv4SyntaxChecker(CheckerBase): """ Provides an interface to check the syntax of an IPv4. :param str subject: Optional, The subject to work with. """ @staticmethod def _get_regex_reserved_ip() -> str: """ Provides the regex to use to match all known reserved IPv4. """ # pylint: disable=line-too-long reserved = [ # Match 0.0.0.0โ€“0.255.255.255 r"(0\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 10.0.0.0โ€“10.255.255.255 r"(10\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 100.64.0.0โ€“100.127.255.255 r"(100\.(0?6[4-9]|0?[7-9][0-9]|1[0-1][0-9]|12[0-7])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 127.0.0.0โ€“127.255.255.255 r"(127\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 169.254.0.0โ€“169.254.255.255 r"(169\.254\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 172.16.0.0โ€“172.31.255.255 r"(172\.(0?1[6-9]|0?2[0-9]|0?3[0-1])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 192.0.0.0โ€“192.0.0.255 r"(192\.0\.0\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 192.0.2.0โ€“192.0.2.255 r"(192\.0\.2\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 192.31.196.0โ€“192.31.196.255 r"(192\.31\.196\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 192.52.193.0โ€“192.52.193.255 r"(192\.52\.193\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 192.88.99.0โ€“192.88.99.255 r"(192\.88\.99\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 192.168.0.0โ€“192.168.255.255 r"(192\.168\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 192.175.48.0-192.175.48.255 r"(192\.175\.48\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))", # Match 198.18.0.0โ€“198.19.255.255 r"(198\.(0?1[8-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 198.51.100.0โ€“198.51.100.255 r"(198\.51\.100\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 203.0.113.0โ€“203.0.113.255 r"(203\.0\.113\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 224.0.0.0โ€“239.255.255.255 r"((22[4-9]|23[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 240.0.0.0โ€“255.255.255.254 r"((24[0-9]|25[0-5])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[0-9]{1,}\/[0-9]{1,}))", # Match 255.255.255.255 r"(255\.255\.255\.255)", ] # pylint: enable=enable-too-long return "({0})".format("|".join(reserved)) @CheckerBase.ensure_subject_is_given def is_valid(self) -> bool: """ Validate the given subject. """ try: try: return ipaddress.ip_address(self.idna_subject).version == 4 except ValueError: try: return ipaddress.ip_interface(self.idna_subject).version == 4 except ValueError: return ( ipaddress.ip_network(self.idna_subject, strict=False).version == 4 ) except ValueError: return False @CheckerBase.ensure_subject_is_given def is_valid_range(self) -> bool: """ Checks if the given subject is an IPv4 range """ if self.is_valid() and "/" in self.idna_subject: return 0 <= int(self.idna_subject[self.idna_subject.rfind("/") + 1 :]) <= 32 return False @CheckerBase.ensure_subject_is_given def is_reserved(self) -> bool: """ Checks if the given subject is a reserved IPv4. """ if self.is_valid(): try: address = ipaddress.IPv4Address(self.idna_subject) return ( address.is_multicast or address.is_private or address.is_unspecified or address.is_reserved or address.is_loopback or address.is_link_local or not address.is_global or RegexHelper(self._get_regex_reserved_ip()).match( self.idna_subject, return_match=False ) ) except ValueError: pass return False PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/ipv6.py000066400000000000000000000104441467462152100226600ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the IPv6 syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 ipaddress from PyFunceble.checker.base import CheckerBase class IPv6SyntaxChecker(CheckerBase): """ Provides an interface to check the syntax of an IPv6. :param str subject: Optional, The subject to work with. """ @CheckerBase.ensure_subject_is_given def is_valid(self) -> bool: """ Validate the given subject. """ try: try: return ipaddress.ip_address(self.idna_subject).version == 6 except ValueError: try: return ipaddress.ip_interface(self.idna_subject).version == 6 except ValueError: return ( ipaddress.ip_network(self.idna_subject, strict=False).version == 6 ) except ValueError: return False @CheckerBase.ensure_subject_is_given def is_valid_range(self) -> bool: """ Checks if the given subject is an IPv6 range. """ if self.is_valid() and "/" in self.idna_subject: return ( 0 <= int(self.idna_subject[self.idna_subject.rfind("/") + 1 :]) <= 128 ) return False @CheckerBase.ensure_subject_is_given def is_reserved(self) -> bool: """ Checks if the given subject is a reserved IPv6. """ if self.is_valid(): try: address = ipaddress.IPv6Address(self.idna_subject) return ( address.is_multicast or address.is_private or address.is_unspecified or address.is_reserved or address.is_loopback or address.is_link_local or not address.is_global ) except ipaddress.AddressValueError: pass return False PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/params.py000066400000000000000000000053611467462152100232610ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our parameter class. The parameter class is the class that will be provided to end-user. It is only a placeholder and should only be taken as informative. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 dataclasses from PyFunceble.checker.params_base import CheckerParamsBase @dataclasses.dataclass class SyntaxCheckerParams(CheckerParamsBase): """ Provides the description of a syntax checker paramaters. """ PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/second_lvl_domain.py000066400000000000000000000111641467462152100254530ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the second level domain syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional from PyFunceble.checker.syntax.domain_base import DomainSyntaxCheckerBase from PyFunceble.helpers.regex import RegexHelper class SecondLvlDomainSyntaxChecker(DomainSyntaxCheckerBase): """ Provides an interface to check the syntax of a second domain. :param str subject: Optional, The subject to work with. """ # pylint: disable=line-too-long REGEX_VALID_DOMAIN: str = ( r"^(?=.{0,253}$)(([a-z0-9][a-z0-9-]{0,61}[a-z0-9]|[a-z0-9])\.)+((?=.*[^0-9])([a-z0-9][a-z0-9-]{0,61}[a-z0-9](?:\.)?|[a-z0-9](?:\.)?))$" ) REGEX_VALID_RELAXED_DOMAIN: str = ( r"^(?=.{0,253}$)(([a-z0-9][a-z0-9_-]{0,61}[a-z0-9_-]|[a-z0-9])\.)+((?=.*[^0-9])([a-z0-9][a-z0-9-]{0,61}[a-z0-9](?:\.)?|[a-z0-9](?:\.)?))$" ) last_point_index: Optional[int] = None """ Saves the index of the last point. """ @DomainSyntaxCheckerBase.ensure_subject_is_given def is_valid(self) -> bool: """ Validate the given subject. .. warning:: A valid domain may also be a valid subdomain. If you precisely want to check a subdomain please refer to the right checker (not this one :-) )! """ # pylint: disable=too-many-return-statements extension = self.get_extension() if not extension or ( extension not in self.iana_dataset and extension not in self.SPECIAL_USE_DOMAIN_NAMES_EXTENSIONS ): return False subject_without_extension = self.idna_subject[: self.last_point_index] subject_without_suffix, _ = self.get_subject_without_suffix( self.idna_subject, extension ) if subject_without_suffix: if "." in subject_without_suffix: return False return RegexHelper(self.REGEX_VALID_DOMAIN).match( self.idna_subject, return_match=False ) or RegexHelper(self.REGEX_VALID_RELAXED_DOMAIN).match( self.idna_subject, return_match=False ) if "." in subject_without_extension: return False return RegexHelper(self.REGEX_VALID_DOMAIN).match( self.idna_subject, return_match=False ) PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/status.py000066400000000000000000000061311467462152100233150ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our status class. The status class is the class that will be provided to end-user. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 dataclasses from typing import Optional import PyFunceble.storage from PyFunceble.checker.status_base import CheckerStatusBase @dataclasses.dataclass class SyntaxCheckerStatus(CheckerStatusBase): """ Provides the description of a syntax check status. """ checker_type: Optional[str] = "SYNTAX" def is_valid(self) -> bool: """ Checks if the current status is valid. """ return self.status == PyFunceble.storage.STATUS.valid def is_invalid(self) -> bool: """ Checks if the current status is invalid. """ return self.status == PyFunceble.storage.STATUS.invalid PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/subdomain.py000066400000000000000000000102371467462152100237550ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the subdomain syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.checker.syntax.domain_base import DomainSyntaxCheckerBase from PyFunceble.helpers.regex import RegexHelper class SubDomainSyntaxChecker(DomainSyntaxCheckerBase): """ Provides an interface to check the syntax of a subdomain. :param str subject: Optional, The subject to work with. """ # pylint: disable=line-too-long REGEX_VALID_SUBDOMAIN: str = ( r"^(?=.{0,253}$)(([a-z0-9_][a-z0-9-_]{0,61}[a-z0-9_-]|[a-z0-9])\.)+((?=.*)([a-z0-9][a-z0-9-]{0,61}[a-z0-9](?:\.)?|[a-z0-9](?:\.)?))$" ) @DomainSyntaxCheckerBase.ensure_subject_is_given def is_valid(self) -> bool: """ Validate the given subject if exists. """ extension = self.get_extension() if ( not extension or extension not in self.iana_dataset and extension not in self.SPECIAL_USE_DOMAIN_NAMES_EXTENSIONS ): return False subject_without_extension = self.idna_subject[: self.last_point_index] subject_without_suffix, suffix = self.get_subject_without_suffix( self.idna_subject, extension ) if subject_without_suffix: if suffix.count(".") >= 2: return RegexHelper(self.REGEX_VALID_SUBDOMAIN).match( subject_without_extension, return_match=False ) if "." in subject_without_suffix: return RegexHelper(self.REGEX_VALID_SUBDOMAIN).match( self.idna_subject, return_match=False ) return False if "." in subject_without_extension: return RegexHelper(self.REGEX_VALID_SUBDOMAIN).match( subject_without_extension, return_match=False ) return False PyFunceble-4.2.29.dev/PyFunceble/checker/syntax/url.py000066400000000000000000000102731467462152100225760ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the URL syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 urllib.parse from typing import Optional from PyFunceble.checker.base import CheckerBase from PyFunceble.checker.syntax.base import SyntaxCheckerBase from PyFunceble.checker.syntax.domain import DomainSyntaxChecker from PyFunceble.checker.syntax.ip import IPSyntaxChecker class URLSyntaxChecker(SyntaxCheckerBase): """ Provides an interface to check the syntax of a URL. :param str subject: Optional, The subject to work with. """ def subject_propagator(self) -> CheckerBase: self.status.subject_kind = "url" return super().subject_propagator() @staticmethod def get_hostname_from_url(url: str) -> Optional[str]: """ Extract the hostname part of the given URL. .. versionadded:: 4.1.0b7 """ parsed = urllib.parse.urlparse(url) if not parsed.scheme or not parsed.netloc: return None if parsed.hostname: if parsed.hostname != parsed.netloc: hostname = parsed.hostname else: hostname = parsed.netloc else: ## pragma: no cover ## Safety check. hostname = parsed.netloc return hostname @CheckerBase.ensure_subject_is_given def is_valid(self) -> bool: """ Validate the given subject. .. versionchanged:: 4.1.0b5.dev URL with scheme and port are no longer :code:`INVALID`. .. versionchanged:: 4.1.0b7.dev Hostname taken from :code:`get_hostname_from_url` """ hostname = self.get_hostname_from_url(self.idna_subject) if not hostname: return False if ( DomainSyntaxChecker(hostname).is_valid() or IPSyntaxChecker(hostname).is_valid() ): return True return False PyFunceble-4.2.29.dev/PyFunceble/checker/utils/000077500000000000000000000000001467462152100212315ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/checker/utils/__init__.py000066400000000000000000000046301467462152100233450ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some utilities related to the checkers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/checker/utils/whois.py000066400000000000000000000077311467462152100227440ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some utilities related to the WHOIS query. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional, Union from sqlalchemy.orm import Session import PyFunceble.facility import PyFunceble.storage from PyFunceble.dataset.base import DatasetBase from PyFunceble.dataset.csv_base import CSVDatasetBase from PyFunceble.dataset.db_base import DBDatasetBase from PyFunceble.dataset.whois.csv import CSVWhoisDataset from PyFunceble.dataset.whois.sql import SQLDBWhoisDataset def get_whois_dataset_object( *, db_session: Optional[Session] = None ) -> Union[DatasetBase, CSVDatasetBase, DBDatasetBase]: """ Provides the whois dataset object to work with. :param db_session: A database session to use. :raise ValueError: When the given database type is unkown. :raise RuntimeError: When the configuration was not loaded yet. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): result = None if PyFunceble.storage.CONFIGURATION.cli_testing.db_type == "csv": result = CSVWhoisDataset() elif PyFunceble.storage.CONFIGURATION.cli_testing.db_type in ( "mariadb", "mysql", "postgresql", ): result = SQLDBWhoisDataset(db_session=db_session) if result: result.set_authorized( bool(PyFunceble.storage.CONFIGURATION.cli_testing.whois_db) ) return result raise ValueError( " " f"({PyFunceble.storage.CONFIGURATION.cli_testing.db_type}) is unknown." ) raise RuntimeError("Configuration not loaded yet.") PyFunceble-4.2.29.dev/PyFunceble/cli/000077500000000000000000000000001467462152100172345ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/__init__.py000066400000000000000000000046251467462152100213540ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the CLI usage. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/continuous_integration/000077500000000000000000000000001467462152100240455ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/continuous_integration/__init__.py000066400000000000000000000047051467462152100261640ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything we may need for continuous integration aka autosaving and auto commiting. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/continuous_integration/base.py000066400000000000000000001156541467462152100253450ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our CI classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: disable=too-many-lines import datetime import functools import secrets from typing import Any, List, Optional import PyFunceble.cli.continuous_integration.exceptions import PyFunceble.facility import PyFunceble.storage from PyFunceble.helpers.command import CommandHelper from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper from PyFunceble.helpers.regex import RegexHelper class ContinuousIntegrationBase: """ Provides the base of all continuous integration methods. :param authorized: The authorization to run. :param git_email: The email to apply while initilizing the git repository for push. :param git_name: The name to apply while initilizing the git repository for push. :param git_branch: The branch to use while testing. :param git_distribution_branch: The branch to push the results into. :param token: The token to apply while initilizing the git repository for push. :param command: The command to execute before each push (except the latest one). :param end_command: The commant to execute at the very end. :param commit_message: The commit message to apply before each push (except the latest one). :param end_commit_message: The commit message to apply at the very end. :param max_exec_minutes: The maximum of minutes to apply before considering the current session as finished. """ STD_AUTHORIZED: bool = False STD_GIT_EMAIL: Optional[str] = None STD_GIT_NAME: Optional[str] = None STD_GIT_BRANCH: Optional[str] = "master" STD_GIT_DISTRIBUTION_BRANCH: Optional[str] = "master" STD_COMMAND: Optional[str] = None STD_END_COMMAND: Optional[str] = None STD_COMMIT_MESSAGE: str = "PyFunceble - AutoSave" STD_END_COMMIT_MESSAGE: str = "PyFunceble - Results" STD_MAX_EXEC_MINUTES: int = 15 COMMON_CI_SKIP_MARKER: List[str] = ["[skip ci]", "[ci skip]", "[no ci]"] end_commit_marker: str = "[ci skip]" _authorized: bool = False _git_email: Optional[str] = None _git_name: Optional[str] = None _git_branch: Optional[str] = None _git_distribution_branch: Optional[str] = None _token: Optional[str] = None _command: Optional[str] = None _end_command: Optional[str] = None _commit_message: Optional[str] = None _end_commit_message: Optional[str] = None _max_exec_minutes: Optional[int] = None start_time: Optional[datetime.datetime] = None expected_end_time: Optional[datetime.datetime] = None git_initialized: bool = False def __init__( self, *, authorized: Optional[bool] = None, git_email: Optional[str] = None, git_name: Optional[str] = None, git_branch: Optional[str] = None, git_distribution_branch: Optional[str] = None, token: Optional[str] = None, command: Optional[str] = None, end_command: Optional[str] = None, commit_message: Optional[str] = None, end_commit_message: Optional[str] = None, max_exec_minutes: Optional[int] = None, ) -> None: if authorized is not None: self.authorized = authorized else: self.guess_and_set_authorized() if git_email is not None: self.git_email = git_email else: self.guess_and_set_git_email() if git_name is not None: self.git_name = git_name else: self.guess_and_set_git_name() if git_branch is not None: self.git_branch = git_branch else: self.guess_and_set_git_branch() if git_distribution_branch is not None: self.git_distribution_branch = git_distribution_branch else: self.guess_and_set_git_distribution_branch() if token is not None: self.token = token else: self.guess_and_set_token() if command is not None: self.command = command else: self.guess_and_set_command() if end_command is not None: self.end_command = end_command else: self.guess_and_set_end_command() if commit_message is not None: self.commit_message = commit_message else: self.guess_and_set_commit_message() if end_commit_message is not None: self.end_commit_message = end_commit_message else: self.guess_and_set_end_commit_message() if max_exec_minutes is not None: self.max_exec_minutes = max_exec_minutes else: self.guess_and_set_max_exec_minutes() def execute_if_authorized(default: Any = None): # pylint: disable=no-self-argument """ Executes the decorated method only if we are authorized to process. Otherwise, apply the given :code:`default`. """ def inner_metdhod(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.authorized: return func(self, *args, **kwargs) # pylint: disable=not-callable return self if default is None else default return wrapper return inner_metdhod def ensure_git_email_is_given(func): # pylint: disable=no-self-argument """ Ensures that the Git Email is given before launching the decorated method. :raise PyFunceble.cli.continuous_integration.exceptions.GitEmailNotFound: When the Git Email is not found. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not self.git_email: # pylint: disable=line-too-long raise PyFunceble.cli.continuous_integration.exceptions.GitEmailNotFound() return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def ensure_git_name_is_given(func): # pylint: disable=no-self-argument """ Ensures that the Git Name is given before launching the decorated method. :raise PyFunceble.cli.continuous_integration.exceptions.GitNameNotFound: When the Git Name is not found. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not self.git_name: raise PyFunceble.cli.continuous_integration.exceptions.GitNameNotFound() return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def ensure_git_branch_is_given(func): # pylint: disable=no-self-argument """ Ensures that the Git Branch is given before launching the decorated method. :raise PyFunceble.cli.continuous_integration.exceptions.GitBranchNotFound: When the Git Branch is not found. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not self.git_name: raise PyFunceble.cli.continuous_integration.exceptions.GitNameNotFound() return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def ensure_git_distribution_branch_is_given( func, ): # pylint: disable=no-self-argument,line-too-long """ Ensures that the Git distribution Branch is given before launching the decorated method. :raise PyFunceble.cli.continuous_integration.exceptions.GitDistributionBranchNotFound: When the Git distribution Branch is not found. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not self.git_name: raise PyFunceble.cli.continuous_integration.exceptions.GitNameNotFound() return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def ensure_token_is_given(func): # pylint: disable=no-self-argument """ Ensures that the token is given before launching the decorated method. :raise PyFunceble.cli.continuous_integration.exceptions.TokenNotFound: When the token is not found. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not self.token: raise PyFunceble.cli.continuous_integration.exceptions.TokenNotFound() return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def ensure_start_time_is_given(func): # pylint: disable=no-self-argument """ Ensures that the starting time is given before launching the decorated method. :raise PyFunceble.cli.continuous_integration.exceptions.StartTimeNotFound: When the token is not found. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not self.start_time: # pylint: disable=line-too-long raise PyFunceble.cli.continuous_integration.exceptions.StartTimeNotFound() return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @property def authorized(self) -> Optional[bool]: """ Provides the currently state of the :code:`_authorized` attribute. """ return self._authorized @authorized.setter def authorized(self, value: bool) -> None: """ Sets the value of the :code:`authorized` attribute. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool` """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._authorized = value @property def bypass_bypass(self) -> bool: """ Provides the currently state of the :code:`_bypass_bypass` attribute. """ return ( EnvironmentVariableHelper("PYFUNCEBLE_BYPASS_BYPASS").get_value() is not None ) def set_authorized(self, value: bool) -> "ContinuousIntegrationBase": """ Sets the value of the :code:`authorized` attribute. :param value: The value to set. """ self.authorized = value return self @property def git_email(self) -> Optional[str]: """ Provides the currently state of the :code:`_git_email` attribute. """ return self._git_email @git_email.setter def git_email(self, value: str) -> None: """ Sets the Git Email to use. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise valueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._git_email = value def set_git_email(self, value: str) -> "ContinuousIntegrationBase": """ Sets the Git Email to use. :param value: The value to set. """ self.git_email = value return self @property def git_name(self) -> Optional[str]: """ Provides the current state of the :code:`_git_name` attribute. """ return self._git_name @git_name.setter def git_name(self, value: str) -> None: """ Sets the Git Name to use. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise valueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._git_name = value def set_git_name(self, value: str) -> "ContinuousIntegrationBase": """ Sets the Git Name to use. :param value: The value to set. """ self.git_name = value return self @property def git_branch(self) -> Optional[str]: """ Provides the current state of the :code:`_git_branch` attribute. """ return self._git_branch @git_branch.setter def git_branch(self, value: str) -> None: """ Sets the Git Branch to use. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise valueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._git_branch = value def set_git_branch(self, value: str) -> "ContinuousIntegrationBase": """ Sets the Git Branch to use. :param value: The value to set. """ self.git_branch = value return self @property def git_distribution_branch(self) -> Optional[str]: """ Provides the current state of the :code:`_git_distribution_branch` attribute. """ return self._git_distribution_branch @git_distribution_branch.setter def git_distribution_branch(self, value: str) -> None: """ Sets the Git distribution Branch to use. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise valueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._git_distribution_branch = value def set_git_distribution_branch(self, value: str) -> "ContinuousIntegrationBase": """ Sets the Git distribution Branch to use. :param value: The value to set. """ self.git_distribution_branch = value return self @property def token(self) -> Optional[str]: """ Provides the current state of the :code:`_token` attribute. """ return self._token @token.setter def token(self, value: str) -> None: """ Sets the token to use. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise valueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._token = value def set_token(self, value: str) -> "ContinuousIntegrationBase": """ Sets the token to use. :param value: The value to set. """ self.token = value return value @property def command(self) -> Optional[str]: """ Provides the current state of the :code:`_command` attribute. """ return self._command @command.setter def command(self, value: str) -> None: """ Sets the command to work with. :param value: The command to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empy.") self._command = value def set_command(self, value: str) -> "ContinuousIntegrationBase": """ Sets the command to work with. :param value: The command to set. """ self.command = value return self @property def end_command(self) -> Optional[str]: """ Provides the current state of the :code:`_end_command` attribute. """ return self._end_command @end_command.setter def end_command(self, value: str) -> None: """ Sets the command to execute at the really end of the process with. :param value: The command to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empy.") self._end_command = value def set_end_command(self, value: str) -> "ContinuousIntegrationBase": """ Sets the command to execute at the really end of the process with. :param value: The command to set. """ self.end_command = value return self @property def commit_message(self) -> Optional[str]: """ Provides the current state of the :code:`_commit_message` attribute. """ return self._commit_message @commit_message.setter def commit_message(self, value: str) -> None: """ Sets the commit message to apply to all commits except the final one. :param value: The message to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empy.") self._commit_message = value def set_commit_message(self, value: str) -> "ContinuousIntegrationBase": """ Sets the commit message to apply to all commits except the final one. :param value: The message to set. """ self.commit_message = value return self @property def end_commit_message(self) -> Optional[str]: """ Provides the current state of the :code:`_end_commit_message` attribute. """ return self._end_commit_message @end_commit_message.setter def end_commit_message(self, value: str) -> None: """ Sets the commit message to apply to the final one. :param value: The message to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empy.") self._end_commit_message = value def set_end_commit_message(self, value: str) -> "ContinuousIntegrationBase": """ Sets the commit message to apply to the final one. :param value: The command to set. """ self.end_commit_message = value return self @property def max_exec_minutes(self) -> Optional[str]: """ Provides the current state of the :code:`_max_exec_minutes` attribute. """ return self._max_exec_minutes @max_exec_minutes.setter def max_exec_minutes(self, value: str) -> None: """ Sets the maximum waiting time before considering the time as exceeded. :param value: The message to set. :raise TypeError: When the given :code:`value` is not a :py:class:`int`. :raise ValueError: When the given :code:`value` is less than :code:`1`. """ if not isinstance(value, int): raise TypeError(f" should be {int}, {type(value)} given.") if value < 1: raise ValueError(" should be greater or equal to 1.") self._max_exec_minutes = value def set_max_exec_minutes(self, value: str) -> "ContinuousIntegrationBase": """ Sets the maximum waiting time before considering the time as exceeded. :param value: The command to set. """ self._max_exec_minutes = value return self @execute_if_authorized(None) def set_start_time(self) -> "ContinuousIntegrationBase": """ Sets the starting time to now. """ self.start_time = datetime.datetime.now(datetime.timezone.utc) self.expected_end_time = self.start_time + datetime.timedelta( minutes=self.max_exec_minutes ) @staticmethod def get_remote_destination(): """ Provides the remote destination to use. :raise PyFunceble.cli.continuous_integration.exceptions.RemoteURLNotFound: When we could not determine the remote destination. """ regex = r"(?:[a-z]+(?:\s+|\t+))(.*)(?:(?:\s+|\t+)\([a-z]+\))" remote_of_interest = [ x for x in CommandHelper("git remote -v").execute().splitlines() if "(fetch)" in x ][0] filtered = RegexHelper(regex).match( remote_of_interest, return_match=True, group=1 ) if filtered: if "@" in filtered: return filtered[filtered.find("@") + 1 :] if "//" in filtered: return filtered[filtered.find("//") + 2 :] raise PyFunceble.cli.continuous_integration.exceptions.RemoteURLNotFound() @staticmethod def exec_command(command: str, allow_stdout: bool) -> None: """ Exceutes the given command. :param command: The command to execute. :param allow_stdout: Allows us to return the command output to stdout. """ PyFunceble.facility.Logger.debug("Executing %r", command) command_helper = CommandHelper(command) if allow_stdout: command_helper.run_to_stdout() else: command_helper.execute() def guess_and_set_authorized(self) -> "ContinuousIntegrationBase": """ Tries to guess the authorization. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.authorized = bool( PyFunceble.storage.CONFIGURATION.cli_testing.ci.active ) else: self.authorized = self.STD_AUTHORIZED return self def guess_and_set_git_email(self) -> "ContinuousIntegrationBase": """ Tries to guess and set the Git Email. """ environment_var = EnvironmentVariableHelper("GIT_EMAIL") if environment_var.exists(): self.git_email = environment_var.get_value() return self def guess_and_set_git_name(self) -> "ContinuousIntegrationBase": """ Tries to guess and set the Git Name. """ environment_var = EnvironmentVariableHelper("GIT_NAME") if environment_var.exists(): self.git_name = environment_var.get_value() return self def guess_and_set_git_branch(self) -> "ContinuousIntegrationBase": """ Tries to guess and set the Git Branch. """ environment_var = EnvironmentVariableHelper("GIT_BRANCH") if environment_var.exists(): self.git_branch = environment_var.get_value() elif PyFunceble.facility.ConfigLoader.is_already_loaded(): self.git_branch = PyFunceble.storage.CONFIGURATION.cli_testing.ci.branch else: self.git_branch = self.STD_GIT_BRANCH return self def guess_and_set_git_distribution_branch(self) -> "ContinuousIntegrationBase": """ Tries to guess and set the Git distribution Branch. """ environment_var = EnvironmentVariableHelper("GIT_DISTRIBUTION_BRANCH") if environment_var.exists(): self.git_distribution_branch = environment_var.get_value() elif PyFunceble.facility.ConfigLoader.is_already_loaded(): self.git_distribution_branch = ( PyFunceble.storage.CONFIGURATION.cli_testing.ci.distribution_branch ) else: self.git_distribution_branch = self.STD_GIT_DISTRIBUTION_BRANCH return self def guess_and_set_token(self) -> "ContinuousIntegrationBase": """ Tries to guess and set the token. """ raise NotImplementedError() def guess_and_set_command(self) -> "ContinuousIntegrationBase": """ Tries to guess and set the command to execute. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if PyFunceble.storage.CONFIGURATION.cli_testing.ci.command: self.command = PyFunceble.storage.CONFIGURATION.cli_testing.ci.command return self def guess_and_set_end_command(self) -> "ContinuousIntegrationBase": """ Tries to guess and set the command to execute at the very end. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if PyFunceble.storage.CONFIGURATION.cli_testing.ci.end_command: self.end_command = ( PyFunceble.storage.CONFIGURATION.cli_testing.ci.end_command ) return self def guess_and_set_commit_message(self) -> "ContinuousIntegrationBase": """ Tries to guess and set the commit message to apply. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if PyFunceble.storage.CONFIGURATION.cli_testing.ci.commit_message: self.commit_message = ( PyFunceble.storage.CONFIGURATION.cli_testing.ci.commit_message ) else: self.commit_message = self.STD_COMMIT_MESSAGE else: self.commit_message = self.STD_COMMIT_MESSAGE return self def guess_and_set_end_commit_message(self) -> "ContinuousIntegrationBase": """ Tries to guess and set the commit message to apply at the very end. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if PyFunceble.storage.CONFIGURATION.cli_testing.ci.end_commit_message: self.end_commit_message = ( PyFunceble.storage.CONFIGURATION.cli_testing.ci.end_commit_message ) else: self.end_commit_message = self.STD_END_COMMIT_MESSAGE else: self.end_commit_message = self.STD_END_COMMIT_MESSAGE return self def guess_and_set_max_exec_minutes(self) -> "ContinuousIntegrationBase": """ Tries to guess and set the maximum execution time. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.max_exec_minutes = ( PyFunceble.storage.CONFIGURATION.cli_testing.ci.max_exec_minutes ) else: self.max_exec_minutes = self.STD_MAX_EXEC_MINUTES return self def guess_all_settings(self) -> "ContinuousIntegrationBase": """ Try to guess all settings. """ to_ignore = ["guess_all_settings"] for method in dir(self): if method in to_ignore or not method.startswith("guess_"): continue getattr(self, method)() return self def is_authorized(self) -> bool: """ Checks if the current object is authorized to run. """ return self.authorized is True @execute_if_authorized(False) @ensure_start_time_is_given def is_time_exceeded(self) -> bool: """ Checks if we exceeded the allocated time we have. """ return self.expected_end_time < datetime.datetime.now(datetime.timezone.utc) @execute_if_authorized(None) @ensure_token_is_given def init_git_remote_with_token(self) -> "ContinuousIntegrationBase": """ Initiates the git remote URL with the help of the given token. """ remote = self.get_remote_destination() # Each entries should have a tuple containing the command to run and # if we are authorized to print to STDOUT. commands_to_execute = [ ("git remote rm origin", False), ("git remote add origin " f"https://{self.token}@{remote}", False), ("git remote update", False), ("git fetch", False), ] for command, allow_stdout in commands_to_execute: self.exec_command(command, allow_stdout) return self @execute_if_authorized(None) @ensure_git_name_is_given @ensure_git_email_is_given @ensure_git_branch_is_given @ensure_git_distribution_branch_is_given def init_git(self) -> "ContinuousIntegrationBase": """ Initiate the git repository. """ PyFunceble.facility.Logger.info("Started initialization of GIT.") if self.token: self.init_git_remote_with_token() commands = [ (f'git config --local user.email "{self.git_email}"', False), (f'git config --local user.name "{self.git_name}"', False), ("git config --local push.default simple", False), ("git config --local pull.rebase true", False), ("git config --local core.autocrlf true", False), ("git config --local branch.autosetuprebase always", False), (f'git checkout "{self.git_branch}"', False), ("git fetch origin", False), ( f"git rebase -X theirs " f"origin/{self.git_distribution_branch}", False, ), ] for command, allow_stdout in commands: self.exec_command(command, allow_stdout) self.git_initialized = True PyFunceble.facility.Logger.info("Finished initialization of GIT.") return self def fix_permissions(self) -> "ContinuousIntegrationBase": """ A method to overwrite when custom rules for permissions are needed. .. note:: This method is automatically called by the methods who apply commits. """ return self @execute_if_authorized(None) def push_changes(self, branch: str, *, exit_it: bool = True) -> None: """ Pushes the changes. :param branch: The branch to push. :param exit_it: Exits after the push ? :raise PyFunceble.cli.continuous_integration.exceptions.StopExecution: When the :code:`exit_it` is set to :code:`True`. """ PyFunceble.facility.Logger.info("Started to push GIT changes.") commands = [] if self.git_initialized: commands.extend( [ ( f'git checkout "{branch}"', True, ), ("git fetch origin", True), (f"git rebase -X theirs origin/{branch}", True), (f"git push origin {branch}", True), ] ) for command, allow_stdout in commands: self.exec_command(command, allow_stdout) PyFunceble.facility.Logger.info("Finished to push GIT changes.") if exit_it: raise PyFunceble.cli.continuous_integration.exceptions.StopExecution() @execute_if_authorized(None) def apply_end_commit(self, *, push: bool = True) -> None: """ Apply the "end" commit and push. Side effect: It runs the declared command to execute. :param push: Whether we should push the changes or not. """ PyFunceble.facility.Logger.info( "Started to prepare and apply final GIT commit." ) self.fix_permissions() commands = [] if self.git_distribution_branch != self.git_branch: branch_to_use = self.git_distribution_branch else: branch_to_use = self.git_branch if self.end_command: commands.append((self.end_command, True)) if self.git_initialized: commands.extend( [ ("git fetch origin", True), ( f"git rebase -X theirs origin/{branch_to_use}", True, ), ("git add --all", True), ( "git commit -a -m " f'"{self.end_commit_message} {self.end_commit_marker}\n\n' f'{secrets.token_urlsafe(18)}"', True, ), ] ) for command, allow_stdout in commands: self.exec_command(command, allow_stdout) if self.end_command: # Fix permissions because we met some strange behaviors in the past. self.fix_permissions() PyFunceble.facility.Logger.info( "Finished to prepare and apply final GIT commit." ) if push: self.push_changes(branch_to_use) @execute_if_authorized(None) def apply_commit(self, *, push: bool = True) -> None: """ Apply the commit and push. Side effect: It runs the declared command to execute. :param push: Whether we should push the changes or not. """ PyFunceble.facility.Logger.info("Started to prepare and apply GIT commit.") self.fix_permissions() commands = [] if self.command: commands.append((self.command, True)) if self.git_initialized: commands.extend( [ ("git add --all", True), ( "git commit -a -m " f'"{self.commit_message}\n\n' f'{secrets.token_urlsafe(18)}"', True, ), ] ) for command, allow_stdout in commands: self.exec_command(command, allow_stdout) if self.command: # Fix permissions because we met some strange behaviors in the past. self.fix_permissions() PyFunceble.facility.Logger.info("Finished to prepare and apply GIT commit.") if push: self.push_changes(self.git_branch) @execute_if_authorized(None) def bypass(self) -> None: """ Stops everything if the latest commit message match any of those: - :code:`[PyFunceble skip]` (case insensitive) - :code:`[PyFunceble-skip]` (case insensitive) - :code:`[skip-PyFunceble]` (case insensitive) - :code:`[skip PyFunceble]` (case insensitive) - :attr:`~PyFunceble.cli.continuous_integration.base.end_commit_marker` - :attr:`~PyFunceble.cli.continuous_integration.base.COMMON_CI_SKIP_MARKER` """ our_marker = self.COMMON_CI_SKIP_MARKER + [ "[pyfunceble skip]", "[pyfunceble-skip]", "[skip-pyfunceble]", "[skip pyfunceble]", self.end_commit_marker, ] latest_commit = CommandHelper("git log -1").execute().lower() if not self.bypass_bypass and any( x.lower() in latest_commit for x in our_marker ): PyFunceble.facility.Logger.info( "Bypass marker caught. Saving and stopping process." ) raise PyFunceble.cli.continuous_integration.exceptions.StopExecution() @execute_if_authorized(None) def init(self) -> "ContinuousIntegrationBase": """ Initiate our infrastructure for the current CI engine. The purpose of this method is to be able to have some custom init based on the CI we are currently on. The init method should be manually started before runing any further action. .. warning:: We assume that we are aware that you should run this method first. """ PyFunceble.facility.Logger.info("Started initizalization of workflow.") self.init_git() PyFunceble.facility.Logger.info("Finished initizalization of workflow.") return self PyFunceble-4.2.29.dev/PyFunceble/cli/continuous_integration/exceptions.py000066400000000000000000000072111467462152100266010ustar00rootroot00000000000000# pylint:disable=line-too-long """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the exception related to the CI integration. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.exceptions class ContinuousIntegrationException(PyFunceble.exceptions.PyFuncebleException): """ Describes an exception related to the continuous integration. """ class TokenNotFound(ContinuousIntegrationException): """ Describes a missing (Git?(lab|hub)) Token. """ class RemoteURLNotFound(ContinuousIntegrationException): """ Describes a missing or unknown remote URL. """ class GitBranchNotFound(ContinuousIntegrationException): """ Describes a missing git branch. """ class GitDistributionBranchNotFound(ContinuousIntegrationException): """ Describes a missing git distribution branch. """ class GitEmailNotFound(ContinuousIntegrationException): """ Describes a missing Git Email. """ class GitNameNotFound(ContinuousIntegrationException): """ Describes a missing Git Name. """ class StopExecution(ContinuousIntegrationException): """ Informs upstream - or interacting interface - that we pushed the changes and that they need stop everything they plan to do with PyFunceble. """ class StartTimeNotFound(ContinuousIntegrationException): """ Describes a missing start time. """ PyFunceble-4.2.29.dev/PyFunceble/cli/continuous_integration/github_actions.py000066400000000000000000000075631467462152100274340ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the CI engine and detection tool for the GitHub Actions. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.facility from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper class GitHubActions(ContinuousIntegrationBase): """ Provides the interface which detects and work under the GitHub Actions infrastructure. """ end_commit_marker: str = "[GHA skip]" def guess_and_set_authorized(self) -> "GitHubActions": """ Tries to guess the authorization. """ needed_environment_vars = ["GITHUB_ACTIONS"] if PyFunceble.facility.ConfigLoader.is_already_loaded(): if bool(PyFunceble.storage.CONFIGURATION.cli_testing.ci.active): self.authorized = all( EnvironmentVariableHelper(x).exists() for x in needed_environment_vars ) else: super().guess_and_set_authorized() elif all( EnvironmentVariableHelper(x).exists() for x in needed_environment_vars ): self.authorized = True else: super().guess_and_set_authorized() return self def guess_and_set_token(self) -> "GitHubActions": """ Tries to guess and set the token. """ environment_var = EnvironmentVariableHelper("GITHUB_TOKEN") if environment_var.exists(): self.token = environment_var.get_value() return self PyFunceble-4.2.29.dev/PyFunceble/cli/continuous_integration/gitlab_ci.py000066400000000000000000000102571467462152100263410ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the CI engine and detection tool for the GitLab CI. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.facility from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper class GitLabCI(ContinuousIntegrationBase): """ Provides the interface which detects and work under the GitLab CI infrastructure. """ def guess_and_set_authorized(self) -> "GitLabCI": """ Tries to guess the authorization. """ needed_environment_vars = ["GITLAB_CI", "GITLAB_USER_ID"] if PyFunceble.facility.ConfigLoader.is_already_loaded(): if bool(PyFunceble.storage.CONFIGURATION.cli_testing.ci.active): self.authorized = all( EnvironmentVariableHelper(x).exists() for x in needed_environment_vars ) else: super().guess_and_set_authorized() elif all( EnvironmentVariableHelper(x).exists() for x in needed_environment_vars ): self.authorized = True else: super().guess_and_set_authorized() return self def guess_and_set_token(self) -> "GitLabCI": """ Tries to guess and set the token. """ environment_var = EnvironmentVariableHelper("GL_TOKEN") if environment_var.exists(): self.token = environment_var.get_value() return self @ContinuousIntegrationBase.execute_if_authorized(None) @ContinuousIntegrationBase.ensure_token_is_given def init_git_remote_with_token(self) -> "GitLabCI": """ Initiates the git remote URL with the help of the given token. """ self.token = f"oauth2:{self.token}" super().init_git_remote_with_token() return self PyFunceble-4.2.29.dev/PyFunceble/cli/continuous_integration/jenkins.py000066400000000000000000000074651467462152100260740ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the CI engine and detection tool for Jenkins. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.facility from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper class Jenkins(ContinuousIntegrationBase): """ Provides the interface which detects and work under several Jenkins infrastructure. """ def guess_and_set_authorized(self) -> "Jenkins": """ Tries to guess the authorization. """ needed_environment_vars = ["JENKINS_URL", "JENKINS_HOME"] if PyFunceble.facility.ConfigLoader.is_already_loaded(): if bool(PyFunceble.storage.CONFIGURATION.cli_testing.ci.active): self.authorized = all( EnvironmentVariableHelper(x).exists() for x in needed_environment_vars ) else: super().guess_and_set_authorized() elif all( EnvironmentVariableHelper(x).exists() for x in needed_environment_vars ): self.authorized = True else: super().guess_and_set_authorized() return self def guess_and_set_token(self) -> "Jenkins": """ Tries to guess and set the token. """ environment_var = EnvironmentVariableHelper("GITHUB_TOKEN") if environment_var.exists(): self.token = environment_var.get_value() return self PyFunceble-4.2.29.dev/PyFunceble/cli/continuous_integration/standalone.py000066400000000000000000000103351467462152100265510ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the CI engine and detection tool for standalone instances. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.cli.continuous_integration.exceptions import PyFunceble.facility from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper class Standalone(ContinuousIntegrationBase): """ Provides a standalone interface which let end-user run PyFunceble in a standalone environment, without any GIT related CI/CD stuff. """ def guess_and_set_authorized(self) -> "Standalone": """ Tries to guess the authorization. """ needed_environment_vars = ["PYFUNCEBLE_STANDALONE_CI"] if all(EnvironmentVariableHelper(x).exists() for x in needed_environment_vars): self.authorized = True elif PyFunceble.facility.ConfigLoader.is_already_loaded(): if bool(PyFunceble.storage.CONFIGURATION.cli_testing.ci.active): self.authorized = all( EnvironmentVariableHelper(x).exists() for x in needed_environment_vars ) else: super().guess_and_set_authorized() else: super().guess_and_set_authorized() return self def guess_and_set_token(self) -> "Standalone": return self @ContinuousIntegrationBase.execute_if_authorized(None) def init_git(self) -> ContinuousIntegrationBase: return self @ContinuousIntegrationBase.execute_if_authorized(None) def bypass(self) -> None: return None @ContinuousIntegrationBase.execute_if_authorized(None) def init_git_remote_with_token(self) -> "Standalone": return self @ContinuousIntegrationBase.execute_if_authorized(None) def apply_commit(self, *, push: bool = True) -> None: return super().apply_end_commit(push=push) PyFunceble-4.2.29.dev/PyFunceble/cli/continuous_integration/travis_ci.py000066400000000000000000000074551467462152100264150ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the CI engine and detection tool for the Travis CI. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.facility from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper class TravisCI(ContinuousIntegrationBase): """ Provides the interface which detects and work under the Travis CI infrastructure. """ def guess_and_set_authorized(self) -> "TravisCI": """ Tries to guess the authorization. """ needed_environment_vars = ["TRAVIS_BUILD_DIR"] if PyFunceble.facility.ConfigLoader.is_already_loaded(): if bool(PyFunceble.storage.CONFIGURATION.cli_testing.ci.active): self.authorized = all( EnvironmentVariableHelper(x).exists() for x in needed_environment_vars ) else: super().guess_and_set_authorized() elif all( EnvironmentVariableHelper(x).exists() for x in needed_environment_vars ): self.authorized = True else: super().guess_and_set_authorized() return self def guess_and_set_token(self) -> "TravisCI": """ Tries to guess and set the token. """ environment_var = EnvironmentVariableHelper("GH_TOKEN") if environment_var.exists(): self.token = environment_var.get_value() return self PyFunceble-4.2.29.dev/PyFunceble/cli/continuous_integration/utils.py000066400000000000000000000071451467462152100255660ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some utilities related to the CI. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.facility from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase from PyFunceble.cli.continuous_integration.github_actions import GitHubActions from PyFunceble.cli.continuous_integration.gitlab_ci import GitLabCI from PyFunceble.cli.continuous_integration.jenkins import Jenkins from PyFunceble.cli.continuous_integration.standalone import Standalone from PyFunceble.cli.continuous_integration.travis_ci import TravisCI def ci_object(*args, **kwargs) -> ContinuousIntegrationBase: """ A placeholder which provides the CI object to use. """ known_objects = [Jenkins, GitHubActions, TravisCI, GitLabCI, Standalone] result = None for known in known_objects: result = known(*args, **kwargs) result.guess_all_settings() PyFunceble.facility.Logger.debug("Checking if %r is authorized.", result) if result.is_authorized(): PyFunceble.facility.Logger.debug( "%r is authorized. Using it as CI object.", result ) return result PyFunceble.facility.Logger.debug( "No known CI object authorized. Using: %r", known_objects[0] ) return known_objects[0](*args, **kwargs) PyFunceble-4.2.29.dev/PyFunceble/cli/credential_loader.py000066400000000000000000000245401467462152100232530ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our credential loader. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from getpass import getpass from typing import Any, Optional import PyFunceble.cli.factory import PyFunceble.facility import PyFunceble.storage from PyFunceble.database.credential.base import CredentialBase from PyFunceble.database.credential.mariadb import MariaDBCredential from PyFunceble.database.credential.mysql import MySQLCredential from PyFunceble.database.credential.postgresql import PostgreSQLCredential from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper class CredentialLoader: """ Provides our creadential loader. The idea is to have an interface which provides the credential to use but at the same time load and initiate the credential interface after loading it from the user input or the environment variables. :param db_type: The database type to load the credential for. """ DB_TYPE2OBJ: dict = { "csv": None, "mysql": MySQLCredential, "mariadb": MariaDBCredential, "postgresql": PostgreSQLCredential, } credential: Optional[CredentialBase] = None """ The credential (itself). """ _db_type: Optional[str] = None def __init__(self, db_type: Optional[str] = None) -> None: if db_type is not None: self.db_type = db_type elif PyFunceble.facility.ConfigLoader.is_already_loaded(): self.db_type = PyFunceble.storage.CONFIGURATION.cli_testing.db_type def ensure_db_type_is_given(func): # pylint: disable=no-self-argument """ Ensure that the db type is given before launching the decorated method. :raise TypeError: When the db type is not given. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.db_type, str): if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.db_type = PyFunceble.storage.CONFIGURATION.cli_testing.db_type else: raise TypeError(f" should be {str}.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def execute_if_authorized(default: Any = None): # pylint: disable=no-self-argument """ Executes the decorated method only if we are authorized to process. Otherwise, apply the given :code:`default`. """ def inner_metdhod(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.authorized: return func(self, *args, **kwargs) # pylint: disable=not-callable return self if default is None else default return wrapper return inner_metdhod def start_if_not_started(func): # pylint: disable=no-self-argument """ Launches the start method before launching the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.credential, CredentialBase): self.start() return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @property def authorized(self) -> bool: """ Provides the authorization to run. """ return self.db_type != "csv" @property def db_type(self) -> Optional[str]: """ Provides the current state of the :code:`_db_type` attribute. """ return self._db_type @db_type.setter def db_type(self, value: str) -> None: """ Sets the database type to work with. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty or not supported. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") value = value.lower() if value not in self.DB_TYPE2OBJ: raise ValueError(f" ({value!r}) is not supported.") self._db_type = value def set_db_type(self, value: str) -> "CredentialLoader": """ Sets the database type to work with. :param value: The value to set. """ self.db_type = value return self @execute_if_authorized(False) def is_already_loaded(self) -> bool: """ Checks if the credential was already loaded. """ return isinstance(self.credential, CredentialBase) def set_credential_var(self, var_name: str, value: Any) -> "CredentialLoader": """ Sets the given :code:`var_name` of the credential object with the given :code:`value`. :param var_name: The name of the variable to set. :param value: The value of to set. """ try: setattr(self.credential, var_name, value) except TypeError: setattr(self.credential, var_name, int(value)) def ask_for_info(self, var_name: str, default: Any) -> str: """ Asks the credential to the end-user. :param var_name: The name of the part to ask for example :code:`host` or :code:`password`. :param default: The default value to return if the user don't give us anything. """ message = ( f"[{self.db_type.upper()}] Please give us your DB {var_name} " f"(Default: {default!r}): " ) if var_name == "password": user_input = getpass(message) else: user_input = input(message) if user_input: return user_input return default @execute_if_authorized(None) @ensure_db_type_is_given def start(self, *, ignore_cli: bool = True) -> "CredentialLoader": """ Starts the loading of the credential. :param ignore_cli: Ignore questions to end-user. """ if not isinstance(self.credential, CredentialBase) and self.authorized: # We directly share the credential object into the DBSession object. # This will let us use the DBSession without having to think about # any other headache. self.credential = PyFunceble.cli.factory.DBSession.credential = ( self.DB_TYPE2OBJ[self.db_type]() ) env_var_helper = EnvironmentVariableHelper( env_file_path=self.credential.get_dot_env_file() ) for cred_var, env_var in self.credential.VAR2ENV.items(): if env_var_helper.set_name(env_var).exists(): self.set_credential_var(cred_var, env_var_helper.get_value()) else: from_file = env_var_helper.get_value_from_env_file() if from_file: self.set_credential_var(cred_var, from_file) elif not ignore_cli: self.set_credential_var( cred_var, self.ask_for_info( cred_var, getattr(self.credential, f"STD_{cred_var.upper()}"), ), ) else: self.set_credential_var( cred_var, getattr(self.credential, f"STD_{cred_var.upper()}"), ) env_var_helper.set_value_in_env_file( str(getattr(self.credential, cred_var)) ) return self @execute_if_authorized("") @start_if_not_started def get_uri(self) -> str: """ Provides the URI to use. """ return self.credential.get_uri() PyFunceble-4.2.29.dev/PyFunceble/cli/entry_points/000077500000000000000000000000001467462152100217715ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/entry_points/__init__.py000066400000000000000000000046061467462152100241100ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides all our entry points. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/entry_points/clean.py000066400000000000000000000120411467462152100234230ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the endpoints related to the cleanup of the data we produce. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 argparse import os import sys import traceback import colorama import PyFunceble.cli.facility import PyFunceble.cli.storage import PyFunceble.cli.utils.ascii_logo import PyFunceble.facility from PyFunceble.cli.filesystem.cleanup import FilesystemCleanup from PyFunceble.cli.system.integrator import SystemIntegrator from PyFunceble.cli.utils.testing import get_destination_from_origin from PyFunceble.helpers.directory import DirectoryHelper def cleaner() -> None: """ Provides the CLI for the public file generation. """ PyFunceble.facility.ConfigLoader.start() colorama.init(autoreset=True) description = ( f"{colorama.Style.BRIGHT}{colorama.Fore.GREEN}PyFunceble Cleaner" f"{colorama.Style.RESET_ALL} - " "The cleaner of PyFunceble." ) parser = argparse.ArgumentParser( description=description, epilog=PyFunceble.cli.storage.STD_EPILOG, add_help=True, formatter_class=argparse.RawTextHelpFormatter, ) parser.add_argument( "-f", "--file", type=str, help="Sets the file to cleanup the information for." ) parser.add_argument( "-a", "--all", action="store_true", help="Authorizes the cleanup of everything that is not useful anymore.", default=False, ) args = parser.parse_args() SystemIntegrator(args).start() directories_to_ignore = ["__pyfunceble_origin__"] utility = FilesystemCleanup() print(PyFunceble.cli.utils.ascii_logo.get_home_representation()) to_cleanup = [] directory_helper = DirectoryHelper() if args.file: to_cleanup.append(get_destination_from_origin(args.file)) if ( args.all and directory_helper.set_path(PyFunceble.cli.storage.OUTPUT_DIRECTORY).exists() ): to_cleanup.extend( [ x for x in os.listdir(PyFunceble.cli.storage.OUTPUT_DIRECTORY) if directory_helper.set_path( os.path.join(PyFunceble.cli.storage.OUTPUT_DIRECTORY, x) ).exists() ] ) for directory in to_cleanup: if directory in directories_to_ignore: continue utility.set_parent_dirname(directory) print(f"Started cleanup of {utility.get_output_basedir()}.", end=" ") try: utility.clean_output_files() print(PyFunceble.cli.storage.DONE) except: # pylint: disable=bare-except print(PyFunceble.cli.storage.ERROR) print(traceback.format_exc()) sys.exit(1) if args.all: utility.clean_database() PyFunceble-4.2.29.dev/PyFunceble/cli/entry_points/iana.py000066400000000000000000000100631467462152100232530ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the endpoints related to our own version of the iana database. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 argparse import sys import traceback from os import cpu_count import colorama import PyFunceble.cli.storage import PyFunceble.cli.utils.ascii_logo from PyFunceble.cli.scripts.iana import IanaDBGenerator def generator() -> None: """ Provides the CLI for the IANA file generation. """ colorama.init(autoreset=True) description = ( f"{colorama.Style.BRIGHT}{colorama.Fore.GREEN}PyFunceble IANA Generator" f"{colorama.Style.RESET_ALL} - " "The IANA database file generator for PyFunceble." ) parser = argparse.ArgumentParser( description=description, epilog=PyFunceble.cli.storage.STD_EPILOG, add_help=True, formatter_class=argparse.RawTextHelpFormatter, ) parser.add_argument( "-d", "--destination", type=str, help="Sets the path to the file to write.", default=None, ) parser.add_argument( "-w", "--max-workers", type=int, help=f"Sets the maximum number of worker to use. " f"(Default: {cpu_count() * 5})", default=None, ) args = parser.parse_args() utility = IanaDBGenerator() if args.destination: utility.destination = args.destination print(PyFunceble.cli.utils.ascii_logo.get_home_representation()) print(f"Generation of IANA database into {utility.destination!r}", end=" ") try: utility.start(max_workers=args.max_workers) print(PyFunceble.cli.storage.DONE) except: # pylint: disable=bare-except print(PyFunceble.cli.storage.ERROR) print(traceback.format_exc()) sys.exit(1) PyFunceble-4.2.29.dev/PyFunceble/cli/entry_points/production.py000066400000000000000000000117551467462152100245420ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the endpoints related to our production preparation. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 argparse import sys import traceback import colorama import PyFunceble.cli.storage import PyFunceble.cli.utils.ascii_logo from PyFunceble.cli.scripts.production import ProductionPrep def producer() -> None: # pylint: disable=too-many-statements """ Provides the CLI for the production preparator. """ colorama.init(autoreset=True) description = ( f"{colorama.Style.BRIGHT}{colorama.Fore.GREEN}PyFunceble Production Preparator" f"{colorama.Style.RESET_ALL} - " "The Production peparator for PyFunceble." ) parser = argparse.ArgumentParser( description=description, epilog=PyFunceble.cli.storage.STD_EPILOG, add_help=True, formatter_class=argparse.RawTextHelpFormatter, ) parser.add_argument( "branch", type=str, help="Sets the branch to acts as.", default=None ) args = parser.parse_args() utility = ProductionPrep() try: utility.branch = args.branch except (TypeError, ValueError) as exception: print(f"{colorama.Fore.RED}{colorama.Style.BRIGHT}{str(exception)}") sys.exit(1) print(PyFunceble.cli.utils.ascii_logo.get_home_representation()) print("Update setup.py", end=" ") try: utility.update_setup_py() print(PyFunceble.cli.storage.DONE) except: # pylint: disable=bare-except print(PyFunceble.cli.storage.ERROR) print(traceback.format_exc()) sys.exit(1) print("Update URL in source code and tests", end=" ") try: utility.update_code_urls() print(PyFunceble.cli.storage.DONE) except: # pylint: disable=bare-except print(PyFunceble.cli.storage.ERROR) print(traceback.format_exc()) sys.exit(1) print("Update source code and tests format", end=" ") try: utility.update_code_format() print(PyFunceble.cli.storage.DONE) except: # pylint: disable=bare-except print(PyFunceble.cli.storage.ERROR) print(traceback.format_exc()) sys.exit(1) print("Update version file", end=" ") try: utility.update_version_file() print(PyFunceble.cli.storage.DONE) except: # pylint: disable=bare-except print(PyFunceble.cli.storage.ERROR) print(traceback.format_exc()) sys.exit(1) print("Update dir structure file", end=" ") try: utility.update_dir_structure_file() print(PyFunceble.cli.storage.DONE) except: # pylint: disable=bare-except print(PyFunceble.cli.storage.ERROR) print(traceback.format_exc()) sys.exit(1) PyFunceble-4.2.29.dev/PyFunceble/cli/entry_points/public_suffix.py000066400000000000000000000103541467462152100252100ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the endpoints related to our own version of the public suffix file. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 argparse import os import sys import traceback import colorama import PyFunceble.cli.storage import PyFunceble.cli.utils.ascii_logo from PyFunceble.cli.scripts.public_suffix import PublicSuffixGenerator def generator() -> None: """ Provides the CLI for the public file generation. """ colorama.init(autoreset=True) description = ( f"{colorama.Style.BRIGHT}{colorama.Fore.GREEN}PyFunceble PSG Generator" f"{colorama.Style.RESET_ALL} - " "The Public Suffix List file generator for PyFunceble." ) parser = argparse.ArgumentParser( description=description, epilog=PyFunceble.cli.storage.STD_EPILOG, add_help=True, formatter_class=argparse.RawTextHelpFormatter, ) parser.add_argument( "-d", "--destination", type=str, help="Sets the path to the file to write.", default=None, ) parser.add_argument( "-w", "--max-workers", type=int, help=f"Sets the maximum number of worker to use. " f"(Default: {os.cpu_count() * 5})", default=None, ) args = parser.parse_args() utility = PublicSuffixGenerator() if args.destination: try: utility.destination = args.destination except (TypeError, ValueError) as exception: print(f"{colorama.Fore.RED}{colorama.Style.BRIGHT}{str(exception)}") sys.exit(1) print(PyFunceble.cli.utils.ascii_logo.get_home_representation()) print(f"Generation of PSL into {utility.destination!r}", end=" ") try: utility.start(max_workers=args.max_workers) print(PyFunceble.cli.storage.DONE) except: # pylint: disable=bare-except print(PyFunceble.cli.storage.ERROR) print(traceback.format_exc()) sys.exit(1) PyFunceble-4.2.29.dev/PyFunceble/cli/entry_points/pyfunceble/000077500000000000000000000000001467462152100241255ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/entry_points/pyfunceble/__init__.py000066400000000000000000000046651467462152100262510ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides (a bit more that "usual") what is needed by the PyFunceble CLI tool. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/entry_points/pyfunceble/argsparser.py000066400000000000000000000112141467462152100266470ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our very own argument parser Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 argparse from typing import Optional, Sequence # pylint: disable=raising-bad-type class OurArgumentParser(argparse.ArgumentParser): """ Overwrites some behavior of the default argument parser. """ def parse_args( self, args: Optional[Sequence[str]] = None, namespace: Optional[argparse.Namespace] = None, ) -> argparse.Namespace: namespace = super().parse_args(args, namespace) if namespace.lookup__timeout is not None and namespace.lookup__timeout < 0: raise self.error("--timeout must be a positive digit.") if ( namespace.cli_testing__cooldown_time is not None and namespace.cli_testing__cooldown_time < 0 ): raise self.error("--cooldown-time must be zero or a positive digit.") if ( namespace.cli_testing__max_workers is not None and namespace.cli_testing__max_workers <= 0 ): raise self.error("--max-workers must be a positive digit.") if ( namespace.cli_testing__display_mode__max_registrar is not None and namespace.cli_testing__display_mode__max_registrar <= 0 ): raise self.error("--max-registrar must be a positive digit.") if namespace.dns__delay is not None and namespace.dns__delay < 0: raise self.error("--dns-delay must be zero or a positive digit.") if namespace.max_http_retries is not None and namespace.max_http_retries < 0: raise self.error("--max-http-retries must be zero or a positive digit.") if namespace.cli_decoding__adblock and namespace.cli_decoding__wildcard: raise self.error("--adblock and --wildcard are incompatible.") if namespace.cli_decoding__adblock and namespace.cli_decoding__rpz: raise self.error("--adblock and --rpz are incompatible.") if namespace.cli_decoding__wildcard and namespace.cli_decoding__rpz: raise self.error("--rpz and --wildcard are incompatible.") if ( namespace.cli_testing__testing_mode__syntax and namespace.cli_testing__testing_mode__reputation ): raise self.error("--syntax and --reputation are incompatible.") return namespace PyFunceble-4.2.29.dev/PyFunceble/cli/entry_points/pyfunceble/cli.py000066400000000000000000001350621467462152100252550ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the endpoint of the PyFunceble CLI tool Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: disable=too-many-lines import argparse import os import sys from typing import Any, List, Optional, Tuple, Union import colorama import shtab import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.storage from PyFunceble.cli.entry_points.pyfunceble.argsparser import OurArgumentParser from PyFunceble.cli.system.integrator import SystemIntegrator from PyFunceble.cli.system.launcher import SystemLauncher from PyFunceble.helpers.regex import RegexHelper def get_configured_value( entry: str, *, negate: bool = False, value_only: bool = False ) -> Any: """ Provides the currently configured value. :param entry: An entry to check. multilevel should be separated with a point. :param negate: Allows us to negate the result from the configuration. :param value_only: Whether we should only return the value or the full message. :raise ValueError: When the given :code:`entry` is not found. """ if ":" in entry: location, var_name = entry.split(":", 1) if location == "cli_storage": result = getattr(PyFunceble.cli.storage, var_name) else: raise RuntimeError(" ({entry!r}) not supported.") if var_name == "OUTPUT_DIRECTORY": result = os.path.join(*os.path.split(result)[:-1]) else: result = PyFunceble.facility.ConfigLoader.get_configured_value(entry) if negate: result = not result return ( ( f"\n{colorama.Fore.YELLOW}{colorama.Style.BRIGHT}" f"Configured value: {colorama.Fore.BLUE}" f"{result!r}" f"{colorama.Style.RESET_ALL}" ) if not value_only else result ) # pylint: disable=protected-access def add_arguments_to_parser( parser: Union[argparse.ArgumentParser, argparse._ArgumentGroup], arguments: List[Tuple[List[str], dict]], ) -> None: """ Adds the given argument into the given parser. """ for pos_args, opt_args in arguments: if "dest" in opt_args: opt_args["dest"] = opt_args["dest"].replace(".", "__") for index, value in enumerate(pos_args): if value.startswith("-") and "." not in value: continue pos_args[index] = value.replace(".", "__") parser.add_argument(*pos_args, **opt_args) def get_source_group_data() -> List[Tuple[List[str], dict]]: """ Provides the arguments of the source group. """ return [ ( [ "-d", "--domain", ], { "dest": "domains", "type": str.lower, "nargs": "+", "help": "Test one or more domains, separated by spaces.\n\n" "When this option is used, no output files are generated.", }, ), ( [ "-u", "--url", ], { "dest": "urls", "type": str, "nargs": "+", "help": "Test one or more full URL, separated by spaces.", }, ), ( [ "-f", "--file", ], { "dest": "files", "type": str, "nargs": "+", "help": "Read a local or remote (RAW link) file and test all " "domains inside it." "\nIf remote (RAW link) file is given, PyFunceble will download " "it,\n and test the content of the given RAW link as if it was a" " locally stored file.", }, ), ( [ "-uf", "--url-file", ], { "dest": "url_files", "type": str, "nargs": "+", "help": "Read a local or remote (RAW link) file and test all " "(full) URLs inside it." "\nIf remote (RAW link) file is given, PyFunceble will download " "it,\n and test the content of the given RAW link as if it was a" " locally stored file. " "\n\nThis argument test if an URL is available. It ONLY test " "full URLs.", }, ), ] def get_filtering_group_data() -> List[Tuple[List[str], dict]]: """ Provides the argument of the filtering group. """ return [ ( [ "--adblock", ], { "dest": "cli_decoding.adblock", "action": "store_true", "help": "Activates or deactivates the decoding of the adblock " "format. %s" % get_configured_value("cli_decoding.adblock"), }, ), ( [ "--aggressive", ], { "dest": "cli_decoding.aggressive", "action": "store_true", "help": argparse.SUPPRESS, }, ), ( ["--cidr"], { "dest": "cli_testing.cidr_expand", "action": "store_true", "help": "Activates or disables the expansion of CIDR formatted\n" "addresses. %s" % get_configured_value("cli_testing.cidr_expand"), }, ), ( [ "--complements", ], { "dest": "cli_testing.complements", "action": "store_true", "help": "Activates or disables the generation and test of the\n" "complements. " "\nA complement is for example `example.org` if " "'www.example.org'\nis given and vice-versa. %s" % get_configured_value("cli_testing.complements"), }, ), ( [ "--preload", ], { "dest": "cli_testing.preload_file", "action": "store_true", "help": "Activates or disables the preloading of the input\n" "file(s) into the continue dataset before starting the tests.\n\n" "This reduces the waiting time while continuing a previous\n" "session.\n" "Note: This is useless when the auto continue subsystem is not " "active. %s" % get_configured_value("cli_testing.preload_file"), }, ), ( [ "--filter", ], { "dest": "cli_testing.file_filter", "type": str, "help": "Regex to match in order to test a given line. %s" % get_configured_value("cli_testing.file_filter"), }, ), ( [ "--mining", ], { "dest": "cli_testing.mining", "action": "store_true", "help": "Activates or disables the mining subsystem. %s" % get_configured_value("cli_testing.mining"), }, ), ( [ "--rpz", ], { "dest": "cli_decoding.rpz", "action": "store_true", "help": "Activates or disables the decoding of RPZ policies\n" "from each given input files. %s" % get_configured_value("cli_decoding.rpz"), }, ), ( [ "--wildcard", ], { "dest": "cli_decoding.wildcard", "action": "store_true", "help": "Activates or disables the decoding of wildcards for\n" "each given input files. %s" % get_configured_value("cli_decoding.wildcard"), }, ), ] def get_test_control_group_data() -> List[Tuple[List[str], dict]]: """ Provides the argument of the test control data group. """ return [ ( [ "--chancy", "--ludicrous", ], { "dest": "cli_testing.chancy_tester", "action": "store_true", "help": "Activates a chancy mode that unleashes the safety\n" "workflow in place. \n\n" f"{colorama.Fore.RED}WARNING: You shouldn't have to use this " "unless you feel really lucky\n" "and trust your machine. This mode makes things look 'fast',\n" "but it may produce some unexpected results if N process\n" "simultaneously write the same output file.\n" "This mode makes the graphical CLI output unparsable - either.\n" f"\n{colorama.Fore.GREEN}MAY THE FORCE BE WITH YOU!" f"\n{colorama.Style.RESET_ALL}%s" % get_configured_value("cli_testing.chancy_tester"), }, ), ( [ "-c", "--auto-continue", "--continue", ], { "dest": "cli_testing.autocontinue", "action": "store_true", "help": "Activates or disables the autocontinue subsystem. %s" % get_configured_value("cli_testing.autocontinue"), }, ), ( [ "--cooldown-time", ], { "dest": "cli_testing.cooldown_time", "type": float, "help": "Sets the cooldown time (in second) to apply between\n" "each test. %s" % get_configured_value("cli_testing.cooldown_time"), }, ), ( [ "--local", ], { "dest": "cli_testing.local_network", "action": "store_true", "help": "Activates or disables the consideration of the test(s)\n" "in or for a local or private network context. %s" % get_configured_value("cli_testing.local_network"), }, ), ( ["--platform-preferred-origin"], { "dest": "platform.preferred_status_origin", "type": str, "choices": ["frequent", "latest", "recommended"], "help": "Sets the preferred status origin. %s" % get_configured_value("platform.preferred_status_origin"), }, ), ( ["--platform-lookup"], { "dest": "lookup.platform", "action": "store_true", "help": "Activates or disables the usage of the Platform lookup\n" "whether possible. %s" % get_configured_value("lookup.platform"), }, ), ( ["--platform-lookup-only"], { "dest": "self_contained.lookup.platform", "action": "store_true", "help": "Only perform a Platform lookup.", }, ), ( ["--dns-lookup"], { "dest": "lookup.dns", "action": "store_true", "help": "Activates or disables the usage of the DNS lookup\n" "whether possible. %s" % get_configured_value("lookup.dns"), }, ), ( ["--dns-lookup-only"], { "dest": "self_contained.lookup.dns", "action": "store_true", "help": "Only perform a DNS lookup.", }, ), ( ["--http", "--http-status-code-lookup"], { "dest": "lookup.http_status_code", "action": "store_true", "help": "Switch the value of the usage of HTTP code. %s" % get_configured_value("lookup.http_status_code"), }, ), ( ["--http-only", "--http-status-code-lookup-only"], { "dest": "self_contained.lookup.http_status_code", "action": "store_true", "help": "Only perform a HTTP Code lookup.", }, ), ( [ "--netinfo-lookup", ], { "dest": "lookup.netinfo", "action": "store_true", "help": "Activates or disables the usage of the network\n" "information (or network socket) whether possible. %s" % get_configured_value("lookup.netinfo"), }, ), ( ["--netinfo-lookup-only"], { "dest": "self_contained.lookup.netinfo", "action": "store_true", "help": "Only perform a network information (or networket " "socket) lookup.", }, ), ( [ "--special-lookup", ], { "dest": "lookup.special", "action": "store_true", "help": "Activates or disables the usage of our SPECIAL and\n" "extra rules whether possible. %s" % get_configured_value("lookup.special"), }, ), ( ["--special-lookup-only"], { "dest": "self_contained.lookup.special", "action": "store_true", "help": "Only perform a SPECIAL lookup.", }, ), ( [ "--whois-lookup", ], { "dest": "lookup.whois", "action": "store_true", "help": "Activates or disables the usage of the WHOIS record\n" "(or better said the expiration date in it) whether possible. %s" % get_configured_value("lookup.whois"), }, ), ( ["--whois-lookup-only"], { "dest": "self_contained.lookup.whois", "action": "store_true", "help": "Only perform a WHOIS lookup.", }, ), ( [ "--reputation-lookup", ], { "dest": "lookup.reputation", "action": "store_true", "help": "Activates or disables the usage of the reputation\n" "dataset whether possible. %s" % get_configured_value("lookup.reputation"), }, ), ( ["--reputation-lookup-only"], { "dest": "self_contained.lookup.reputation", "action": "store_true", "help": "Only perform a reputation lookup.", }, ), ( [ "--reputation", ], { "dest": "cli_testing.testing_mode.reputation", "action": "store_true", "help": "Activates or disables the reputation checker. %s" % get_configured_value("cli_testing.testing_mode.reputation"), }, ), ( [ "--syntax", ], { "dest": "cli_testing.testing_mode.syntax", "action": "store_true", "help": "Activates or disables the syntax checker. %s" % get_configured_value("cli_testing.testing_mode.syntax"), }, ), ( [ "-t", "--timeout", ], { "dest": "lookup.timeout", "type": float, "default": 5.0, "help": "Sets the default timeout to apply to each lookup\n" "utilities every time it is possible to define a timeout. %s" % get_configured_value("lookup.timeout"), }, ), ( [ "--max-http-retries", ], { "dest": "max_http_retries", "type": int, "default": 3, "help": "Sets the maximum number of retries for an HTTP " "request. %s" % get_configured_value("max_http_retries"), }, ), ( [ "-ua", "--user-agent", ], { "dest": "user_agent.custom", "type": str, "help": "Sets the user agent to use.\n\nIf not given, we try to " "get the latest (automatically) for you.", }, ), ( [ "-vsc", "--verify-ssl-certificate", ], { "dest": "verify_ssl_certificate", "action": "store_true", "help": "Activates or disables the verification of the SSL/TLS\n" "certificate when testing for URL. %s" % get_configured_value("verify_ssl_certificate"), }, ), ] def get_dns_control_group_data() -> List[Tuple[List[str], dict]]: """ Provides the argument of the DNS control group. """ return [ ( [ "--dns", ], { "dest": "dns.server", "nargs": "+", "type": str, "help": "Sets one or more (space separated) DNS server(s) to " "use during testing." "\n\nTo specify a port number for the " "DNS server you append\nit as :port [ip:port].\n\n" "If no port is specified, the default DNS port (53) is used. %s" % get_configured_value("dns.server"), }, ), ( [ "--dns-protocol", ], { "dest": "dns.protocol", "type": str, "choices": ["UDP", "TCP", "HTTPS", "TLS"], "help": "Sets the protocol to use for the DNS queries. %s" % get_configured_value("dns.protocol"), }, ), ( ["--follow-server-order"], { "dest": "dns.follow_server_order", "action": "store_true", "help": "Let us follow or mix the order of usage of the given\n" "or found DNS server(s). %s" % get_configured_value("dns.follow_server_order"), }, ), ( ["--trust-dns-server"], { "dest": "dns.trust_server", "action": "store_true", "help": "Activates or disable the trust mode.\n\n" "When active, when the first read DNS server give us a negative\n" "response - without error - we take it as it it.\n" "Otherwise, if not active, when the first read DNS server give us\n" "a negative response - without error - we still consolidate by\n" "checking all given/found server.\n%s" % get_configured_value("dns.trust_server"), }, ), ( [ "--dns-delay", ], { "dest": "dns.delay", "type": float, "help": "Sets the delay (in seconds) to apply between each DNS\n " "queries.\n %s" % get_configured_value("dns.delay"), }, ), ] def get_proxy_control_group_data() -> List[Tuple[List[str], dict]]: """ Provides the argument of the proxy control group. """ return [ ( [ "--http-proxy", ], { "dest": "proxy.global.http", "type": str, "help": "Sets the proxy to use when testing subjects over HTTP. %s" % get_configured_value("proxy.global.http"), }, ), ( [ "--https-proxy", ], { "dest": "proxy.global.https", "type": str, "help": "Sets the proxy to use when testing subjects over HTTPS. %s" % get_configured_value("proxy.global.https"), }, ), ] def get_database_control_group_data() -> List[Tuple[List[str], dict]]: """ Provides the arguments of the database group. """ return [ ( [ "--inactive-db", ], { "dest": "cli_testing.inactive_db", "action": "store_true", "help": "Activates or disables the usage of a 'database' to\n" f"store all {PyFunceble.storage.STATUS.down!r} and " f"{PyFunceble.storage.STATUS.invalid!r} " " subject for continuous retest. %s" % get_configured_value("cli_testing.inactive_db"), }, ), ( [ "--database-type", ], { "dest": "cli_testing.db_type", "type": str, "choices": ["csv", "mariadb", "mysql", "postgresql"], "help": "Sets the database engine to use. " "\nYou can choose between the following: " "`csv | mariadb | mysql | postgresql` %s" % get_configured_value("cli_testing.db_type"), }, ), ( [ "-dbr", "--days-between-db-retest", ], { "dest": "cli_testing.days_between.db_retest", "type": int, "help": "Sets the numbers of days since the introduction of\n" "subject into the inactive dataset before it gets retested. %s" % get_configured_value("cli_testing.days_between.db_retest"), }, ), ( [ "-dbc", "--days-between-db-clean", ], { "dest": "cli_testing.days_between.db_clean", "type": int, "help": argparse.SUPPRESS, }, ), ( [ "-wdb", "--whois-database", ], { "dest": "cli_testing.whois_db", "action": "store_true", "help": "Activates or disables the usage of a 'database' to\n" "store the expiration date of all domains with a valid\n" "expiration date. %s" % get_configured_value("cli_testing.whois_db"), }, ), ] def get_output_control_group_data() -> List[Tuple[List[str], dict]]: """ Provides the argument of the output group. """ return [ ( [ "-a", "--all", ], { "dest": "cli_testing.display_mode.all", "action": "store_true", "help": "Activates or disables the display of the all\n" "information in the table we print to stdout. %s" % get_configured_value("cli_testing.display_mode.all"), }, ), ( [ "-ex", "--execution", ], { "dest": "cli_testing.display_mode.execution_time", "action": "store_true", "help": "Activates or disables the display of the execution time. %s" % get_configured_value("cli_testing.display_mode.execution_time"), }, ), ( ["--colour", "--color"], { "dest": "cli_testing.display_mode.colour", "action": "store_true", "help": "Activates or disables the coloration to STDOUT. %s" % get_configured_value("cli_testing.display_mode.colour"), }, ), ( ["--display-status"], { "dest": "cli_testing.display_mode.status", "type": str.upper, "choices": ["all"] + list(PyFunceble.storage.STATUS.values()), "nargs": "+", "help": "Sets the status that we are allowed to print to STDOUT.\n\n" "Multiple space separated statuses can be given." "%s" % get_configured_value("cli_testing.display_mode.status"), "default": "all", }, ), ( [ "--dots", ], { "dest": "cli_testing.display_mode.dots", "action": "store_true", "help": "Activate or disables the display of dots or other\n" "characters when we skip the test of a subject. %s" % get_configured_value("cli_testing.display_mode.dots"), }, ), ( [ "--hierarchical", ], { "dest": "cli_testing.sorting_mode.hierarchical", "action": "store_true", "help": "Activates or disables the sorting of the files\n" "content (output) in a hierarchical order. %s" % get_configured_value("cli_testing.sorting_mode.hierarchical"), }, ), ( [ "-h", "--host", ], { "dest": "cli_testing.file_generation.hosts", "action": "store_true", "help": "Activates or disables the generation of the\n" "hosts file(s). %s" % get_configured_value("cli_testing.file_generation.hosts"), }, ), ( ["-ip", "--hosts-ip"], { "dest": "cli_testing.hosts_ip", "type": str, "help": "Sets the IP to prefix each lines of the hosts file. %s" % get_configured_value("cli_testing.hosts_ip"), }, ), ( [ "--merge-output", ], { "dest": "cli_testing.file_generation.merge_output_dirs", "action": "store_true", "help": "Activates or disables the merging of the outputs of all\n" "inputted files inside a single subdirectory as opposed to the\n" "normal behavior. %s" % get_configured_value("cli_testing.file_generation.merge_output_dirs"), }, ), ( [ "--no-files", ], { "dest": "cli_testing.file_generation.no_file", "action": "store_true", "help": "Activates or disables the generation of any non-logs\n" "file(s). %s" % get_configured_value("cli_testing.file_generation.no_file"), }, ), ( [ "--output-location", ], { "dest": "output_location", "type": str, "help": "Sets the location where we are supposed to generation\n" "the output directory from. %s" % get_configured_value("cli_storage:OUTPUT_DIRECTORY"), }, ), ( [ "--unified-results", ], { "dest": "cli_testing.file_generation.unified_results", "action": "store_true", "help": "Activates or disables the generation of the unified\n" "results file instead of the divided ones. %s" % get_configured_value( "cli_testing.file_generation.unified_results", ), }, ), ( [ "--percentage", ], { "dest": "cli_testing.display_mode.percentage", "action": "store_true", "help": "Activates or disables the display and generation\n" "of the percentage - file - of each status. %s" % get_configured_value("cli_testing.display_mode.percentage"), }, ), ( [ "--registrar", ], { "dest": "cli_testing.display_mode.registrar", "action": "store_true", "help": "Activates or disables the display and generation\n" "of the registrar - file - status at the end of a test.\n" "The registrar file contains the top domain registrar found\n" "while testing. %s" % get_configured_value("cli_testing.display_mode.registrar"), }, ), ( [ "--max-registrar", ], { "dest": "cli_testing.display_mode.max_registrar", "type": int, "default": 15, "help": "Sets the maximal number of registrar to display.\n" "Note: This argument has no effect when the --registrar\n" "argument is not set. This argument only takes effect on\n" "display but not\n" "in the log file %s" % get_configured_value("cli_testing.display_mode.max_registrar"), }, ), ( [ "--plain", ], { "dest": "cli_testing.file_generation.plain", "action": "store_true", "help": "Activates or disables the generation of the\n" "RAW file(s). What is meant is a list with only a list of\n" "subject (one per line). %s" % get_configured_value("cli_testing.file_generation.plain"), }, ), ( [ "-q", "--quiet", ], { "dest": "cli_testing.display_mode.quiet", "action": "store_true", "help": "Activates or disables the display of output to the\n" "terminal. %s" % get_configured_value("cli_testing.display_mode.quiet"), }, ), ( [ "--share-logs", ], { "dest": "share_logs", "action": "store_true", "help": argparse.SUPPRESS, }, ), ( [ "--push-platform", ], { "dest": "platform.push", "action": "store_true", "help": "Activates or disables the push of test result into the\n" "Platform API. %s" % get_configured_value("platform.push"), }, ), ( [ "-s", "--simple", ], { "dest": "cli_testing.display_mode.simple", "action": "store_true", "help": "Activates or disables the simple output mode. %s" % get_configured_value("cli_testing.display_mode.simple"), }, ), ] def get_multiprocessing_group_data() -> List[Tuple[List[str], dict]]: """ Provides the argument of the multiprocessing group data. """ available_cpu = os.cpu_count() if available_cpu is not None and available_cpu > 2: default_max_workers = available_cpu - 2 else: default_max_workers = 1 return [ ( [ "-w", "--max-workers", ], { "dest": "cli_testing.max_workers", "type": int, "default": default_max_workers, "help": "Sets the number of maximal workers to use.\n" f"If not given, {default_max_workers} " "(based on the current machine) will be applied. %s" % get_configured_value("cli_testing.max_workers"), }, ), ] def get_ci_group_data() -> List[Tuple[List[str], dict]]: """ Provides the argument of the CI group data. """ return [ ( ["--ci-max-minutes"], { "dest": "cli_testing.ci.max_exec_minutes", "type": int, "help": "Sets the number of minutes to wait before starting\n" "to stop a CI session. %s" % get_configured_value("cli_testing.ci.max_exec_minutes"), }, ), ( ["--ci"], { "dest": "cli_testing.ci.active", "action": "store_true", "help": "Activates or disables the Continuous Integration\n" "mechanism. %s" % get_configured_value("cli_testing.ci.active"), }, ), ( ["--ci-branch"], { "dest": "cli_testing.ci.branch", "type": str, "help": "Sets our git working branch. This is the branch\n" "from where we are supposed to store the tests\n" "(excepts the final results). %s" % get_configured_value("cli_testing.ci.branch"), }, ), ( ["--ci-distribution-branch"], { "dest": "cli_testing.ci.distribution_branch", "type": str, "help": "Sets our git distributions branch. This is the\n" "branch from where we are supposed to store and push\n" "the final results. %s" % get_configured_value("cli_testing.ci.distribution_branch"), }, ), ( ["--ci-command"], { "dest": "cli_testing.ci.command", "type": str, "help": "Sets the command to execute before each commit\n" "(except the final one). %s" % get_configured_value("cli_testing.ci.command"), }, ), ( ["--ci-end-command"], { "dest": "cli_testing.ci.end_command", "type": str, "help": "Sets the command to execute before the final commit. %s" % get_configured_value("cli_testing.ci.end_command"), }, ), ( ["--ci-commit-message"], { "dest": "cli_testing.ci.commit_message", "type": str, "help": "Sets the commit message to apply every time we have\n" "to apply a commit except for the really last one. %s" % get_configured_value("cli_testing.ci.commit_message"), }, ), ( [ "--ci-end-commit-message", ], { "dest": "cli_testing.ci.end_commit_message", "type": str, "help": "Sets the commit message to apply at the really end. %s" % get_configured_value("cli_testing.ci.end_commit_message"), }, ), ] def get_default_group_data() -> List[Tuple[List[str], dict]]: """ Provides the argument of the default group. """ return [ ( ["--debug"], { "dest": "debug.active", "action": "store_true", "help": argparse.SUPPRESS, }, ), ( ["--logging-level"], { "dest": "debug.level", "choices": ["debug", "info", "warning", "error", "critical"], "default": None, "type": str.lower, "help": argparse.SUPPRESS, }, ), ( ["--help"], { "action": "help", "help": "Show this help message and exit.", "default": argparse.SUPPRESS, }, ), ( [ "-v", "--version", ], { "action": "version", "help": "Show the version of PyFunceble and exit.", "version": "%(prog)s " + PyFunceble.storage.PROJECT_VERSION, }, ), ] def platform_parser( parser: Union[argparse.ArgumentParser, argparse._SubParsersAction] ) -> None: """ Adds the platform group to the given parser. """ platform = parser.add_parser( "platform", add_help=False, epilog=PyFunceble.cli.storage.STD_EPILOG, ) args = [ ( ["cli_testing.testing_mode.platform_contribution"], { "default": get_configured_value( "cli_testing.testing_mode.platform_contribution", value_only=True ), "action": "store_%s" % str( not get_configured_value( "cli_testing.testing_mode.platform_contribution", value_only=True, ) ).lower(), "help": argparse.SUPPRESS, }, ) ] add_arguments_to_parser(platform, args) add_arguments_to_parser(platform, get_default_group_data()) def ask_authorization_to_merge_config(missing_key: Optional[str] = None) -> bool: """ Asks the end-user for the authorization to merge the upstream configuration and - finally - return the new authorization status. :param missing_key: The name of a missing key. If not given, a more generic message will be given to end-user. """ if missing_key: message = ( f"{colorama.Fore.RED}{colorama.Style.BRIGHT}The {missing_key!r} " f"key is missing from your configuration file." f"{colorama.Style.RESET_ALL}\n" f"Are we authorized to merge it from upstream ? {colorama.Style.BRIGHT}" "[y/n] " ) else: message = ( f"{colorama.Fore.RED}{colorama.Style.BRIGHT}A " f"key is missing from your configuration file." f"{colorama.Style.RESET_ALL}\n" f"Are we authorized to merge it from upstream ? {colorama.Style.BRIGHT}" "[y/n] " ) while True: response = input(message).lower() if response[0] not in ("y", "n"): continue if response[0] == "y": return True return False def tool() -> None: """ Provides the CLI of PyFunceble. """ # pylint: disable=too-many-locals # We start with loading the configuration. That way, we don't have to # think of this anymore as soon as the CLI is called. # As the merging is now done on demand and not on first hand, this will # give us a bit of agility. PyFunceble.facility.ConfigLoader.start() colorama.init(autoreset=True) description = ( f"{colorama.Style.BRIGHT}{colorama.Fore.GREEN}PyFunceble" f"{colorama.Style.RESET_ALL} - " "The tool to check the availability or syntax of domain, IP or URL.\n\n" f"{colorama.Style.BRIGHT}Note:{colorama.Style.RESET_ALL}\n" " All arguments listed bellow acts a switch to your configuration file-s.\n" " This means that if (e.g.) 'file_generation.no_file' is set to 'true' " "its value\n" " will be switch to 'false' at the runtime if the '--no-files' argument is " "being used.\n" " Meaning that output files will be generated." ) our_epilog = ( f"{colorama.Style.BRIGHT}Examples:{colorama.Style.RESET_ALL}\n\n" " Check the availability of 'example.com'.\n" " $ pyfunceble -d example.com\n\n" " Check the availability of 'example.com' with a simple (stdout) output.\n" " $ pyfunceble -s -d example.com\n\n" " Check the availability of 'example.com' with extended (stdout) output.\n" " $ pyfunceble -a -d example.com\n\n" " Check the availability of 'example.com' and 'example.org'.\n" " $ pyfunceble -d example.com example.org\n\n" " Check the availability of 'https://example.com'.\n" " $ pyfunceble -u https://example.com\n\n" " Check the availability of 'https://example.com' and " "'https://example.org'.\n" " $ pyfunceble -u https://example.com https://example.com\n\n" " Check the syntax of 'example.com'.\n" " $ pyfunceble --syntax -d example.com\n\n" " Check the reputation of 'example.com'.\n" " $ pyfunceble --reputation -d example.com\n\n" " Check the availability of all subjects in the 'myhosts' file.\n" " $ pyfunceble -f myhosts\n\n" " Check the availability of all subjects in the 'myhosts' and 'yourhosts' " "files.\n" " $ pyfunceble -f myhosts yourhosts\n\n" "\n\n" f"{colorama.Style.BRIGHT}{colorama.Fore.YELLOW}For an in-depth usage, " "explanation and examples of the arguments,\n" f"you should read the documentation at{colorama.Fore.GREEN} " "https://docs.pyfunceble.com" f"{colorama.Style.RESET_ALL}\n\n" ) parser = OurArgumentParser( description=description, epilog=our_epilog + PyFunceble.cli.storage.STD_EPILOG, add_help=False, formatter_class=argparse.RawTextHelpFormatter, ) # pylint: disable=possibly-unused-variable command_sub = parser.add_subparsers(dest="command", help=argparse.SUPPRESS) shtab.add_argument_to( parser, option_string=["--show-completion"], help="Show Shell completion script and exit.", ) source_group = parser.add_argument_group("Test sources") filtering_group = parser.add_argument_group( "Source filtering, decoding, conversion and expansion" ) test_control_group = parser.add_argument_group("Test control") dns_control_group = parser.add_argument_group("DNS control") proxy_control_group = parser.add_argument_group("Proxy control") database_control_group = parser.add_argument_group("Databases") output_control_group = parser.add_argument_group("Output control") multiprocessing_group = parser.add_argument_group("Multiprocessing") ci_group = parser.add_argument_group("CI / CD") funcs = [ get_source_group_data, get_filtering_group_data, get_test_control_group_data, get_dns_control_group_data, get_proxy_control_group_data, get_database_control_group_data, get_output_control_group_data, get_multiprocessing_group_data, get_ci_group_data, ] parse_funcs = [platform_parser] for func in funcs: parser_name = func.__name__.replace("get_", "").replace("_data", "") try: add_arguments_to_parser(locals()[parser_name], func()) except ValueError as exception: exception_message = str(exception) if "configuration" not in exception_message: raise exception missing_key = RegexHelper(r"\s\(\'(.*)\'\)").match( exception_message, return_match=True, group=1 ) if ask_authorization_to_merge_config(missing_key): PyFunceble.facility.ConfigLoader.set_merge_upstream(True).start() add_arguments_to_parser(locals()[parser_name], func()) else: print( f"{colorama.Fore.RED}{colorama.Style.BRIGHT}Could not find " f"the {missing_key!r} in your configuration.\n" f"{colorama.Fore.MAGENTA}Please fix your " "configuration file manually or fill a new issue if you " "don't understand this error." ) sys.exit(1) for func in parse_funcs: func(command_sub) add_arguments_to_parser(parser, get_default_group_data()) args = parser.parse_args() if any( getattr(args, x) for x in [ "domains", "urls", "files", "url_files", ] ) or bool(args.command): SystemIntegrator(args).start() SystemLauncher(args).start() PyFunceble-4.2.29.dev/PyFunceble/cli/execution_time.py000066400000000000000000000160631467462152100226350ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the interface for the generation of the execution time. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: disable=too-many-lines import datetime import functools from typing import Any, Optional import PyFunceble.cli.storage import PyFunceble.facility class ExecutionTime: """ Provides the interface for the execution time. :param authorized: The authorization to run. """ STD_AUTHORIZED: bool = False _authorized: bool = False start_time: Optional[datetime.datetime] = None end_time: Optional[datetime.datetime] = None def __init__( self, authorized: Optional[bool] = None, ) -> None: if authorized is not None: self.authorized = authorized else: self.guess_and_set_authorized() def execute_if_authorized(default: Any = None): # pylint: disable=no-self-argument """ Executes the decorated method only if we are authorized to process. Otherwise, apply the given :code:`default`. """ def inner_metdhod(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.authorized: return func(self, *args, **kwargs) # pylint: disable=not-callable return self if default is None else default return wrapper return inner_metdhod @staticmethod def split_difference(start: datetime.datetime, end: datetime.datetime) -> dict: """ Calculates the difference between the two datetime object. :param start: The starting time. :param end: The ending time. :raise TypeError: When the given :code:`start` or :code:`end` is not a :py:class:`datetime.datetime`. """ if not isinstance(start, datetime.datetime): raise TypeError( f" should be {datetime.datetime}, {type(start)} given." ) if not isinstance(end, datetime.datetime): raise TypeError( f" should be {datetime.datetime}, {type(start)} given." ) difference = end.timestamp() - start.timestamp() result = {} result["days"] = difference // (24 * 60 * 60) result["hours"] = (difference // (60 * 60)) % 24 result["minutes"] = (difference % 3600) // 60 result["seconds"] = difference % 60 return result @property def authorized(self) -> Optional[bool]: """ Provides the currently state of the :code:`_authorized` attribute. """ return self._authorized @authorized.setter def authorized(self, value: bool) -> None: """ Sets the value of the :code:`authorized` attribute. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool` """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._authorized = value def set_authorized(self, value: bool) -> "ExecutionTime": """ Sets the value of the :code:`authorized` attribute. :param value: The value to set. """ self.authorized = value return self @execute_if_authorized(None) def set_start_time(self) -> "ExecutionTime": """ Sets the starting time to now. """ self.start_time = datetime.datetime.now(datetime.timezone.utc) return self @execute_if_authorized(None) def set_end_time(self) -> "ExecutionTime": """ Sets the starting time to now. """ self.end_time = datetime.datetime.now(datetime.timezone.utc) return self def guess_and_set_authorized(self) -> "ExecutionTime": """ Try to guess and set the authorization from the configuration file. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.authorized = bool( PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.execution_time ) else: self.authorized = self.STD_AUTHORIZED @execute_if_authorized(None) def get_info(self) -> dict: """ Provides the information to work with. """ if not self.end_time: self.set_end_time() result = self.split_difference(self.start_time, self.end_time) result["days"] = str(int(result["days"])).zfill(2) result["hours"] = str(int(result["hours"])).zfill(2) result["minutes"] = str(int(result["minutes"])).zfill(2) result["seconds"] = str(round(result["seconds"], 6)).zfill(2) return result PyFunceble-4.2.29.dev/PyFunceble/cli/facility.py000066400000000000000000000050201467462152100214070ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some loader that we may need later. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.cli.credential_loader import CredentialLoader as credential_loader CredentialLoader = credential_loader() PyFunceble-4.2.29.dev/PyFunceble/cli/factory.py000066400000000000000000000050121467462152100212530ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything which doesn't get through the door of the facility. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.database.session import DBSession as db_session DBSession = db_session() PyFunceble-4.2.29.dev/PyFunceble/cli/file_preloader.py000066400000000000000000000435711467462152100225740ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the interface for the preloading of a given file. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy import functools import os from datetime import datetime, timedelta, timezone from typing import Any, Optional from domain2idna import domain2idna import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.storage from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase from PyFunceble.cli.processes.workers.tester import TesterWorker from PyFunceble.cli.utils.stdout import print_single_line from PyFunceble.cli.utils.testing import get_subjects_from_line from PyFunceble.converter.adblock_input_line2subject import AdblockInputLine2Subject from PyFunceble.converter.cidr2subject import CIDR2Subject from PyFunceble.converter.input_line2subject import InputLine2Subject from PyFunceble.converter.rpz_input_line2subject import RPZInputLine2Subject from PyFunceble.converter.rpz_policy2subject import RPZPolicy2Subject from PyFunceble.converter.subject2complements import Subject2Complements from PyFunceble.converter.url2netloc import Url2Netloc from PyFunceble.converter.wildcard2subject import Wildcard2Subject from PyFunceble.dataset.autocontinue.base import ContinueDatasetBase from PyFunceble.dataset.autocontinue.csv import CSVContinueDataset from PyFunceble.dataset.inactive.base import InactiveDatasetBase from PyFunceble.helpers.dict import DictHelper from PyFunceble.helpers.file import FileHelper from PyFunceble.helpers.hash import HashHelper class FilePreloader: """ Provides an interface for the file preloading. The main idea behind this interface is to read all lines of the given file parse each lines into something our autocontinue dataset understand. Once everything preloaded in the autocontinue dataset, one can use the :meth:`PyFunceble.dataset.autocontinue.base.ContinueDataset.get_to_test` to get the next subject to test. By doing this, we don't have to re-read a file completely once we are sure that the hash of the file didn't changed. :param authorized: The authorization to launch. If :py:class:`None` is given, we will try to guess the best value. :param protocol: The protocol describing the file to test. """ STD_AUTHORIZED: bool = False _authorized: Optional[bool] = False _protocol: Optional[dict] = None __description: list = [] __description_file: Optional[str] = None __matching_index: int = 0 continuous_integration: Optional[ContinuousIntegrationBase] = None continue_dataset: Optional[ContinueDatasetBase] = None checker_type: Optional[str] = None subject2complements: Optional[Subject2Complements] = None inputline2subject: Optional[InputLine2Subject] = None adblock_inputline2subject: Optional[AdblockInputLine2Subject] = None wildcard2subject: Optional[Wildcard2Subject] = None rpz_policy2subject: Optional[RPZPolicy2Subject] = None rpz_inputline2subject: Optional[RPZInputLine2Subject] = None url2netloc: Optional[Url2Netloc] = None cidr2subject: Optional[CIDR2Subject] = None def __init__( self, *, authorized: Optional[bool] = None, protocol: Optional[dict] = None, continuous_integration: Optional[ContinuousIntegrationBase] = None, checker_type: Optional[str] = None, adblock_inputline2subject: Optional[AdblockInputLine2Subject] = None, wildcard2subject: Optional[Wildcard2Subject] = None, rpz_policy2subject: Optional[RPZPolicy2Subject] = None, rpz_inputline2subject: Optional[RPZInputLine2Subject] = None, inputline2subject: Optional[InputLine2Subject] = None, subject2complements: Optional[Subject2Complements] = None, url2netloc: Optional[Url2Netloc] = None, continue_dataset: Optional[ContinueDatasetBase] = None, inactive_dataset: Optional[InactiveDatasetBase] = None, cidr2subject: Optional[CIDR2Subject] = None, ) -> None: if authorized is not None: self.authorized = authorized else: self.guess_and_set_authorized() if protocol is not None: self.file_path = protocol self.continuous_integration = continuous_integration self.checker_type = checker_type self.adblock_inputline2subject = adblock_inputline2subject self.wildcard2subject = wildcard2subject self.rpz_policy2subject = rpz_policy2subject self.rpz_inputline2subject = rpz_inputline2subject self.inputline2subject = inputline2subject self.subject2complements = subject2complements self.url2netloc = url2netloc self.continue_dataset = continue_dataset self.inactive_dataset = inactive_dataset self.cidr2subject = cidr2subject def execute_if_authorized(default: Any = None): # pylint: disable=no-self-argument """ Executes the decorated method only if we are authorized to process. Otherwise, apply the given :code:`default`. .. warning:: If :py:class:`None` is given as default value, this method will return the :code:`self` object. """ def inner_method(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.authorized: return func(self, *args, **kwargs) # pylint: disable=not-callable return self if default is None else default return wrapper return inner_method def ensure_protocol_is_given(func): # pylint: disable=no-self-argument """ Ensures that the protocol is given before launching the decorated method. :raise RuntimeError: When the protocol is not declared yet. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.protocol is None: raise RuntimeError(" is not given.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @property def authorized(self) -> Optional[bool]: """ Provides the current state of the :code:`_authorized` attribute. """ return self._authorized @authorized.setter def authorized(self, value: bool) -> None: """ Sets the value of the :code:`_authorized` attribute. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._authorized = value def set_authorized(self, value: bool) -> "FilePreloader": """ Sets the value of the :code:`_authorized` attribute. :param value: The value to set. """ self.authorized = value return self @property def protocol(self) -> Optional[dict]: """ Provides the current state of the :code:`_file_path` attribute. """ return self._protocol @protocol.setter def protocol(self, value: dict) -> None: """ Sets the value of the :code:`_protocol` attribute. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`dict`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, dict): raise TypeError(f" should be {str}, {type(value)} given.") self._protocol = value self.__description_file = os.path.join( self._protocol["output_dir"], PyFunceble.cli.storage.PRE_LOADER_FILE ) def set_protocol(self, value: dict) -> "FilePreloader": """ Sets the value of the :code:`_protocol` attribute. :param value: The value to set. """ self.protocol = value return self def guess_and_set_authorized(self) -> "FilePreloader": """ Try to guess and set the value of the :code:`_authorized` attribute. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if bool(PyFunceble.storage.CONFIGURATION.cli_testing.autocontinue) and bool( PyFunceble.storage.CONFIGURATION.cli_testing.preload_file ): self.authorized = True else: self.authorized = self.STD_AUTHORIZED else: self.authorized = self.STD_AUTHORIZED return self @execute_if_authorized(False) @ensure_protocol_is_given def does_preloader_description_file_exists(self) -> bool: """ Checks if our preloader file exists. """ return FileHelper(self.__description_file).exists() def __load_description(self) -> "FilePreloader": """ Loads the descriptoin into the interface. """ def set_new_dataset(*, append: bool = False, new_index: int = 0) -> None: """ Sets the default dataset into the given index. :param new_index: The index to write into. :param append: Append instead. """ new_dataset = copy.deepcopy(self.protocol) new_dataset["previous_hash"] = None new_dataset["hash"] = None new_dataset["line_number"] = 1 if append: self.__description.append(new_dataset) elif self.__description: self.__description[new_index] = new_dataset else: self.__description = [new_dataset] if self.does_preloader_description_file_exists(): dataset = DictHelper().from_json_file(self.__description_file) if not isinstance(dataset, list): dataset = [dataset] found = False for index, descr in enumerate(dataset): if all(x in descr and descr[x] == y for x, y in self.protocol.items()): self.__matching_index = index found = True break self.__description = dataset if not found: set_new_dataset(append=True) self.__matching_index = len(self.__description) - 1 else: set_new_dataset() return self def __save_description(self) -> "FilePreloader": """ Saves the description at its destination. """ self.__description[self.__matching_index].update(self.protocol) DictHelper(self.__description).to_json_file(self.__description_file) @execute_if_authorized(None) @ensure_protocol_is_given def start(self, print_dots: bool = False) -> "FilePreloader": """ Starts the pre-loading of the currently set file path. """ self.__load_description() broken = False file_helper = FileHelper(self.protocol["subject"]) self.__description[self.__matching_index]["hash"] = HashHelper().hash_file( file_helper.path ) if isinstance(self.continue_dataset, CSVContinueDataset): self.continue_dataset.set_base_directory(self.protocol["output_dir"]) if ( self.__description[self.__matching_index]["checker_type"] != self.protocol["checker_type"] or self.__description[self.__matching_index]["subject_type"] != self.protocol["subject_type"] ): try: self.continue_dataset.cleanup() except TypeError: self.continue_dataset.cleanup(session_id=self.protocol["session_id"]) if ( self.__description[self.__matching_index]["previous_hash"] and self.__description[self.__matching_index]["hash"] != self.__description[self.__matching_index]["previous_hash"] ): # Forces the reading of each lines because there is literally no # way to know where something has been changed. self.__description[self.__matching_index]["line_number"] = 1 if ( self.__description[self.__matching_index]["checker_type"] != self.protocol["checker_type"] or self.__description[self.__matching_index]["subject_type"] != self.protocol["subject_type"] or self.__description[self.__matching_index]["hash"] != self.__description[self.__matching_index]["previous_hash"] ): try: with file_helper.open("r", encoding="utf-8") as file_stream: line_num = 1 for line in file_stream: if ( line_num < self.__description[self.__matching_index]["line_number"] ): line_num += 1 continue if ( self.continuous_integration and self.continuous_integration.is_time_exceeded() ): broken = True break line = line.strip() if self.rpz_policy2subject and "SOA" in line: self.rpz_policy2subject.set_soa(line.split()[0]) for subject in get_subjects_from_line( line, self.checker_type, subject_type=self.protocol["subject_type"], adblock_inputline2subject=self.adblock_inputline2subject, wildcard2subject=self.wildcard2subject, rpz_policy2subject=self.rpz_policy2subject, rpz_inputline2subject=self.rpz_inputline2subject, inputline2subject=self.inputline2subject, subject2complements=self.subject2complements, url2netloc=self.url2netloc, cidr2subject=self.cidr2subject, ): to_send = copy.deepcopy(self.protocol) to_send["subject"] = subject to_send["idna_subject"] = domain2idna(subject) to_send["tested_at"] = datetime.now( timezone.utc ) - timedelta(days=365.25 * 20) if self.inactive_dataset.exists(to_send): print_single_line("I") continue if TesterWorker.should_be_ignored( subject=to_send["idna_subject"] ): print_single_line("X") continue self.continue_dataset.update(to_send, ignore_if_exist=True) if print_dots: print_single_line() self.__description[self.__matching_index]["line_number"] += 1 line_num += 1 except KeyboardInterrupt as exception: self.__save_description() raise exception if not broken: self.__description[self.__matching_index]["previous_hash"] = ( self.__description[self.__matching_index]["hash"] ) self.__save_description() return self PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/000077500000000000000000000000001467462152100214205ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/__init__.py000066400000000000000000000046631467462152100235420ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to our very own filesystem or output structure. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/cleanup.py000066400000000000000000000113151467462152100234220ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the cleanup of the filesystem. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from typing import List import PyFunceble.cli.facility import PyFunceble.cli.factory import PyFunceble.cli.utils.testing import PyFunceble.sessions from PyFunceble.cli.filesystem.dir_base import FilesystemDirBase from PyFunceble.database.sqlalchemy.all_schemas import Continue, Inactive from PyFunceble.helpers.file import FileHelper class FilesystemCleanup(FilesystemDirBase): """ Provides the interface for the cleanup of the filesystem. """ file_helper: FileHelper = FileHelper() def clean_database(self) -> "FilesystemCleanup": """ Cleanups the uneeded data that were stored in the database. .. warning:: This method cleans everything except the WHOIS records. """ if ( PyFunceble.cli.facility.CredentialLoader.is_already_loaded() and self.db_session ): to_clean = [Continue, Inactive] for orm_obj in to_clean: # pylint: disable=line-too-long with PyFunceble.cli.factory.DBSession.get_db_session() as db_session: db_session.query(orm_obj).delete(synchronize_session=False) db_session.commit() PyFunceble.facility.Logger.info( "Deleted all entries in %r.", orm_obj ) @property def output_files_to_delete(self) -> List[str]: """ Provides the list of output files to delete. """ result = [] files_to_ignore = [".gitignore", ".keep", ".gitkeep"] for root, _, files in os.walk(self.get_output_basedir()): for file in files: if file in files_to_ignore: continue result.append(os.path.join(root, file)) return result def clean_output_files(self) -> "FilesystemCleanup": """ Cleanups the unneeded files from the output directory. """ for file in self.output_files_to_delete: self.file_helper.set_path(file).delete() PyFunceble.facility.Logger.debug("Deleted: %r.", file) return self def start(self) -> "FilesystemCleanup": """ Starts the cleanup of everything unneeded. """ self.clean_output_files() return self PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/counter.py000066400000000000000000000154631467462152100234620ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to our counter tracker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy from typing import Dict, List, Tuple, Union import PyFunceble.cli.storage import PyFunceble.cli.utils.testing import PyFunceble.storage from PyFunceble.checker.status_base import CheckerStatusBase from PyFunceble.cli.filesystem.json_base import FilesystemJSONBase from PyFunceble.helpers.list import ListHelper class FilesystemCounter(FilesystemJSONBase): """ Provides our counter. """ STD_DATASET: Dict[str, int] = { "counter": { PyFunceble.storage.STATUS.up: 0, PyFunceble.storage.STATUS.valid: 0, PyFunceble.storage.STATUS.sane: 0, PyFunceble.storage.STATUS.down: 0, PyFunceble.storage.STATUS.malicious: 0, PyFunceble.storage.STATUS.invalid: 0, "total": 0, }, "percentage": { PyFunceble.storage.STATUS.up: 0, PyFunceble.storage.STATUS.valid: 0, PyFunceble.storage.STATUS.sane: 0, PyFunceble.storage.STATUS.down: 0, PyFunceble.storage.STATUS.malicious: 0, PyFunceble.storage.STATUS.invalid: 0, "total": 0, }, } PERCENTAGE_STATUSES: Dict[str, List[str]] = { "SYNTAX": [ PyFunceble.storage.STATUS.valid, PyFunceble.storage.STATUS.invalid, ], "REPUTATION": [ PyFunceble.storage.STATUS.sane, PyFunceble.storage.STATUS.malicious, ], "AVAILABILITY": [ PyFunceble.storage.STATUS.up, PyFunceble.storage.STATUS.down, PyFunceble.storage.STATUS.invalid, ], } SOURCE_FILE: str = PyFunceble.cli.storage.COUNTER_FILE @FilesystemJSONBase.fetch_dataset_beforehand def get_sorted_dataset(self) -> List[Tuple[str, float]]: """ Provides the datasets in a sorted manner. """ return ( ListHelper( [(x, y) for x, y in self.dataset["percentage"].items() if x != "total"] ) .custom_sort(key_method=lambda x: x[-1], reverse=True) .subject ) @FilesystemJSONBase.fetch_dataset_beforehand def get_dataset_for_printer(self) -> List[Dict[str, Union[str, int]]]: """ Provides the dataset that the printer may understand. :raise ValueError: When the current testing mode is not supported (yet?). """ result = {} testing_mode = PyFunceble.cli.utils.testing.get_testing_mode() if testing_mode not in self.PERCENTAGE_STATUSES: raise ValueError(" ({testing_mode!r}) is not supported.") for status, value in self.dataset["counter"].items(): if ( status == "total" or status not in self.PERCENTAGE_STATUSES[testing_mode] ): continue result[status] = {"status": status, "amount": value} for status, value in self.dataset["percentage"].items(): if ( status == "total" or status not in self.PERCENTAGE_STATUSES[testing_mode] ): continue result[status]["percentage"] = f"{round(value)}%" # Apply the right order. return [result[x] for x in self.PERCENTAGE_STATUSES[testing_mode]] @FilesystemJSONBase.update_source_file_path_beforehand @FilesystemJSONBase.fetch_dataset_beforehand @FilesystemJSONBase.save_dataset_afterwards def count(self, status: CheckerStatusBase) -> "FilesystemCounter": """ Starts the counting process. :param status: The status to count into our dataset. """ if not isinstance(status, CheckerStatusBase): raise TypeError( f" should be {CheckerStatusBase}, {type(status)} given." ) if "counter" not in self.dataset: self.dataset = copy.deepcopy(self.STD_DATASET) self.dataset["counter"][status.status] += 1 self.dataset["counter"]["total"] += 1 for key in self.dataset["percentage"]: if key == "total": continue self.dataset["percentage"][key] = ( self.dataset["counter"][key] * 100 ) / self.dataset["counter"]["total"] self.dataset["percentage"]["total"] = sum( y for x, y in self.dataset["percentage"].items() if x != "total" ) return self PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/dir_base.py000066400000000000000000000145601467462152100235500ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides a common base to the manipulation of the output directory. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from typing import Optional, Union import PyFunceble.cli.storage from PyFunceble.database.session import DBSession from PyFunceble.helpers.directory import DirectoryHelper class FilesystemDirBase: """ Provides a common base for the manipulation of our output directory. """ _parent_dirname: Optional[str] = None db_session: Optional[DBSession] = None # Setting this to true will let you differ to the inline directory. _differ_to_inline: bool = False INLINE_DEST: str = "_inline_" def __init__( self, parent_dirname: Optional[str] = None, *, db_session: Optional[DBSession] = None, ) -> None: if parent_dirname is not None: self.parent_dirname = parent_dirname else: self.parent_dirname = PyFunceble.cli.storage.STD_PARENT_DIRNAME self.db_session = db_session @property def parent_dirname(self) -> Optional[str]: """ Provides the current state of the :code:`_parent_dirname` attribute. """ return self._parent_dirname @parent_dirname.setter def parent_dirname(self, value: Union[str, None]) -> None: """ Sets the parent dirname. The parent dirname is a directory which acts a parent into the output directory. :parm value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str` or :py:class:`None`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, (str, type(None))): raise TypeError(f" should be {str}, {type(value)} given.") if value is not None and not value: raise ValueError(" should not be empty.") self._parent_dirname = value def set_parent_dirname(self, value: str) -> "FilesystemDirBase": """ Sets the parent dirname. The parent dirname is a directory which acts a parent into the output directory. :parm value: The value to set. """ self.parent_dirname = value return self @property def differ_to_inline(self) -> bool: """ Provides the current state of the :code:`_differ_to_inline` attribute. """ return self._differ_to_inline @differ_to_inline.setter def differ_to_inline(self, value: bool) -> None: """ Allows/Disallow the split to the inline directory. The attribute can be set when you want to overwrite the behavior of the :code:`get_output_basedir` method. :parm value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._differ_to_inline = value def set_differ_to_inline(self, value: bool) -> "FilesystemDirBase": """ Allows/Disallow the split to the inline directory. The attribute can be set when you want to overwrite the behavior of the :code:`get_output_basedir` method. :parm value: The value to set. """ self.differ_to_inline = value return self def get_output_basedir(self) -> str: """ Provides the output base directory. :param create_if_missing: Authorizes the creation of the directory if it's missing. """ if self.parent_dirname: result = os.path.join( PyFunceble.cli.storage.OUTPUT_DIRECTORY, self.parent_dirname ) elif self.differ_to_inline: result = os.path.join( PyFunceble.cli.storage.OUTPUT_DIRECTORY, self.INLINE_DEST ) else: result = PyFunceble.cli.storage.OUTPUT_DIRECTORY DirectoryHelper(result).create() return result PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/dir_structure/000077500000000000000000000000001467462152100243165ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/dir_structure/__init__.py000066400000000000000000000046731467462152100264410ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the generation of backup of the directory structure. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/dir_structure/backup.py000066400000000000000000000102721467462152100261370ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an interface for the backup of the directory structure. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import PyFunceble.facility from PyFunceble.cli.filesystem.dir_structure.base import DirectoryStructureBase from PyFunceble.helpers.dict import DictHelper from PyFunceble.helpers.directory import DirectoryHelper from PyFunceble.helpers.file import FileHelper from PyFunceble.helpers.hash import HashHelper class DirectoryStructureBackup(DirectoryStructureBase): """ Provides the base of all dir structure classes. """ def get_backup_data(self) -> dict: """ Provides the data which acts as a backup. """ result = {} base_dir = self.get_output_basedir() file_helper = FileHelper() hash_helper = HashHelper() for file in DirectoryHelper(base_dir).list_all_files(): file_helper.set_path(file) reduced_path = self.get_path_without_base_dir(file) directory, filename = reduced_path.rsplit(os.sep, 1) file_hash = hash_helper.hash_file(file_helper.path) dataset = {filename: {"content": file_helper.read(), "hash": file_hash}} if directory not in result: result[directory] = dataset else: result[directory].update(dataset) PyFunceble.facility.Logger.debug("Dir Structure to backup:\n%r", result) return result def store_backup(self) -> "DirectoryStructureBackup": """ Stores the backup at the current destination. """ DictHelper(self.get_backup_data()).to_json_file(self.source_file) PyFunceble.facility.Logger.info("Stored backup into: %r", self.source_file) return self def start(self) -> "DirectoryStructureBackup": """ Starts the backup process. """ return self.cleanup().store_backup() PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/dir_structure/base.py000066400000000000000000000123621467462152100256060ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all directory structure classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from typing import Optional try: import importlib.resources as package_resources except ImportError: # pragma: no cover ## Retro compatibility import importlib_resources as package_resources import PyFunceble.storage from PyFunceble.cli.filesystem.cleanup import FilesystemCleanup from PyFunceble.cli.filesystem.dir_base import FilesystemDirBase class DirectoryStructureBase(FilesystemDirBase): """ Provides the base of all dir structure classes. """ std_source_file: Optional[str] = None _source_file: Optional[str] = None def __init__( self, parent_dirname: Optional[str] = None, source_file: Optional[str] = None ) -> None: with package_resources.path( "PyFunceble.data.infrastructure", PyFunceble.storage.DISTRIBUTED_DIR_STRUCTURE_FILENAME, ) as file_path: self.std_source_file = str(file_path) if source_file is not None: self.source_file = source_file else: self.source_file = self.std_source_file super().__init__(parent_dirname=parent_dirname) @property def source_file(self) -> Optional[str]: """ Provides the current state of the :code:`_source_file` attribute. """ return self._source_file @source_file.setter def source_file(self, value: str) -> None: """ Sets the value of the source file to use. :param value: The value to set. :raise TypeError: When the given value is not a :py:class:`str`. :raise ValueError: When the given value is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._source_file = value def set_source_file(self, value: str) -> "DirectoryStructureBase": """ Sets the value of the source file to use. :param value: The value to set. """ self.source_file = value return self def get_path_without_base_dir(self, full_path: str) -> str: """ Given a full path, we remove the base dir. """ to_replace = os.path.join(self.get_output_basedir(), "") return full_path.replace(to_replace, "") def cleanup(self) -> "DirectoryStructureBase": """ Cleans the output directory. """ FilesystemCleanup(self.parent_dirname).clean_output_files() return self def get_backup_data(self) -> dict: """ Provides the data to manipulate. """ raise NotImplementedError() def start(self) -> "DirectoryStructureBase": """ Starts the whole process. """ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/dir_structure/restore.py000066400000000000000000000133551467462152100263620ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an interface for the backup of the directory structure. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import PyFunceble.cli.storage from PyFunceble.cli.filesystem.dir_structure.base import DirectoryStructureBase from PyFunceble.helpers.dict import DictHelper from PyFunceble.helpers.directory import DirectoryHelper from PyFunceble.helpers.file import FileHelper from PyFunceble.utils.platform import PlatformUtility class DirectoryStructureRestoration(DirectoryStructureBase): """ Provides the base of all dir structure classes. """ def get_backup_data(self) -> dict: """ Stores the backup at the current destination. """ data = DictHelper().from_json_file(self.source_file) if PlatformUtility.is_windows(): result = {} for directory, files in data.items(): result[os.path.normpath(directory)] = files PyFunceble.facility.Logger.debug("Backup (read) data:\n%r", result) return result PyFunceble.facility.Logger.debug("Backup (read) data:\n%r", data) return data def restore_from_backup(self) -> "DirectoryStructureRestoration": """ Restores or reconstruct the output directory. """ # pylint: disable=too-many-locals PyFunceble.facility.Logger.info( "Started restoration of the directory structure" ) backup = self.get_backup_data() base_dir = self.get_output_basedir() dir_helper = DirectoryHelper() file_helper = FileHelper() if dir_helper.set_path(base_dir).exists(): for root, _, files in os.walk(dir_helper.path): reduced_path = self.get_path_without_base_dir(root) if reduced_path not in backup and root != reduced_path: dir_helper.set_path(root).delete() PyFunceble.facility.Logger.debug( "Added %r into the list of directories to delete. " "Reason: not found in own dataset.", root, ) continue for directory, files in backup.items(): dir_helper.set_path(os.path.join(base_dir, directory)).create() for file, dataset in files.items(): file_full_path = os.path.join(dir_helper.path, file) if ( file == ".gitignore" and PyFunceble.cli.storage.STD_PARENT_DIRNAME not in file_full_path ): to_delete = file_full_path file_helper.set_path(to_delete).delete() PyFunceble.facility.Logger.debug( "(If exists) Deleted: %r. Reason: We are going to " "replace it with .gitkeep", to_delete, ) file_full_path = file_full_path.replace(".gitignore", ".gitkeep") file_helper.set_path(file_full_path) if not file_helper.exists(): file_helper.write(dataset["content"], overwrite=True) PyFunceble.facility.Logger.info( "Finished restoration of the directory structure" ) return self def start(self) -> "DirectoryStructureRestoration": """ Starts the restoration process. """ return self.cleanup().restore_from_backup() PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/json_base.py000066400000000000000000000114641467462152100237430ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides a base for the manipulation of JSON files. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy import functools import os from typing import Dict, Optional, Union from PyFunceble.cli.filesystem.dir_base import FilesystemDirBase from PyFunceble.helpers.dict import DictHelper from PyFunceble.helpers.file import FileHelper class FilesystemJSONBase(FilesystemDirBase): """ A base interface for the manipulation of JSON files. """ dataset: Dict[str, int] = {} source_file_path: Optional[str] = None SOURCE_FILE: Optional[str] = None STD_DATASET: Union[dict, list] = {} def update_source_file_path_beforehand(func): # pylint: disable=no-self-argument """ Updates the source file before launching the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): self.source_file_path = os.path.join( self.get_output_basedir(), self.SOURCE_FILE ) return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def fetch_dataset_beforehand(func): # pylint: disable=no-self-argument """ Updates the dataset to work with before launching the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): self.fetch_dataset() return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def save_dataset_afterwards(func): # pylint: disable=no-self-argument """ Saves the dataset after launching the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) # pylint: disable=not-callable self.save_dataset() return result return wrapper @update_source_file_path_beforehand def fetch_dataset(self) -> "FilesystemJSONBase": """ Fetch the dataset from the source file. """ file_helper = FileHelper(self.source_file_path) if file_helper.exists(): self.dataset = DictHelper().from_json_file(file_helper.path) else: self.dataset = copy.deepcopy(self.STD_DATASET) return self def save_dataset(self) -> "FilesystemJSONBase": """ Saves the current dataset into it's final destination. """ DictHelper(self.dataset).to_json_file(self.source_file_path) return self PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/printer/000077500000000000000000000000001467462152100231035ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/printer/__init__.py000066400000000000000000000046641467462152100252260ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to what we actually print (output) or to a file. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/printer/base.py000066400000000000000000000277331467462152100244030ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our printers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy import functools import string from typing import Dict, List, Optional class PrinterBase: """ Provides the base of all printer class. Printer classes are classes which derivate from this class. their objectives should be the same: Unify and simplify the way to print something to a given destination. """ STD_UNKNOWN: str = "Unknown" STD_LENGTH: Dict[str, int] = { "idna_subject": 100, "status": 11, "status_source": 10, "http_status_code": 10, "percentage": 12, "expiration_date": 17, "amount": 12, "checker_type": 13, "days": 2, "hours": 2, "minutes": 2, "seconds": 6, "registrar": 30, } TEMPLATES: Dict[str, string.Template] = { "all": string.Template( "$idna_subject $status $status_source $expiration_date $registrar " "$http_status_code $checker_type" ), "less": string.Template("$idna_subject $status $status_source"), "simple": string.Template("$idna_subject $status"), "percentage": string.Template("$status $percentage $amount"), "hosts": string.Template("$ip $idna_subject"), "plain": string.Template("$idna_subject"), "execution_time": string.Template( "\nExecution Time: $days:$hours:$minutes:$seconds\n" ), "registrar": string.Template("$registrar $percentage $amount"), } HEADERS: Dict[str, str] = { "idna_subject": "Subject", "status": "Status", "status_source": "Source", "http_status_code": "HTTP Code", "expiration_date": "Expiration Date", "percentage": "Percentage", "amount": "Amount", "ip": "IP", "checker_type": "Checker", "days": "Days", "hours": "Hours", "minutes": "Minutes", "seconds": "Seconds", "registrar": "Registrar", } _template_to_use: Optional[str] = None _dataset: Optional[Dict[str, str]] = None _skip_column: Optional[List[str]] = [] def __init__( self, template_to_use: Optional[str] = None, *, dataset: Optional[Dict[str, str]] = None, skip_column: Optional[List[str]] = None, ) -> None: if template_to_use is not None: self.template_to_use = template_to_use if dataset is not None: self.dataset = dataset if skip_column is not None: self.skip_column = skip_column def ensure_template_to_use_is_given(func): # pylint: disable=no-self-argument """ Ensures that the template to use is given before launching the decorated method. :raise TypeError: When the current :code:`self.template_to_use` is not set. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.template_to_use, str): raise TypeError(" is not given.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def ensure_dataset_is_given(func): # pylint: disable=no-self-argument """ Ensures that the dataset to write is given before launching the decorated method. :raise TypeError: When the current :code:`self.template_to_use` is not set. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.dataset, dict): raise TypeError(" is not given.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @property def skip_column(self) -> Optional[List[str]]: """ Provides the current state of the :code:`_skip_column` attribute. """ return self._skip_column @skip_column.setter def skip_column(self, value: List[str]) -> None: """ Sets the columns to skip. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`list`. """ if not isinstance(value, list): raise TypeError(f" should be {list}, {type(value)} given.") if any(not isinstance(x, str) for x in value): raise TypeError(f" should be a list of {str}, {type(value)} given.") self._skip_column = value def set_skip_column(self, value: List[str]) -> "PrinterBase": """ Sets the columns to skip. :param value: The value to set. """ self.skip_column = value return self @property def template_to_use(self) -> Optional[str]: """ Provides the current state of the :code:`_template_to_use` attribute. """ return self._template_to_use @template_to_use.setter def template_to_use(self, value: str) -> None: """ Sets the template to use. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is not supported. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if value not in self.TEMPLATES: raise ValueError( f" ({value!r}) is not supported " f"({list(self.TEMPLATES.keys())!r})." ) self._template_to_use = value def set_template_to_use(self, value: str) -> "PrinterBase": """ Sets the template to use. :param value: The value to set. """ self.template_to_use = value return self @property def dataset(self) -> Optional[Dict[str, str]]: """ Provides the current state of the :code:`_dataset` attribute. """ return self._dataset @dataset.setter def dataset(self, value: Dict[str, str]) -> None: """ Sets the dataset to apply to the template. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`dict` :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, dict): raise TypeError(f" should be {dict}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._dataset = copy.deepcopy(value) def set_dataset(self, value: Dict[str, str]) -> "PrinterBase": """ Sets the dataset to apply to the template. :param value: The value to set. """ self.dataset = value return self @ensure_template_to_use_is_given def get_header_to_print(self) -> str: """ Provides the template header to print. """ ignore_header = ["simple", "hosts", "plain", "execution_time"] to_print_data = [dict(), dict()] # pylint: disable=use-dict-literal if self.template_to_use not in ignore_header: for key, value in self.HEADERS.items(): if key not in self.TEMPLATES[self.template_to_use].template: continue if key in self.skip_column: self.TEMPLATES[self.template_to_use].template = self.TEMPLATES[ self.template_to_use ].template.replace(f"${key} ", "") continue to_print_data[0][key] = f"{value:<{self.STD_LENGTH[key]}}" for key, value in to_print_data[0].items(): to_print_data[1][key] = "-" * len(value) to_print = [ self.TEMPLATES[self.template_to_use].safe_substitute( **to_print_data[0] ), self.TEMPLATES[self.template_to_use].safe_substitute( **to_print_data[1] ), ] return "\n".join(to_print) return "" @ensure_template_to_use_is_given @ensure_dataset_is_given def get_line_to_print(self) -> str: """ Provides the line to print. """ to_print = {} ignore_length = ["simple", "hosts", "plain", "execution_time"] for key, value in self.dataset.items(): if key not in self.HEADERS or key in self.skip_column: continue if not value and value != 0: value = self.STD_UNKNOWN if self.template_to_use not in ignore_length: to_print[key] = f"{value:<{self.STD_LENGTH[key]}}" else: to_print[key] = value missings = [ x[1:] for x in self.TEMPLATES[self.template_to_use].template.split() if x.startswith("$") and x[1:] not in to_print ] for missing in missings: try: to_print[missing] = f"{self.STD_UNKNOWN:<{self.STD_LENGTH[missing]}}" except KeyError: # Example: execution time pass return self.TEMPLATES[self.template_to_use].safe_substitute(**to_print) def print_header(self) -> None: """ Prints the header. """ header = self.get_header_to_print() if header: print(f"\n\n{header}") def print_interpolated_line(self) -> None: """ Prints the line where we are suppose to write it. """ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/printer/file.py000066400000000000000000000153121467462152100243760ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the file printer. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from datetime import datetime, timezone from typing import Dict, Optional import PyFunceble.facility import PyFunceble.storage from PyFunceble.cli.filesystem.printer.base import PrinterBase from PyFunceble.helpers.file import FileHelper class FilePrinter(PrinterBase): """ Provides the file printer. """ STD_FILE_GENERATION: str = ( f"# Generated by {PyFunceble.storage.PROJECT_NAME} " f"(v{PyFunceble.storage.PROJECT_VERSION.split()[0]}) " f"/ {PyFunceble.storage.SHORT_REPO_LINK}\n" ) file_helper: FileHelper = FileHelper() _destination: Optional[str] = None allow_coloration: bool = True def __init__( self, template_to_use: Optional[str] = None, *, dataset: Optional[Dict[str, str]] = None, destination: Optional[str] = None, **kwargs, ) -> None: if destination is not None: self.destination = destination super().__init__(template_to_use=template_to_use, dataset=dataset, **kwargs) def ensure_destination_is_given(func): # pylint: disable=no-self-argument """ Ensures that the destination is given before launching the decorated method. :raise TypeError: When the current :code:`self.template_to_use` is not set. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.destination, str): raise TypeError(" is not given.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def propagate_destination(func): # pylint: disable=no-self-argument """ Propagates the new value of the destination just after launching the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) # pylint: disable=not-callable self.file_helper.set_path(self.destination) return result return wrapper @property def destination(self) -> Optional[str]: """ Provides the current state of the :code:`_destination` attribute. """ return self._destination @destination.setter @propagate_destination def destination(self, value: str) -> None: """ Sets the destination to use. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When teh given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._destination = value def set_destination(self, value: str) -> "FilePrinter": """ Sets the destination to use. :param value: The value to set. """ self.destination = value return self @staticmethod def get_generation_date_line() -> str: """ Provides the line which informs of the date a file was generated. """ return f"# Date of generation: {datetime.now(timezone.utc).isoformat()}" @ensure_destination_is_given def print_interpolated_line(self) -> None: """ Prints the interpolated line into the destination. """ PyFunceble.facility.Logger.info( "Started to write into %r.", self.file_helper.path ) line_to_print = self.get_line_to_print() + "\n" without_header = ["hosts", "plain"] PyFunceble.facility.Logger.debug("Line to print: %r", line_to_print) if not self.file_helper.exists(): self.file_helper.write(self.STD_FILE_GENERATION, overwrite=True) self.file_helper.write(self.get_generation_date_line()) self.file_helper.write("\n\n") if self.template_to_use not in without_header: self.file_helper.write(self.get_header_to_print()) self.file_helper.write("\n") self.file_helper.write(line_to_print) PyFunceble.facility.Logger.info( "Finished to write into %r.", self.file_helper.path ) PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/printer/stdout.py000066400000000000000000000170171467462152100250050ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the stdout printer. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Dict, List, Optional import colorama import PyFunceble.facility import PyFunceble.storage from PyFunceble.cli.filesystem.printer.base import PrinterBase class StdoutPrinter(PrinterBase): """ Provides the stdout printer. """ STD_FILE_HEADER: str = ( f"# Generated by {PyFunceble.storage.PROJECT_NAME} " f"(v{PyFunceble.storage.PROJECT_VERSION.split()[0]}) " f"/ {PyFunceble.storage.SHORT_REPO_LINK}\n" ) STD_ALLOW_COLORATION: bool = True STATUS2BACKGROUND_COLOR: Dict[str, str] = { PyFunceble.storage.STATUS.up: f"{colorama.Fore.BLACK}{colorama.Back.GREEN}", PyFunceble.storage.STATUS.valid: f"{colorama.Fore.BLACK}" f"{colorama.Back.GREEN}", PyFunceble.storage.STATUS.sane: f"{colorama.Fore.BLACK}" f"{colorama.Back.GREEN}", PyFunceble.storage.STATUS.down: f"{colorama.Fore.BLACK}{colorama.Back.RED}", PyFunceble.storage.STATUS.malicious: f"{colorama.Fore.BLACK}" f"{colorama.Back.RED}", PyFunceble.storage.STATUS.invalid: f"{colorama.Fore.BLACK}" f"{colorama.Back.CYAN}", } STATUS2FORGROUND_COLOR: Dict[str, str] = { PyFunceble.storage.STATUS.up: f"{colorama.Style.BRIGHT}" f"{colorama.Fore.GREEN}", PyFunceble.storage.STATUS.valid: f"{colorama.Style.BRIGHT}" f"{colorama.Fore.GREEN}", PyFunceble.storage.STATUS.sane: f"{colorama.Style.BRIGHT}" f"{colorama.Fore.GREEN}", PyFunceble.storage.STATUS.down: f"{colorama.Style.BRIGHT}" f"{colorama.Fore.RED}", PyFunceble.storage.STATUS.malicious: f"{colorama.Style.BRIGHT}" f"{colorama.Fore.RED}", PyFunceble.storage.STATUS.invalid: f"{colorama.Style.BRIGHT}" f"{colorama.Fore.CYAN}", } BACKGROUND_COLORATED: List[str] = ["all", "less"] FOREGROUND_COLORATED: List[str] = ["percentage", "simple"] _allow_coloration: bool = True def __init__( self, template_to_use: Optional[str] = None, *, dataset: Optional[Dict[str, str]] = None, allow_coloration: Optional[bool] = None, **kwargs, ) -> None: if allow_coloration is not None: self.allow_coloration = allow_coloration else: self.guess_allow_coloration() super().__init__(template_to_use=template_to_use, dataset=dataset, **kwargs) @property def allow_coloration(self) -> bool: """ Provides the current state of the :code:`_allow_coloration` attribute. """ return self._allow_coloration @allow_coloration.setter def allow_coloration(self, value: bool) -> Optional[bool]: """ Sets the authorization to use the coloration. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When teh given :code:`value` is empty. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._allow_coloration = value def set_allow_coloration(self, value: bool) -> "StdoutPrinter": """ Sets the authorization to use the coloration. :param value: The value to set. """ self.allow_coloration = value return self def guess_allow_coloration(self) -> "StdoutPrinter": """ Try to guess and set the :code:`allow_coloration` attribute. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.allow_coloration = ( PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.colour ) else: self.allow_coloration = self.STD_ALLOW_COLORATION def print_interpolated_line(self): """ Prints the interpolated line into the destination. """ PyFunceble.facility.Logger.info("Started to print to stdout.") line_to_print = self.get_line_to_print() PyFunceble.facility.Logger.debug("Line to print: %r", line_to_print) if "status" in self.dataset: status_to_compare = self.dataset["status"] if self.allow_coloration: if self.template_to_use in self.BACKGROUND_COLORATED: print( f"{self.STATUS2BACKGROUND_COLOR[status_to_compare]}" f"{line_to_print}" ) elif self.template_to_use in self.FOREGROUND_COLORATED: print( f"{self.STATUS2FORGROUND_COLOR[status_to_compare]}" f"{line_to_print}" ) else: print(line_to_print) else: print(line_to_print) elif self.template_to_use == "execution_time": if self.allow_coloration: print(f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}{line_to_print}") else: print(line_to_print) else: print(line_to_print) PyFunceble.facility.Logger.info("Finished to print to stdout.") PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/registrar_counter.py000066400000000000000000000131341467462152100255350ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the registrar counter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Dict, List, Optional, Union import PyFunceble.cli.storage from PyFunceble.cli.filesystem.json_base import FilesystemJSONBase from PyFunceble.helpers.list import ListHelper class RegistrarCounter(FilesystemJSONBase): """ Provides our registrar stats counter. """ STD_DATASET: Dict[str, int] = { "counter": { "total": 0, }, "percentage": {"total": 0}, } SUPPORTED_TEST_MODES: List[str] = ["AVAILABILITY"] SOURCE_FILE: str = PyFunceble.cli.storage.REGISTRAR_COUNTER_FILE @FilesystemJSONBase.fetch_dataset_beforehand def get_dataset_for_printer( self, *, limit: Optional[int] = 15 ) -> List[Dict[str, Union[str, int]]]: """ Provides the dataset that the printer may understand. :param limit: Maximum number of registrars to display. .. warning:: If set to :code:`None`, all registrars will be displayed. :raise ValueError: When the current testing mode is not supported (yet?). """ result = {} testing_mode = PyFunceble.cli.utils.testing.get_testing_mode() if testing_mode not in self.SUPPORTED_TEST_MODES: raise ValueError(" ({testing_mode!r}) is not supported.") for registrar, value in self.dataset["counter"].items(): if registrar == "total": continue result[registrar] = {"registrar": registrar, "amount": value} for registrar, value in self.dataset["percentage"].items(): if registrar == "total": continue result[registrar]["percentage"] = f"{round(value)}%" # Apply the right order. result = ( ListHelper([y for _, y in result.items()]) .custom_sort(key_method=lambda x: x["amount"], reverse=True) .subject ) return result[:limit] if limit else result @FilesystemJSONBase.update_source_file_path_beforehand @FilesystemJSONBase.fetch_dataset_beforehand @FilesystemJSONBase.save_dataset_afterwards def count(self, registrar: str) -> "RegistrarCounter": """ Starts the counting process. :param registrar: The registrar to count into our dataset. """ if not isinstance(registrar, str): raise TypeError(f" should be {str}, {type(registrar)} given.") if registrar not in self.dataset["counter"]: self.dataset["counter"][registrar] = 1 else: self.dataset["counter"][registrar] += 1 self.dataset["counter"]["total"] += 1 self.dataset["percentage"][registrar] = ( self.dataset["counter"][registrar] * 100 ) / self.dataset["counter"]["total"] for key in self.dataset["percentage"]: if key in ("total", registrar): continue self.dataset["percentage"][key] = ( self.dataset["counter"][key] * 100 ) / self.dataset["counter"]["total"] self.dataset["percentage"]["total"] = sum( y for x, y in self.dataset["percentage"].items() if x != "total" ) return self PyFunceble-4.2.29.dev/PyFunceble/cli/filesystem/status_file.py000066400000000000000000000600761467462152100243250ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to our status file generation. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools import os from typing import Optional, Union import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.storage from PyFunceble.checker.availability.status import AvailabilityCheckerStatus from PyFunceble.checker.reputation.status import ReputationCheckerStatus from PyFunceble.checker.status_base import CheckerStatusBase from PyFunceble.checker.syntax.status import SyntaxCheckerStatus from PyFunceble.cli.filesystem.dir_base import FilesystemDirBase from PyFunceble.cli.filesystem.dir_structure.restore import ( DirectoryStructureRestoration, ) from PyFunceble.cli.filesystem.printer.file import FilePrinter from PyFunceble.helpers.directory import DirectoryHelper from PyFunceble.utils.platform import PlatformUtility class StatusFileGenerator(FilesystemDirBase): """ Provides an interface for the generation of the status file from a given status. """ # pylint: disable=too-many-public-methods STD_HOSTS_IP: str = "0.0.0.0" STD_ALLOW_HOSTS_FILES: bool = True STD_ALLOW_PLAIN_FILES: bool = True STD_ALLOW_ANALYTIC_FILES: bool = True STD_ALLOW_UNIFIED_FILE: bool = False file_printer: FilePrinter = FilePrinter() _test_dataset: Optional[dict] = None _status: Optional[ Union[SyntaxCheckerStatus, AvailabilityCheckerStatus, ReputationCheckerStatus] ] = None _allow_hosts_files: bool = True _allow_plain_files: bool = True _allow_analytic_files: bool = True _allow_unified_file: bool = False _hosts_ip: Optional[str] = None def __init__( self, status: Optional[ Union[ SyntaxCheckerStatus, AvailabilityCheckerStatus, ReputationCheckerStatus ] ] = None, *, allow_hosts_files: Optional[bool] = None, allow_plain_files: Optional[bool] = None, allow_analytic_files: Optional[bool] = None, hosts_ip: Optional[str] = None, allow_unified_file: Optional[bool] = None, parent_dirname: Optional[str] = None, test_dataset: Optional[dict] = None, ) -> None: if status is not None: self.status = status if allow_hosts_files is not None: self.allow_hosts_files = allow_hosts_files else: self.guess_and_set_allow_hosts_files() if allow_plain_files is not None: self.allow_plain_files = allow_plain_files else: self.guess_and_set_allow_plain_files() if allow_analytic_files is not None: self.allow_analytic_files = allow_analytic_files else: self.guess_and_set_allow_analytic_files() if hosts_ip is not None: self.hosts_ip = hosts_ip else: self.guess_and_set_hosts_ip() if allow_unified_file is not None: self.allow_unified_file = allow_unified_file else: self.guess_and_set_allow_unified_file() if test_dataset is not None: self.test_dataset = test_dataset super().__init__(parent_dirname=parent_dirname) def ensure_status_is_given(func): # pylint: disable=no-self-argument """ Ensures that the status is given before launching the decorated method. :raise TypeError: When :code:`self.status` is not set. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance( self.status, CheckerStatusBase, ): raise TypeError(" is not given.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @property def status(self) -> CheckerStatusBase: """ Provides the current state of the :code:`_status` attribute. """ return self._status @status.setter def status(self, value: CheckerStatusBase) -> None: """ Sets the status to work with. :param value: The value to set. :raise TypeError: When the given value is not a :class`~ PyFunceble.checker.syntax.status.SyntaxCheckerStatus`, :class:`~PyFunceble.checker.availability.status.AvailabilityCheckerStatus` or :class:`~PyFunceble.checker.reputation.status.ReputationCheckerStatus` """ if not isinstance( value, CheckerStatusBase, ): raise TypeError( f" should be {CheckerStatusBase}, {type(value)} given." ) self._status = value def set_status( self, value: CheckerStatusBase, ) -> "StatusFileGenerator": """ Sets the status to work with. :param value: The value to set. """ self.status = value return self @property def test_dataset(self) -> Optional[dict]: """ Provides the current state of the :code:`_test_dataset` attribute. """ return self._test_dataset @test_dataset.setter def test_dataset(self, value: dict) -> None: """ Sets the test dataset which was given to the tester. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class`dict`. """ if not isinstance(value, dict): raise TypeError(f" should be {dict}, {type(value)} given.") self._test_dataset = value def set_test_dataset(self, value: dict) -> "StatusFileGenerator": """ Sets the test dataset which was given to the tester. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class`dict`. """ self.test_dataset = value return self @property def allow_hosts_files(self) -> bool: """ Provides the current state of the :code:`_allow_hosts_files` attribute. """ return self._allow_hosts_files @allow_hosts_files.setter def allow_hosts_files(self, value: bool) -> None: """ Sets the authorization to generation of hosts files. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._allow_hosts_files = value def set_allow_hosts_files(self, value: bool) -> "StatusFileGenerator": """ Sets the authorization to generation of hosts files. :param value: The value to set. """ self.allow_hosts_files = value return self def guess_and_set_allow_hosts_files(self) -> "StatusFileGenerator": """ Tries to guess the value of the :code:`allow_hosts_files` from the configuration file. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.allow_hosts_files = ( PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.hosts ) else: self.allow_hosts_files = self.STD_ALLOW_HOSTS_FILES @property def allow_plain_files(self) -> bool: """ Provides the current state of the :code:`_allow_plain_file` attribute. """ return self._allow_plain_files @allow_plain_files.setter def allow_plain_files(self, value: bool) -> None: """ Sets the authorization to generation of plain files. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._allow_plain_files = value def set_allow_plain_files(self, value: bool) -> "StatusFileGenerator": """ Sets the authorization to generation of plain files. :param value: The value to set. """ self.allow_plain_files = value return self def guess_and_set_allow_plain_files(self) -> "StatusFileGenerator": """ Tries to guess the value of the :code:`allow_plain_files` from the configuration file. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.allow_plain_files = ( PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.plain ) else: self.allow_plain_files = self.STD_ALLOW_PLAIN_FILES @property def allow_analytic_files(self) -> bool: """ Provides the current state of the :code:`_allow_analytic_files` attribute. """ return self._allow_analytic_files @allow_analytic_files.setter def allow_analytic_files(self, value: bool) -> None: """ Sets the authorization to generation of analytic files. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._allow_analytic_files = value def set_allow_analytic_files(self, value: bool) -> "StatusFileGenerator": """ Sets the authorization to generation of analytic files. :param value: The value to set. """ self.allow_analytic_files = value return self def guess_and_set_allow_analytic_files(self) -> "StatusFileGenerator": """ Tries to guess the value of the :code:`allow_analytic_files` from the configuration file. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.allow_analytic_files = ( PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.analytic ) else: self.allow_analytic_files = self.STD_ALLOW_ANALYTIC_FILES @property def hosts_ip(self) -> Optional[str]: """ Provides the current state of the :code:`_hosts_ip` attribute. """ return self._hosts_ip @hosts_ip.setter def hosts_ip(self, value: str) -> None: """ Sets the hosts IP to use while generating the hosts files. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._hosts_ip = value def set_hosts_ip(self, value: str) -> "StatusFileGenerator": """ Sets the hosts IP to use while generating the hosts files. :param value: The value to set. """ self.hosts_ip = value return self def guess_and_set_hosts_ip(self) -> "StatusFileGenerator": """ Tries to guess the value of the :code:`hosts_ip` from the configuration file. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.hosts_ip = PyFunceble.storage.CONFIGURATION.cli_testing.hosts_ip else: self.hosts_ip = self.STD_HOSTS_IP @property def allow_unified_file(self) -> bool: """ Provides the current state of the :code:`allow_unified_file` attribute. """ return self._allow_unified_file @allow_unified_file.setter def allow_unified_file(self, value: bool) -> None: """ Sets the authorization to generation of the unified status file. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._allow_unified_file = value def set_allow_unified_file(self, value: bool) -> "StatusFileGenerator": """ Sets the authorization to generation of the unified status file. :param value: The value to set. """ self.allow_unified_file = value return self def guess_and_set_allow_unified_file(self) -> "StatusFileGenerator": """ Tries to guess the value of the :code:`allow_unified_file` from the configuration file. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): # pylint: disable=line-too-long self.allow_unified_file = ( PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.unified_results ) else: self.allow_unified_file = self.STD_ALLOW_UNIFIED_FILE def guess_all_settings(self) -> "StatusFileGenerator": """ Try to guess all settings. """ to_ignore = ["guess_all_settings"] for method in dir(self): if method in to_ignore or not method.startswith("guess_"): continue getattr(self, method)() return self def get_output_basedir(self) -> str: """ Provides the output base directory. :param create_if_missing: Authorizes the creation of the directory if it's missing. """ result = super().get_output_basedir() if not DirectoryHelper(result).exists(): DirectoryStructureRestoration(self.parent_dirname).start() return result @ensure_status_is_given def generate_hosts_file(self) -> "StatusFileGenerator": """ Generates the hosts file. """ our_dataset = self.status.to_dict() our_dataset["ip"] = self.hosts_ip if not hasattr(self.status, "ip_syntax") or not self.status.ip_syntax: location = os.path.join( self.get_output_basedir(), PyFunceble.cli.storage.OUTPUTS.hosts.directory, self.status.status.upper(), PyFunceble.cli.storage.OUTPUTS.hosts.filename, ) else: location = os.path.join( self.get_output_basedir(), PyFunceble.cli.storage.OUTPUTS.hosts.directory, self.status.status.upper(), PyFunceble.cli.storage.OUTPUTS.hosts.ip_filename, ) self.file_printer.destination = location self.file_printer.dataset = our_dataset self.file_printer.template_to_use = "hosts" self.file_printer.print_interpolated_line() return self @ensure_status_is_given def generate_plain_file(self) -> "StatusFileGenerator": """ Generates the plain file. """ location = None if not hasattr(self.status, "ip_syntax") or not self.status.ip_syntax: location = os.path.join( self.get_output_basedir(), PyFunceble.cli.storage.OUTPUTS.domains.directory, self.status.status.upper(), PyFunceble.cli.storage.OUTPUTS.domains.filename, ) self.file_printer.destination = location self.file_printer.dataset = self.status.to_dict() self.file_printer.template_to_use = "plain" self.file_printer.print_interpolated_line() if not hasattr(self.status, "ip_syntax") or self.status.subject_kind == "ip": location = os.path.join( self.get_output_basedir(), PyFunceble.cli.storage.OUTPUTS.ips.directory, self.status.status.upper(), PyFunceble.cli.storage.OUTPUTS.ips.filename, ) self.file_printer.destination = location self.file_printer.dataset = self.status.to_dict() self.file_printer.template_to_use = "plain" self.file_printer.print_interpolated_line() return self @ensure_status_is_given def generate_analytic_file(self) -> "StatusFileGenerator": """ Generates the analytic files. """ locations_data_and_template = [] # pylint: disable=line-too-long if hasattr(self.status, "http_status_code") and self.status.http_status_code: if PyFunceble.facility.ConfigLoader.is_already_loaded(): http_code_dataset = PyFunceble.storage.HTTP_CODES else: http_code_dataset = PyFunceble.storage.STD_HTTP_CODES if ( self.status.http_status_code in http_code_dataset.list.potentially_down or self.status.status in (PyFunceble.storage.STATUS.down, PyFunceble.storage.STATUS.invalid) ): locations_data_and_template.append( ( os.path.join( self.get_output_basedir(), PyFunceble.cli.storage.OUTPUTS.analytic.directories.parent, PyFunceble.cli.storage.OUTPUTS.analytic.directories.potentially_down, PyFunceble.cli.storage.OUTPUTS.analytic.filenames.potentially_down, ), "plain", self.status.to_dict(), ) ) if self.status.http_status_code in http_code_dataset.list.up: locations_data_and_template.append( ( os.path.join( self.get_output_basedir(), PyFunceble.cli.storage.OUTPUTS.analytic.directories.parent, PyFunceble.cli.storage.OUTPUTS.analytic.directories.potentially_down, PyFunceble.cli.storage.OUTPUTS.analytic.filenames.up, ), "plain", self.status.to_dict(), ) ) if ( self.status.http_status_code in http_code_dataset.list.potentially_up or self.status.status == PyFunceble.storage.STATUS.down ): locations_data_and_template.append( ( os.path.join( self.get_output_basedir(), PyFunceble.cli.storage.OUTPUTS.analytic.directories.parent, PyFunceble.cli.storage.OUTPUTS.analytic.directories.potentially_down, PyFunceble.cli.storage.OUTPUTS.analytic.filenames.potentially_up, ), "plain", self.status.to_dict(), ) ) if self.test_dataset and "from_inactive" in self.test_dataset: # Let's generate the supicious file :-) if self.status.status in [ PyFunceble.storage.STATUS.up, PyFunceble.storage.STATUS.valid, PyFunceble.storage.STATUS.sane, ]: locations_data_and_template.append( ( os.path.join( self.get_output_basedir(), PyFunceble.cli.storage.OUTPUTS.analytic.directories.parent, PyFunceble.cli.storage.OUTPUTS.analytic.directories.suspicious, PyFunceble.cli.storage.OUTPUTS.analytic.filenames.suspicious, ), "plain", self.status.to_dict(), ) ) for file_location, template, our_dataset in locations_data_and_template: self.file_printer.destination = file_location self.file_printer.dataset = our_dataset self.file_printer.template_to_use = template self.file_printer.print_interpolated_line() return self @ensure_status_is_given def generate_splitted_status_file(self) -> "StatusFileGenerator": """ Generates the splitted status file. """ self.file_printer.destination = os.path.join( self.get_output_basedir(), PyFunceble.cli.storage.OUTPUTS.splitted.directory, self.status.status.upper(), ) if not PlatformUtility.is_unix(): self.file_printer.destination += ".txt" self.file_printer.template_to_use = "all" self.file_printer.dataset = self.status.to_dict() self.file_printer.print_interpolated_line() return self @ensure_status_is_given def generate_unified_status_file(self) -> "StatusFileGenerator": """ Generates the unified status file. """ self.file_printer.destination = os.path.join( self.get_output_basedir(), PyFunceble.cli.storage.RESULTS_RAW_FILE, ) self.file_printer.template_to_use = "all" self.file_printer.dataset = self.status.to_dict() self.file_printer.print_interpolated_line() return self def start(self) -> "StatusFileGenerator": """ Starts the generation of everything possible. """ if self.allow_hosts_files: self.generate_hosts_file() if self.allow_plain_files: self.generate_plain_file() if self.allow_analytic_files: self.generate_analytic_file() if self.allow_unified_file: self.generate_unified_status_file() else: self.generate_splitted_status_file() PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/000077500000000000000000000000001467462152100212435ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/__init__.py000066400000000000000000000046061467462152100233620ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our system migrators. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/alembic.py000066400000000000000000000165251467462152100232220ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our very own alembic interface. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools import os from typing import Any, Optional from sqlalchemy.orm import Session from sqlalchemy.sql import text try: import importlib.resources as package_resources except ImportError: # pragma: no cover ## Retro compatibility import importlib_resources as package_resources import alembic import alembic.config from alembic import command as alembic_command from alembic.script.base import ScriptDirectory import PyFunceble.cli.facility import PyFunceble.cli.factory import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.sessions from PyFunceble.cli.migrators.db_base import DBMigratorBase class Alembic: """ Provides our very own alambic handler. """ db_session: Optional[Session] = None migrator_base: Optional[DBMigratorBase] = None alembic_config: Optional[alembic.config.Config] = None def __init__(self, db_session: Session) -> None: self.db_session = db_session self.migrator_base = DBMigratorBase() self.migrator_base.db_session = db_session def execute_if_authorized(default: Any = None): # pylint: disable=no-self-argument """ Executes the decorated method only if we are authorized to process. Otherwise, apply the given :code:`default`. """ def inner_metdhod(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.authorized: return func(self, *args, **kwargs) # pylint: disable=not-callable return self if default is None else default return wrapper return inner_metdhod @property def authorized(self): """ Provides the authorization to process. """ # Here we explicitly start because the usage of alembic may be out # of our running context. return PyFunceble.cli.facility.CredentialLoader.is_already_loaded() @property def migration_directory(self) -> str: """ Provides the location of our migration directory. """ with package_resources.path( f"PyFunceble.data.{PyFunceble.cli.storage.ALEMBIC_DIRECTORY_NAME}", "__init__.py", ) as file_path: result = os.path.split(file_path)[0] if PyFunceble.storage.CONFIGURATION.cli_testing.db_type == "postgresql": return os.path.join(result, "postgresql") return os.path.join(result, "mysql") @execute_if_authorized(None) def configure(self) -> "Alembic": """ Configure our alembic configuration based on what we need. """ if self.alembic_config is None: self.alembic_config = alembic.config.Config() self.alembic_config.set_main_option("script_location", self.migration_directory) self.alembic_config.set_main_option( "sqlalchemy.url", PyFunceble.cli.facility.CredentialLoader.get_uri(), ) return self def is_revision_different(self, revision: str) -> bool: """ Checks if the given revision is already set. :param revision: The revision to check """ revision_id = ( ScriptDirectory.from_config(self.alembic_config) .get_revision(revision) .revision ) statement = text( "SELECT * from alembic_version WHERE version_num = :db_revision" ) result = self.db_session.execute(statement, {"db_revision": revision_id}) return result.fetchone() is None @execute_if_authorized(None) def upgrade(self, revision: str = "head") -> "Alembic": """ Upgrades the database structure. :param revision: The revision to apply. """ self.configure() if not self.migrator_base.does_table_exists( "alembic_version" ) or self.is_revision_different(revision): PyFunceble.facility.Logger.info( "Started update (%r) of the database schema(s).", revision ) alembic_command.upgrade(self.alembic_config, revision) PyFunceble.facility.Logger.info( "Finished update (%r) of the database schema(s).", revision ) @execute_if_authorized(None) def downgrade(self, revision: str = "head") -> "Alembic": """ Upgrades the database structure. :param revision: The revision to apply. """ self.configure() if not self.migrator_base.does_table_exists( "alembic_version" ) or self.is_revision_different(revision): PyFunceble.facility.Logger.info( "Started downgrade (%r) of the database schema(s).", revision ) alembic_command.downgrade(self.alembic_config, revision) PyFunceble.facility.Logger.info( "Finished downgrade (%r) of the database schema(s).", revision ) PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/base.py000066400000000000000000000063221467462152100225320ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of our migrator classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional from sqlalchemy.orm import Session from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase class MigratorBase: """ Provides the base of all classes. """ done: bool = False continuous_integration: Optional[ContinuousIntegrationBase] = None db_session: Optional[Session] = None print_action_to_stdout: bool = False def __init__(self, print_action_to_stdout: bool = False) -> None: self.print_action_to_stdout = print_action_to_stdout self.__post_init__() def __post_init__(self) -> None: """ A method to be called (automatically) after the __init__ execution. """ def start(self) -> "MigratorBase": """ Starts the migration. """ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/csv_file/000077500000000000000000000000001467462152100230355ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/csv_file/__init__.py000066400000000000000000000046131467462152100251520ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the csv file(s) migrators. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/csv_file/base.py000066400000000000000000000132161467462152100243240ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all CSV file-s migrators. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 csv import functools import tempfile from typing import List, Optional import PyFunceble.facility from PyFunceble.cli.migrators.base import MigratorBase from PyFunceble.cli.utils.stdout import print_single_line from PyFunceble.helpers.file import FileHelper class CSVFileMigratorBase(MigratorBase): """ Provides the base of all CSV file migrator classes. """ source_file: Optional[str] = None FIELDS: Optional[List[str]] = None TO_DELETE: Optional[List[str]] = None TO_ADD: Optional[List[str]] = None def ensure_source_file_is_given(func): # pylint: disable=no-self-argument """ Ensures that the source file is given before launching the decorated method. :raise RuntimeError: When the:code:`self.source_file` is not given. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.source_file, str): raise RuntimeError(" is not given.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @ensure_source_file_is_given def migrate(self) -> "MigratorBase": """ Provides the migrator (itself). """ file_helper = FileHelper(self.source_file) if file_helper.exists(): with file_helper.open("r", encoding="utf-8") as file_stream: first_line = next(file_stream) if any(x in first_line for x in self.TO_DELETE) or any( x not in first_line for x in self.TO_ADD ): temp_destination = tempfile.NamedTemporaryFile( "a+", newline="", encoding="utf-8", delete=False ) file_handler = file_helper.open(newline="") reader = csv.DictReader(file_handler) writer = csv.DictWriter( temp_destination, fieldnames=[x for x in self.FIELDS if x not in self.TO_DELETE] + [x for x in self.TO_ADD if x not in self.FIELDS], ) writer.writeheader() keys_found = False for row in reader: row = dict(row) for key in self.TO_DELETE: if key in row: del row[key] keys_found = True for key in self.TO_ADD: if key not in row: row[key] = "" keys_found = True writer.writerow(row) if not keys_found: break writer.writerow(row) if self.print_action_to_stdout: print_single_line() temp_destination.seek(0) FileHelper(temp_destination.name).move(self.source_file) self.done = True def start(self) -> "MigratorBase": """ Starts the migration and everything related to it. """ PyFunceble.facility.Logger.info("Started migration.") self.migrate() PyFunceble.facility.Logger.info("Finished migration.") return self PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/csv_file/inactive_source_delete.py000066400000000000000000000062531467462152100301210ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the interface for the deletion of the 'source' column from the inactive dataset. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from typing import List import PyFunceble.cli.storage import PyFunceble.storage from PyFunceble.cli.migrators.csv_file.base import CSVFileMigratorBase class InactiveDatasetDeleteSourceColumnMigrator(CSVFileMigratorBase): """ Provides the interface for the deletion of the 'source' column. """ FIELDS: List[str] = [ "idna_subject", "checker_type", "destination", "source", "tested_at", ] TO_ADD: List[str] = [] TO_DELETE: List[str] = ["source"] def __post_init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.INACTIVE_DB_FILE ) return super().__post_init__() PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/csv_file/whois_registrar_add.py000066400000000000000000000061551467462152100274410ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the interface for the addition of the 'registrar' column from the whois dataset. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from typing import List import PyFunceble.cli.storage import PyFunceble.storage from PyFunceble.cli.migrators.csv_file.base import CSVFileMigratorBase class WhoisDatasetAddRegistrarColumnMigrator(CSVFileMigratorBase): """ Provides the interface for the addition of the 'registrar' column. """ FIELDS: List[str] = ["subject", "idna_subject", "expiration_date", "epoch"] TO_DELETE: List[str] = [] TO_ADD: List[str] = ["registrar"] def __post_init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.WHOIS_DB_FILE ) return super().__post_init__() PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/db_base.py000066400000000000000000000100101467462152100231640ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our database migration. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from typing import Any import sqlalchemy import PyFunceble.cli.facility import PyFunceble.cli.factory import PyFunceble.sessions from PyFunceble.cli.migrators.base import MigratorBase class DBMigratorBase(MigratorBase): """ Provides the base of all our database migration. """ def __init__(self, print_action_to_stdout: bool = False) -> None: super().__init__(print_action_to_stdout=print_action_to_stdout) def execute_if_authorized(default: Any = None): # pylint: disable=no-self-argument """ Executes the decorated method only if we are authorized to process. Otherwise, apply the given :code:`default`. """ def inner_metdhod(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.authorized: return func(self, *args, **kwargs) # pylint: disable=not-callable return self if default is None else default return wrapper return inner_metdhod @property def authorized(self): """ Provides the authorization to run. """ return PyFunceble.cli.facility.CredentialLoader.is_already_loaded() def does_table_exists(self, table_name: str) -> bool: """ Checks if the table exists. :param table_name: The name of the table to check. """ return sqlalchemy.inspect(PyFunceble.sessions.DB_ENGINE).has_table(table_name) def start(self) -> "MigratorBase": """ Starts the migration. """ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/file_cleanup/000077500000000000000000000000001467462152100236715ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/file_cleanup/__init__.py000066400000000000000000000046141467462152100260070ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the file cleanup migrators. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/file_cleanup/base.py000066400000000000000000000100271467462152100251550ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all cleanup migrators. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from typing import Optional import PyFunceble.facility from PyFunceble.cli.migrators.base import MigratorBase from PyFunceble.cli.utils.stdout import print_single_line from PyFunceble.helpers.file import FileHelper class FileClenupMigratorBase(MigratorBase): """ Provides the base of all file cleanup related migration classes. """ source_file: Optional[str] = None def ensure_source_file_is_given(func): # pylint: disable=no-self-argument """ Ensures that the source file is given before launching the decorated method. :raise RuntimeError: When the:code:`self.source_file` is not given. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.source_file, str): raise RuntimeError(" is not given.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @ensure_source_file_is_given def migrate(self) -> "FileClenupMigratorBase": """ Provides the migrator (itself) """ FileHelper(self.source_file).delete() PyFunceble.facility.Logger.debug("Deleted: %r", self.source_file) self.done = True if self.print_action_to_stdout: print_single_line() def start(self) -> "FileClenupMigratorBase": """ Starts the migration and everything related to it. """ PyFunceble.facility.Logger.info("Started migration.") self.migrate() PyFunceble.facility.Logger.info("Finished migration.") return self PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/file_cleanup/hashes_file.py000066400000000000000000000056331467462152100265240ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the cleaner of the previous - unfamous - hashes file. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import PyFunceble.cli.storage import PyFunceble.storage from PyFunceble.cli.migrators.file_cleanup.base import FileClenupMigratorBase class HashesFileCleanupMigrator(FileClenupMigratorBase): """ Provides the interface for the cleanup of the hashes file. """ def __post_init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.HASHES_FILENAME ) return super().__post_init__() PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/file_cleanup/mining_file.py000066400000000000000000000056331467462152100265320ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the cleaner of the previous - unfamous - mining file. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import PyFunceble.cli.storage import PyFunceble.storage from PyFunceble.cli.migrators.file_cleanup.base import FileClenupMigratorBase class MiningFileCleanupMigrator(FileClenupMigratorBase): """ Provides the interface for the cleanup of the mining file. """ def __post_init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.MINING_OLD_FILE ) return super().__post_init__() PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/file_cleanup/production_config_file.py000066400000000000000000000057521467462152100307660ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the cleaner of the previous .PyFunceble_production.yaml file. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import PyFunceble.cli.storage import PyFunceble.storage from PyFunceble.cli.migrators.file_cleanup.base import FileClenupMigratorBase class ProductionConfigFileCleanupMigrator(FileClenupMigratorBase): """ Provides the interface for the cleanup of the :code:`.PyFunceble_production.yaml` file. """ def __post_init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.DISTRIBUTED_CONFIGURATION_FILENAME, ) return super().__post_init__() PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/json2csv/000077500000000000000000000000001467462152100230125ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/json2csv/__init__.py000066400000000000000000000046131467462152100251270ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the JSON to CSV migrators. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/json2csv/base.py000066400000000000000000000106641467462152100243050ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all JSON 2 CSV migrators. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from typing import Optional import PyFunceble.facility from PyFunceble.cli.migrators.base import MigratorBase from PyFunceble.dataset.csv_base import CSVDatasetBase class JSON2CSVMigratorBase(MigratorBase): """ Provides the base of all JSON to CSV related classes. """ source_file: Optional[str] = None dataset: Optional[CSVDatasetBase] = None def ensure_source_file_is_given(func): # pylint: disable=no-self-argument """ Ensures that the source file is given before launching the decorated method. :raise RuntimeError: When the:code:`self.source_file` is not given. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.source_file, str): raise RuntimeError(" is not given.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def ensure_dataset_is_given(func): # pylint: disable=no-self-argument """ Ensures that the dataset is given before launching the decorated method. :raise RuntimeError: When the:code:`self.source_file` is not given. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.dataset, CSVDatasetBase): raise RuntimeError(" is not given.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def migrate(self) -> "JSON2CSVMigratorBase": """ Provides the migrator (itself) """ raise NotImplementedError() @ensure_source_file_is_given @ensure_dataset_is_given def start(self) -> "JSON2CSVMigratorBase": """ Starts the migration and everything related to it. """ PyFunceble.facility.Logger.info("Started migration.") self.migrate() PyFunceble.facility.Logger.info("Finished migration.") return self PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/json2csv/inactive.py000066400000000000000000000142011467462152100251640ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the our inactive DB migrator. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 datetime import os from typing import Optional import domain2idna import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.storage from PyFunceble.cli.migrators.json2csv.base import JSON2CSVMigratorBase from PyFunceble.cli.utils.stdout import print_single_line from PyFunceble.cli.utils.testing import get_destination_from_origin from PyFunceble.dataset.inactive.csv import CSVInactiveDataset from PyFunceble.helpers.file import FileHelper class InactiveJSON2CSVMigrator(JSON2CSVMigratorBase): """ The migrator of the inactive database dile. """ dataset: Optional[CSVInactiveDataset] = None def __post_init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.INACTIVE_DB_OLD_FILE, ) self.dataset = CSVInactiveDataset() return super().__post_init__() def migrate(self) -> "InactiveJSON2CSVMigrator": """ Starts the migration. """ file_helper = FileHelper(self.source_file) if file_helper.exists(): self.dataset.set_authorized(True) dataset = { "idna_subject": None, "status": None, "status_source": None, "checker_type": "AVAILABILITY", "destination": None, "source": None, "tested_at": None, "session_id": None, } delete_file = True with file_helper.open("r", encoding="utf-8") as file_stream: for line in file_stream: if ( self.continuous_integration and self.continuous_integration.is_time_exceeded() ): delete_file = False break line = ( line.strip() .replace('"', "") .replace(",", "") .replace( "{", "", ) .replace("}", "") ) if ":" not in line: continue index, value = [x.strip() for x in line.rsplit(":", 1)] if not value: if index.isdigit(): dataset["tested_at"] = datetime.datetime.fromtimestamp( float(index), datetime.timezone.utc, ).isoformat() else: dataset["source"] = os.path.abspath(index) dataset["destination"] = get_destination_from_origin( dataset["source"] ) continue dataset["idna_subject"] = domain2idna.domain2idna(index) dataset["status"] = value if not dataset["tested_at"]: dataset["tested_at"] = datetime.datetime.now( datetime.timezone.utc ).isoformat() PyFunceble.facility.Logger.debug("Decoded dataset:\n%r.", dataset) self.dataset.update(dataset) if self.print_action_to_stdout: print_single_line() PyFunceble.facility.Logger.info( "Added %r into %r", dataset["idna_subject"], self.dataset ) if delete_file: file_helper.delete() self.done = True return self PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/json2csv/whois.py000066400000000000000000000130661467462152100245230ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the our whois DB migrator. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from typing import Optional import domain2idna import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.storage from PyFunceble.cli.migrators.json2csv.base import JSON2CSVMigratorBase from PyFunceble.cli.utils.stdout import print_single_line from PyFunceble.dataset.whois.csv import CSVWhoisDataset from PyFunceble.helpers.file import FileHelper class WhoisJSON2CSVMigrator(JSON2CSVMigratorBase): """ The migrator of the inactive database dile. """ dataset: Optional[CSVWhoisDataset] = CSVWhoisDataset() def __post_init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.WHOIS_DB_OLD_FILE, ) self.dataset = CSVWhoisDataset() return super().__post_init__() def migrate(self) -> "WhoisJSON2CSVMigrator": """ Provides the migration logic. """ file_helper = FileHelper(self.source_file) if file_helper.exists(): self.dataset.set_authorized(True) dataset = { "subject": None, "idna_subject": None, "expiration_date": None, "epoch": None, } delete_file = True with file_helper.open("r", encoding="utf-8") as file_stream: for line in file_stream: if ( self.continuous_integration and self.continuous_integration.is_time_exceeded() ): delete_file = False break line = ( line.strip() .replace('"', "") .replace(",", "") .replace( "{", "", ) .replace("}", "") ) if ":" not in line: continue index, value = [x.strip() for x in line.split(":")] if not value: dataset["subject"], dataset["idna_subject"] = ( index, domain2idna.domain2idna(index), ) continue if index == "epoch": dataset["epoch"] = float(value) elif index == "expiration_date": dataset["expiration_date"] = value elif index == "state": PyFunceble.facility.Logger.debug( "Decoded dataset:\n%r.", dataset ) self.dataset.update(dataset) if self.print_action_to_stdout: print_single_line() PyFunceble.facility.Logger.info( "Added %r into %r", dataset["idna_subject"], self.dataset ) if delete_file: file_helper.delete() self.done = True return self PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/mariadb/000077500000000000000000000000001467462152100226425ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/mariadb/__init__.py000066400000000000000000000046241467462152100247610ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides all our mariadb related migrations. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/mariadb/base.py000066400000000000000000000111231467462152100241240ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all mariadb related migrations. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from typing import Any, Generator, Tuple from sqlalchemy.sql import text import PyFunceble.cli.facility import PyFunceble.cli.factory import PyFunceble.sessions from PyFunceble.cli.migrators.db_base import DBMigratorBase class MariaDBMigratorBase(DBMigratorBase): """ Provides the base of all our mariadb migration. """ def execute_if_authorized(default: Any = None): # pylint: disable=no-self-argument """ Executes the decorated method only if we are authorized to process. Otherwise, apply the given :code:`default`. """ def inner_metdhod(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.authorized: return func(self, *args, **kwargs) # pylint: disable=not-callable return self if default is None else default return wrapper return inner_metdhod def get_rows( self, statement: str, limit: int = 20 ) -> Generator[Tuple[str, int], dict, None]: """ Run the given statement with a defined limit, and yield each row. .. warning:: If you don't delete the given rows, this method will be infinite. """ statement += f" LIMIT {limit}" while True: db_result = list(self.db_session.execute(text(statement)).fetchall()) if not db_result: break for result in db_result: yield dict(result) @property def authorized(self) -> bool: """ Provides the authorization to process. """ return PyFunceble.cli.facility.CredentialLoader.is_already_loaded() @execute_if_authorized(None) def migrate(self) -> "MariaDBMigratorBase": """ Provides the migration (itself). """ raise NotImplementedError() @execute_if_authorized(None) def start(self) -> "MariaDBMigratorBase": """ Starts the migration if wanted. """ PyFunceble.facility.Logger.info("Started migration.") self.migrate() PyFunceble.facility.Logger.info("Finished migration.") return self PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/mariadb/file_and_status.py000066400000000000000000000156761467462152100263770ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the migrator of the :code:`pyfunceble_file` and `pyfunceble_status` tables. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 domain2idna from sqlalchemy.sql import text import PyFunceble.cli.facility import PyFunceble.cli.factory import PyFunceble.cli.utils.testing import PyFunceble.facility import PyFunceble.sessions import PyFunceble.storage from PyFunceble.cli.migrators.mariadb.base import MariaDBMigratorBase from PyFunceble.cli.utils.stdout import print_single_line from PyFunceble.cli.utils.testing import get_destination_from_origin class FileAndStatusMigrator(MariaDBMigratorBase): """ Provides the interface which provides the migration of the :code:`pyfunceble_file` and :code:`pyfunceble_status`. """ @property def authorized(self) -> bool: """ Provides the authorization to process. """ if PyFunceble.cli.facility.CredentialLoader.is_already_loaded(): for table in ["pyfunceble_file", "pyfunceble_status"]: if self.does_table_exists(table): return True return False @MariaDBMigratorBase.execute_if_authorized(None) def migrate(self) -> "FileAndStatusMigrator": inactive_statuses = ( PyFunceble.storage.STATUS.down, PyFunceble.storage.STATUS.invalid, ) inactive_dataset = PyFunceble.cli.utils.testing.get_inactive_dataset_object() continue_dataset = PyFunceble.cli.utils.testing.get_continue_databaset_object() drop_table = True for file_info in self.get_rows("SELECT * from pyfunceble_file"): if ( self.continuous_integration and self.continuous_integration.is_time_exceeded() ): drop_table = False break destination = get_destination_from_origin(file_info["path"]) for status in self.get_rows( f"SELECT * from pyfunceble_status WHERE file_id = {file_info['id']}" ): if ( self.continuous_integration and self.continuous_integration.is_time_exceeded() ): drop_table = False break to_send = { "idna_subject": domain2idna.domain2idna(status["tested"]), "checker_type": "AVAILABILITY", "destination": destination, "source": file_info["path"], "tested_at": status["tested_at"], "session_id": None, } if status["status"] in inactive_statuses: inactive_dataset.update(to_send) if self.print_action_to_stdout: print_single_line() PyFunceble.facility.Logger.debug("Dataset: %r", to_send) continue_dataset.update(to_send) if self.print_action_to_stdout: print_single_line() PyFunceble.facility.Logger.info( "Added %r into %r", to_send["idna_subject"], continue_dataset ) # pylint: disable=line-too-long self.db_session.execute( text(f"DELETE from pyfunceble_status WHERE id = {status['id']}") ) self.db_session.commit() PyFunceble.facility.Logger.debug( "Deleted from pyfunceble_status: \n%r", status ) if drop_table: # pylint: disable=line-too-long self.db_session.execute( text(f"DELETE from pyfunceble_file WHERE id = {file_info['id']}") ) self.db_session.commit() PyFunceble.facility.Logger.debug( "Deleted from pyfunceble_file: \n%r", file_info ) else: PyFunceble.facility.Logger.debug( "Not deleted from pyfunceble_file (not authorized): \n%r", file_info ) if drop_table: self.db_session.execute(text("DROP TABLE pyfunceble_file")) self.db_session.commit() PyFunceble.facility.Logger.debug("Deleted pyfunceble_file table.") self.db_session.execute(text("DROP TABLE pyfunceble_status")) self.db_session.commit() PyFunceble.facility.Logger.debug("Deleted pyfunceble_status table.") self.done = True else: PyFunceble.facility.Logger.debug( "No table deleted. Reason: not authorized." ) return self PyFunceble-4.2.29.dev/PyFunceble/cli/migrators/mariadb/whois_record_idna_subject.py000066400000000000000000000105241467462152100304170ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our WHOIS record migrator. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 domain2idna import PyFunceble.cli.factory import PyFunceble.facility import PyFunceble.sessions from PyFunceble.cli.migrators.mariadb.base import MariaDBMigratorBase from PyFunceble.cli.utils.stdout import print_single_line from PyFunceble.database.sqlalchemy.all_schemas import WhoisRecord class WhoisRecordIDNASubjectMigrator(MariaDBMigratorBase): """ Provides the interface which provides the completion of the missing IDNA subject column. """ @property def authorized(self) -> bool: """ Provides the authorization to process. """ if PyFunceble.cli.facility.CredentialLoader.is_already_loaded(): # pylint: disable=singleton-comparison return ( self.db_session.query(WhoisRecord) .filter(WhoisRecord.idna_subject == None) .first() is not None ) return False @MariaDBMigratorBase.execute_if_authorized(None) def migrate(self) -> "WhoisRecordIDNASubjectMigrator": # pylint: disable=singleton-comparison broken = False for row in self.db_session.query(WhoisRecord).filter( WhoisRecord.idna_subject == None ): if ( self.continuous_integration and self.continuous_integration.is_time_exceeded() ): broken = True break PyFunceble.facility.Logger.info( "Started to fix idna_subject field of %r", row.subject ) row.idna_subject = domain2idna.domain2idna(row.subject) self.db_session.add(row) if self.print_action_to_stdout: print_single_line() PyFunceble.facility.Logger.info( "Finished to fix idna_subject field of %r", row.subject ) self.db_session.commit() if not broken: self.done = True return self PyFunceble-4.2.29.dev/PyFunceble/cli/processes/000077500000000000000000000000001467462152100212425ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/processes/__init__.py000066400000000000000000000051261467462152100233570ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides all our the logic behind our multiprocessing mechanism. .. note:: Our processes submodules or class does not extends the multiprocessing module. They are just there to clarify our workflow for future contributors :-) Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/processes/base.py000066400000000000000000000364261467462152100225410ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all multiprocessing jobs. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools import multiprocessing import os import queue from typing import Any, List, Optional import PyFunceble.facility from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase from PyFunceble.cli.processes.workers.base import WorkerBase class ProcessesManagerBase: """ Provides the base of all classes. """ CPU_COUNT = os.cpu_count() if CPU_COUNT > 2: STD_MAX_WORKER: int = CPU_COUNT - 2 else: STD_MAX_WORKER: int = 1 WORKER_OBJ: Optional[WorkerBase] = None input_datasets: Optional[List] = [] """ Use this variable if you want to differ the addition in the input queue. """ output_datasets: Optional[List] = [] """ Use this variable if you want to differ the addition in the output queue. """ input_queue: Optional[queue.Queue] = None """ The input queue. Dataset will be given through this. """ output_queue: Optional[List[queue.Queue]] = None """ The output queue. This is where the result of a worker will be put. """ daemon: Optional[bool] = None manager: Optional[multiprocessing.Manager] = None global_exit_event: Optional[multiprocessing.Event] = None continuous_integration: Optional[ContinuousIntegrationBase] = None _created_workers: Optional[List[WorkerBase]] = None _running_workers: Optional[List[WorkerBase]] = None _output_workers_count: Optional[int] = None _max_worker: Optional[int] = None def __init__( self, manager: Optional[multiprocessing.Manager] = None, max_worker: Optional[int] = None, *, continuous_integration: Optional[ContinuousIntegrationBase] = None, input_queue: Optional[queue.Queue] = None, output_queue: Optional[queue.Queue] = None, daemon: bool = False, generate_input_queue: bool = True, generate_output_queue: bool = True, output_queue_num: int = 1, output_workers_count: Optional[int] = None, ) -> None: if manager is not None: self.manager = manager else: self.manager = multiprocessing.Manager() if input_queue is None: if generate_input_queue: self.input_queue = self.manager.Queue() else: self.input_queue = None else: self.input_queue = input_queue if output_queue is None: if generate_output_queue: self.output_queue = [ self.manager.Queue() for _ in range(output_queue_num) ] else: self.output_queue = None else: if not isinstance(output_queue, list): self.output_queue = [output_queue] else: self.output_queue = output_queue if max_worker is not None: self.max_worker = max_worker else: self.max_worker = self.STD_MAX_WORKER if continuous_integration is not None: self.continuous_integration = continuous_integration self.daemon = daemon self.global_exit_event = multiprocessing.Event() self._running_workers = [] self._created_workers = [] if output_workers_count is None: self._output_workers_count = 1 else: self._output_workers_count = int(output_workers_count) def ensure_worker_obj_is_given(func): # pylint: disable=no-self-argument """ Ensures that the worker is properly declared before launching the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.WORKER_OBJ is None: raise TypeError(f" should not be {None}!") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def create_workers_if_missing(func): # pylint: disable=no-self-argument """ Creates the workers if they are missing before launching the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): # pylint: disable=protected-access if not self._created_workers: self.create() return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def ignore_if_running(func): # pylint: disable=no-self-argument """ Ignore the launching of the decorated method if the workers are running. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not self.is_running(): return func(self, *args, **kwargs) # pylint: disable=not-callable return self return wrapper @property def max_worker(self) -> Optional[int]: """ Provides the number of maximum worker we are allowed to generate. """ return self._max_worker @max_worker.setter def max_worker(self, value: int) -> None: """ Sets the number of maximum worker we are authorized to generate. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`int`. :raise ValueError: When the given :code:`value` is less than :code:`1`. """ if not isinstance(value, int): raise TypeError(f" should be {int}, {type(value)} given.") if value < 1: raise ValueError(" should be greater or equal to one.") self._max_worker = value def set_max_worker(self, value: int) -> "ProcessesManagerBase": """ Sets the number of maximum worker we are authorized to generate. :param value: The value to set. """ self.max_worker = value return self def is_running(self) -> bool: """ Checks if a worker is running. """ if not self._running_workers: return False for worker in self._running_workers: if worker.is_alive(): return True return False def send_stop_signal( self, *, worker_name: Optional[str] = None ) -> "ProcessesManagerBase": """ Sends a stop message to the input queue. """ self.add_to_all_input_queues( "stop", worker_name=worker_name, include_destination=True ) def terminate(self) -> "ProcessesManagerBase": """ Terminates all workers and send a stop message to the declared output queues - which are implicitly dependend of this process "pool". """ if self._running_workers: workers = self._running_workers else: workers = self._created_workers if workers[0].global_exit_event: workers[0].global_exit_event.set() for worker in workers: worker.terminate() worker.join() # When all worker of the current process are down or finished, send the # stop message to the depending workers. self.add_to_all_output_queues("stop") def wait(self) -> "ProcessesManagerBase": """ Wait until all workers are done. """ for worker in self._running_workers: PyFunceble.facility.Logger.info( "Waiting for %r to finish.", worker.name, ) worker.join() self._running_workers.remove(worker) PyFunceble.facility.Logger.info( "Still running: %r.", self._running_workers, ) for worker in self._created_workers: if worker.exception: worker_error, _ = worker.exception self.terminate() raise worker_error self.terminate() @create_workers_if_missing def add_to_all_input_queues( self, data: Any, *, worker_name: Optional[str] = None, include_destination: bool = False, ) -> "ProcessesManagerBase": """ Adds the given data to the input queues. :param data: The data to add into the queue. :param include_destination: Authorizes the addition of the destination into the message. """ if self.is_running(): workers = self._running_workers else: workers = self._created_workers for worker in workers: if include_destination: worker.add_to_input_queue( data, worker_name=worker_name, destination_worker=worker.name ) else: worker.add_to_input_queue(data, worker_name=worker_name) PyFunceble.facility.Logger.debug("Added to all (input) queues: %r", data) @create_workers_if_missing def add_to_all_output_queues( self, data: Any, *, worker_name: Optional[str] = None, ) -> "ProcessesManagerBase": """ Adds the given data to the output queues. :param data: The data to add into the queue. :param worker_name: The name of the worker that is sending the message. """ for _ in range(self._output_workers_count): self.add_to_output_queue(data, worker_name=worker_name) PyFunceble.facility.Logger.debug("Added to all (output) queues: %r", data) return self @create_workers_if_missing def add_to_input_queue( self, data: Any, *, worker_name: Optional[str] = None ) -> "ProcessesManagerBase": """ Adds the given data to the current queue. :param data: The data to add into the queue. """ if self.is_running(): self._running_workers[0].add_to_input_queue(data, worker_name=worker_name) else: self._created_workers[0].add_to_input_queue(data, worker_name=worker_name) PyFunceble.facility.Logger.debug("Added to the (main) queue: %r", data) @create_workers_if_missing def add_to_output_queue( self, data: Any, *, worker_name: Optional[str] = None ) -> "ProcessesManagerBase": """ Adds the given data to the output queue. :param data: The data to add into the queue. """ if self.is_running(): self._running_workers[0].add_to_output_queue(data, worker_name=worker_name) else: self._created_workers[0].add_to_output_queue(data, worker_name=worker_name) PyFunceble.facility.Logger.debug("Added to the (output) queue: %r", data) return self def create(self) -> "ProcessesManagerBase": """ Creates the defined amount of worker. """ def share_concurrent_worker_names() -> None: """ Share the name of all concurrent worker to all workers. """ concurrent_names = [x.name for x in self._created_workers] for worker in self._created_workers: worker.concurrent_worker_names = list(concurrent_names) worker.concurrent_worker_names.remove(worker.name) for i in range(self.max_worker): worker = self.WORKER_OBJ( # pylint: disable=not-callable self.input_queue, self.output_queue, self.global_exit_event, name=f"{self.WORKER_OBJ.STD_NAME}_{i + 1}", daemon=self.daemon, continuous_integration=self.continuous_integration, configuration=PyFunceble.storage.CONFIGURATION.to_dict(), ) self._created_workers.append(worker) share_concurrent_worker_names() PyFunceble.facility.Logger.info( "Created %r workers of %r. Details:\n%r", len(self._created_workers), self.WORKER_OBJ, self._created_workers, ) return self @ensure_worker_obj_is_given @create_workers_if_missing @ignore_if_running def start(self) -> "ProcessesManagerBase": """ Starts all - previously - created workers. """ for worker in self._created_workers: try: worker.start() except AssertionError: # Example: cannot start a process twice pass self._running_workers.append(worker) if self.input_datasets: while self.input_datasets: self.add_to_input_queue(self.input_datasets.pop()) if self.output_datasets: while self.output_datasets: self.add_to_output_queue(self.output_datasets.pop()) PyFunceble.facility.Logger.info( "Started %r workers of %r. Details:\n%r", len(self._running_workers), self.WORKER_OBJ, self._running_workers, ) return self PyFunceble-4.2.29.dev/PyFunceble/cli/processes/chancy_producer.py000066400000000000000000000057471467462152100250010ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the chancy producer manager. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.cli.processes.base import ProcessesManagerBase from PyFunceble.cli.processes.workers.chancy_producer import ChancyProducerWorker class ChancyProducerProcessesManager(ProcessesManagerBase): """ Provides the chancy producer manager. .. warning:: The chancy tester shouldn't be used without any recommendation from a developer or someone in charge of the source code. It can harm and produce output overflow. You should rely on this ONLY if you believe in your own luck. """ WORKER_OBJ: ChancyProducerWorker = ChancyProducerWorker PyFunceble-4.2.29.dev/PyFunceble/cli/processes/chancy_tester.py000066400000000000000000000057311467462152100244550ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the chancy tester manager. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.cli.processes.base import ProcessesManagerBase from PyFunceble.cli.processes.workers.chancy_tester import ChancyTesterWorker class ChancyTesterProcessesManager(ProcessesManagerBase): """ Provides the chancy tester manager. .. warning:: The chancy tester shouldn't be used without any recommendation from a developer or someone in charge of the source code. It can harm and produce output overflow. You should rely on this ONLY if you believe in your own luck. """ WORKER_OBJ: ChancyTesterWorker = ChancyTesterWorker PyFunceble-4.2.29.dev/PyFunceble/cli/processes/dir_files_sorter.py000066400000000000000000000053421467462152100251560ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the directory files sorter manager. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.cli.processes.base import ProcessesManagerBase from PyFunceble.cli.processes.workers.dir_files_sorter import DireFileSorterWorker class DirFileSorterProcessesManager(ProcessesManagerBase): """ Provides the directory files sorter manager. """ WORKER_OBJ: DireFileSorterWorker = DireFileSorterWorker PyFunceble-4.2.29.dev/PyFunceble/cli/processes/file_sorter.py000066400000000000000000000052701467462152100241350ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the file sorter manager. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.cli.processes.base import ProcessesManagerBase from PyFunceble.cli.processes.workers.file_sorter import FileSorterWorker class FileSorterProcessesManager(ProcessesManagerBase): """ Provides the file sorter manager. """ WORKER_OBJ: FileSorterWorker = FileSorterWorker PyFunceble-4.2.29.dev/PyFunceble/cli/processes/migrator.py000066400000000000000000000410561467462152100234460ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the migrator manager. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional import colorama from sqlalchemy.orm import Session import PyFunceble.checker.utils.whois import PyFunceble.cli.utils.stdout import PyFunceble.cli.utils.testing import PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase from PyFunceble.cli.migrators.alembic import Alembic from PyFunceble.cli.migrators.csv_file.inactive_source_delete import ( InactiveDatasetDeleteSourceColumnMigrator, ) from PyFunceble.cli.migrators.csv_file.whois_registrar_add import ( WhoisDatasetAddRegistrarColumnMigrator, ) from PyFunceble.cli.migrators.file_cleanup.hashes_file import HashesFileCleanupMigrator from PyFunceble.cli.migrators.file_cleanup.mining_file import MiningFileCleanupMigrator from PyFunceble.cli.migrators.file_cleanup.production_config_file import ( ProductionConfigFileCleanupMigrator, ) from PyFunceble.cli.migrators.json2csv.inactive import InactiveJSON2CSVMigrator from PyFunceble.cli.migrators.json2csv.whois import WhoisJSON2CSVMigrator from PyFunceble.cli.migrators.mariadb.file_and_status import FileAndStatusMigrator from PyFunceble.cli.migrators.mariadb.whois_record_idna_subject import ( WhoisRecordIDNASubjectMigrator, ) from PyFunceble.cli.processes.base import ProcessesManagerBase from PyFunceble.cli.processes.workers.migrator import MigratorWorker from PyFunceble.helpers.file import FileHelper class MigratorProcessesManager(ProcessesManagerBase): """ Provides the migrator manager. """ WORKER_OBJ: MigratorWorker = MigratorWorker @staticmethod def json2csv_inactive_target( continuous_integration: ContinuousIntegrationBase, ) -> None: """ Provides the target for the inactive database migrator. """ migrator = InactiveJSON2CSVMigrator(print_action_to_stdout=True) migrator.continuous_integration = continuous_integration if FileHelper(migrator.source_file).exists(): print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" "Started migration (json2csv) of the inactive dataset." ) migrator.start() if migrator.done: print( f"\n{colorama.Fore.GREEN}{colorama.Style.BRIGHT}" "Finished migration (json2csv) of the inactive dataset." ) else: print( f"\n{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" "Unfinished migration (json2csv) of the inactive dataset." ) else: PyFunceble.facility.Logger.info( "Stopped json2csv_inactive_target. File does not exist." ) @staticmethod def json2csv_whois_target( continuous_integration: ContinuousIntegrationBase, ) -> None: """ Provides the target for the whois database migrator. """ migrator = WhoisJSON2CSVMigrator(print_action_to_stdout=True) migrator.continuous_integration = continuous_integration if FileHelper(migrator.source_file).exists(): print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" "Started migration (json2csv) of the whois dataset." ) migrator.start() if migrator.done: print( f"\n{colorama.Fore.GREEN}{colorama.Style.BRIGHT}" "Finished migration (json2csv) of the whois dataset." ) else: print( f"\n{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" "Unfinished migration (json2csv) of the whois dataset." ) else: PyFunceble.facility.Logger.info( "Stopped json2csv_whois_target. File does not exist." ) @staticmethod def mariadb_whois_record_idna_subject_target( continuous_integration: ContinuousIntegrationBase, *, db_session: Optional[Session] = None, ) -> None: """ Provides the target for the whois addition of the missing idna_subject column. """ migrator = WhoisRecordIDNASubjectMigrator(print_action_to_stdout=True) migrator.continuous_integration = continuous_integration migrator.db_session = db_session if migrator.authorized: print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" "Started completion of NULL idna_subject(s) into the whois dataset." ) migrator.start() if migrator.done: print( f"{colorama.Fore.GREEN}{colorama.Style.BRIGHT}" "Finished completion of NULL idna_subject(s) into " "the whois dataset." ) else: print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" "Unfinished completion of NULL idna_subject(s) into " "the whois dataset." ) else: PyFunceble.facility.Logger.info( "Stopped mariadb_whois_record_idna_subject_target. Not authorized." ) @staticmethod def mariadb_file_and_status_target( continuous_integration: ContinuousIntegrationBase, *, db_session: Optional[Session] = None, ) -> None: """ Provides the target for the migration of the :code:`pyfunceble_file` and :code:`pyfunceble_status` tables. """ migrator = FileAndStatusMigrator(print_action_to_stdout=True) migrator.continuous_integration = continuous_integration migrator.db_session = db_session if migrator.authorized: print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" "Started migration of the pyfunceble_file and " "pyfunceble_status tables." ) migrator.start() if migrator.done: print( f"{colorama.Fore.GREEN}{colorama.Style.BRIGHT}" "Finished migration of the pyfunceble_file and " "pyfunceble_status tables." ) else: print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" "Unfinished migration of the pyfunceble_file and " "pyfunceble_status tables." ) else: PyFunceble.facility.Logger.info( "Stopped mariadb_file_and_status_target. Not authorized." ) @staticmethod def hashes_file_cleanup_target( continuous_integration: ContinuousIntegrationBase, ) -> None: """ Provides the target for the cleanup of the hashes file. """ migrator = HashesFileCleanupMigrator(print_action_to_stdout=True) migrator.continuous_integration = continuous_integration if FileHelper(migrator.source_file).exists(): print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" f"Started deletion of {migrator.source_file!r}." ) migrator.start() if migrator.done: print( f"{colorama.Fore.GREEN}{colorama.Style.BRIGHT}" f"Finished deletion of {migrator.source_file!r}." ) else: print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" f"Unfinished deletion of {migrator.source_file!r}." ) else: PyFunceble.facility.Logger.info( "Stopped hashes_file_cleanup_target. File does not exist." ) @staticmethod def production_config_file_cleanup_target( continuous_integration: ContinuousIntegrationBase, ) -> None: """ Provides the target for the cleanup of the production configuration file. """ migrator = ProductionConfigFileCleanupMigrator(print_action_to_stdout=True) migrator.continuous_integration = continuous_integration if FileHelper(migrator.source_file).exists(): print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" f"Started deletion of {migrator.source_file!r}." ) migrator.start() if migrator.done: print( f"{colorama.Fore.GREEN}{colorama.Style.BRIGHT}" f"Finished deletion of {migrator.source_file!r}." ) else: print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" f"Unfinished deletion of {migrator.source_file!r}." ) else: PyFunceble.facility.Logger.info( "Stopped production_config_file_cleanup_target. File does not exist." ) @staticmethod def mining_file_cleanup_target( continuous_integration: ContinuousIntegrationBase, ) -> None: """ Provides the target for the cleanup of the mining file. """ migrator = MiningFileCleanupMigrator(print_action_to_stdout=True) migrator.continuous_integration = continuous_integration if FileHelper(migrator.source_file).exists(): print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" f"Started deletion of {migrator.source_file!r}." ) migrator.start() if migrator.done: print( f"{colorama.Fore.GREEN}{colorama.Style.BRIGHT}" f"Finished deletion of {migrator.source_file!r}." ) else: print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" f"Unfinished deletion of {migrator.source_file!r}." ) else: PyFunceble.facility.Logger.info( "Stopped hashes_file_cleanup_target. File does not exist." ) @staticmethod def csv_file_delete_source_column_target( continuous_integration: ContinuousIntegrationBase, ) -> None: """ Provides the target for the deletion of the source column. """ migrator = InactiveDatasetDeleteSourceColumnMigrator( print_action_to_stdout=True ) migrator.continuous_integration = continuous_integration file_helper = FileHelper(migrator.source_file) if file_helper.exists(): with file_helper.open("r", encoding="utf-8") as file_stream: first_line = next(file_stream) if any(x in first_line for x in migrator.TO_DELETE): print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" "Started deletion of the 'source' column into " f"{migrator.source_file!r}." ) migrator.start() if migrator.done: print( f"{colorama.Fore.GREEN}{colorama.Style.BRIGHT}" "Finished deletion of the 'source' column into " f"{migrator.source_file!r}." ) else: print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" "unfinished deletion of the 'source' column into " f"{migrator.source_file!r}." ) else: PyFunceble.facility.Logger.info( "Stopped csv_file_delete_source_column_target. File does not exist." ) @staticmethod def csv_file_add_registrar_column_target( continuous_integration: ContinuousIntegrationBase, ) -> None: """ Provides the target for the addition of the registrar column. """ migrator = WhoisDatasetAddRegistrarColumnMigrator(print_action_to_stdout=True) migrator.continuous_integration = continuous_integration file_helper = FileHelper(migrator.source_file) if file_helper.exists(): with file_helper.open("r", encoding="utf-8") as file_stream: first_line = next(file_stream) if any(x not in first_line for x in migrator.TO_ADD): print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" "Started addition of the 'registrar' column into " f"{migrator.source_file!r}." ) migrator.start() if migrator.done: print( f"{colorama.Fore.GREEN}{colorama.Style.BRIGHT}" "Finished addition of the 'registrar' column into " f"{migrator.source_file!r}." ) else: print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" "unfinished addition of the 'registrar' column into " f"{migrator.source_file!r}." ) else: PyFunceble.facility.Logger.info( "Stopped csv_file_add_registrar_column_target. File does not exist." ) def create(self) -> "ProcessesManagerBase": for method in dir(self): if not method.endswith("_target"): continue worker = MigratorWorker( None, name=f"pyfunceble_{method}", daemon=True, continuous_integration=self.continuous_integration, ) worker.target = getattr(self, method) self._created_workers.append(worker) PyFunceble.facility.Logger.info("Created worker for %r", method) @ProcessesManagerBase.ensure_worker_obj_is_given @ProcessesManagerBase.create_workers_if_missing def start(self) -> "ProcessesManagerBase": # We start the migration (as a standalone) Alembic(self._created_workers[0].db_session).upgrade() return super().start() PyFunceble-4.2.29.dev/PyFunceble/cli/processes/miner.py000066400000000000000000000052221467462152100227270ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the miner manager. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.cli.processes.base import ProcessesManagerBase from PyFunceble.cli.processes.workers.miner import MinerWorker class MinerProcessesManager(ProcessesManagerBase): """ Provides the miner manager. """ WORKER_OBJ: MinerWorker = MinerWorker PyFunceble-4.2.29.dev/PyFunceble/cli/processes/producer.py000066400000000000000000000052471467462152100234470ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the producer manager. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.cli.processes.base import ProcessesManagerBase from PyFunceble.cli.processes.workers.producer import ProducerWorker class ProducerProcessesManager(ProcessesManagerBase): """ Provides the producer manager. """ WORKER_OBJ: ProducerWorker = ProducerWorker PyFunceble-4.2.29.dev/PyFunceble/cli/processes/tester.py000066400000000000000000000052311467462152100231230ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the tester manager. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.cli.processes.base import ProcessesManagerBase from PyFunceble.cli.processes.workers.tester import TesterWorker class TesterProcessesManager(ProcessesManagerBase): """ Provides the tester manager. """ WORKER_OBJ: TesterWorker = TesterWorker PyFunceble-4.2.29.dev/PyFunceble/cli/processes/workers/000077500000000000000000000000001467462152100227365ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/processes/workers/__init__.py000066400000000000000000000046141467462152100250540ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides all our standalone workers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/processes/workers/base.py000066400000000000000000000340761467462152100242340ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our workers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 multiprocessing import multiprocessing.connection import queue import time import traceback from datetime import datetime, timedelta, timezone from typing import Any, List, Optional, Tuple import PyFunceble.cli.facility import PyFunceble.cli.factory import PyFunceble.facility import PyFunceble.sessions from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase class WorkerBase(multiprocessing.Process): """ Provides the base of all our workers. :param input_queue: The input queue to read. :param output_queue: The output queue to write. """ STD_NAME: str = "pyfunceble_base_worker" MINING_WAIT_TIME: int = 60 BREAKOFF: float = 2.0 input_queue: Optional[queue.Queue] = None output_queue: Optional[queue.Queue] = None continuous_integration: ContinuousIntegrationBase = None global_exit_event: Optional[multiprocessing.Event] = None exit_it: Optional[multiprocessing.Event] = None send_stop_message: Optional[bool] = None accept_waiting_delay: Optional[bool] = None concurrent_worker_names: Optional[List[str]] = None db_session: Optional[PyFunceble.cli.factory.db_session] = None _parent_connection: Optional[multiprocessing.connection.Connection] = None _child_connection: Optional[multiprocessing.connection.Connection] = None _exception: Optional[multiprocessing.Pipe] = None _params: Optional[dict] = {} def __init__( self, input_queue: Optional[queue.Queue], output_queue: Optional[queue.Queue] = None, global_exit_event: Optional[multiprocessing.Event] = None, *, name: Optional[str] = None, daemon: Optional[bool] = None, continuous_integration: Optional[ContinuousIntegrationBase] = None, configuration: Optional[dict] = None, ) -> None: self.configuration = self._params["configuration"] = configuration self.input_queue = self._params["input_queue"] = input_queue self.output_queue = self._params["output_queue"] = output_queue self.continuous_integration = self._params["continuous_integration"] = ( continuous_integration ) self.global_exit_event = self._params["global_exit_event"] = global_exit_event self.exit_it = multiprocessing.Event() self._parent_connection, self._child_connection = multiprocessing.Pipe() self._exception = None self.send_stop_message = True self.accept_waiting_delay = True self.concurrent_worker_names = [] try: self.db_session = ( PyFunceble.cli.factory.DBSession.get_db_session().get_new_session()() ) except TypeError: self.db_session = None super().__init__(name=name, daemon=daemon) self.__post_init__() def __del__(self) -> None: if self.db_session is not None: self.db_session.close() def __post_init__(self) -> None: """ A method which will be executed after the :code:`__init__` method. """ @property def exception(self): """ Provides the exception of the current worker. """ if self._parent_connection.poll(): self._exception = self._parent_connection.recv() return self._exception def add_to_input_queue( self, data: Any, *, worker_name: Optional[str] = None, destination_worker: Optional[str] = None, ) -> "WorkerBase": """ Adds the given data to the current queue. :param data: The data to add into the queue. :param destination_worker: The name of the worker which is supposed to read the message. """ if worker_name: to_send = (worker_name, destination_worker, data) else: to_send = (self.name, destination_worker, data) self.input_queue.put(to_send) PyFunceble.facility.Logger.debug("Added to the (input) queue: %r", data) def add_to_output_queue( self, data: Any, *, worker_name: Optional[str] = None, destination_worker: Optional[str] = None, ) -> "WorkerBase": """ Adds the given data to the output queue queue. :param data: The data to add into the queue. """ if worker_name: to_send = (worker_name, destination_worker, data) else: to_send = (self.name, destination_worker, data) if self.output_queue is not None: for output_queue in self.output_queue: output_queue.put(to_send) PyFunceble.facility.Logger.debug("Added to the (output) queue: %r", data) return self def target(self, consumed: Any) -> Optional[Tuple[Any, ...]]: """ This the target that is run to process something. This method should return a result which will pu send to the output queue. """ raise NotImplementedError() def share_waiting_message( self, *, overall: bool = False, ignore_current_worker: bool = False, apply_breakoff: bool = False, ) -> "WorkerBase": """ Shares a waiting message to both input and output queues. The idea is to keep our worker awake when necessary. This functionality is really important when running the mining worker because sometime the flow is so long, that we may need some time. :param overall: Shares the message multiple time to specific destination in our current stack. :param ignore_current_worker: Doesn't share the message with ourself. :param apply_breakoff: Activates the breakoff (sleep) before starting to share the message. """ if overall: for worker_name in self.concurrent_worker_names: if apply_breakoff: time.sleep(self.BREAKOFF) if not ignore_current_worker: # Give the whole stack a bit more of time. self.add_to_input_queue("wait", destination_worker=worker_name) self.add_to_output_queue("wait") else: if apply_breakoff: time.sleep(self.BREAKOFF) if not ignore_current_worker: self.add_to_input_queue("wait", destination_worker=self.name) self.add_to_output_queue("wait") def run(self) -> None: # pylint: disable=too-many-statements def break_now() -> bool: """ Checks if it is time to make a break. """ if not wait_for_stop or not self.accept_waiting_delay: return True return datetime.now(timezone.utc) > break_time if self.configuration is not None: PyFunceble.facility.ConfigLoader.set_custom_config(self.configuration) if multiprocessing.get_start_method() != "fork": PyFunceble.facility.ConfigLoader.start() PyFunceble.cli.facility.CredentialLoader.start() PyFunceble.cli.factory.DBSession.init_db_sessions() # Be sure that all settings are loaded proprely!! PyFunceble.factory.Requester = PyFunceble.factory.requester() wait_for_stop = ( bool(PyFunceble.storage.CONFIGURATION.cli_testing.mining) is True ) break_time = datetime.now(timezone.utc) + timedelta( seconds=self.MINING_WAIT_TIME ) try: # pylint: disable=too-many-nested-blocks while True: if self.global_exit_event.is_set(): PyFunceble.facility.Logger.info( "Got global exit event. Stopping worker." ) break if self.exit_it.is_set(): PyFunceble.facility.Logger.info("Got exit event. Stopping worker.") break if ( self.continuous_integration and self.continuous_integration.is_time_exceeded() ): PyFunceble.facility.Logger.info( "CI time exceeded. Stopping worker." ) if break_now(): self.exit_it.set() continue continue try: worker_name, destination_worker, consumed = self.input_queue.get() except (EOFError, KeyboardInterrupt): PyFunceble.facility.Logger.info( "Got EOFError/KeyboardInterrupt. Stopping worker." ) self.global_exit_event.set() break if destination_worker and destination_worker != self.name: self.add_to_input_queue( consumed, worker_name=worker_name, destination_worker=destination_worker, ) continue PyFunceble.facility.Logger.info( "Got (from %r): %r", worker_name, consumed, ) if consumed == "stop": if break_now(): PyFunceble.facility.Logger.info( "Got stop message from %r. Applying.", worker_name, ) self.exit_it.set() continue self.share_waiting_message(apply_breakoff=wait_for_stop) continue if consumed == "wait": if not wait_for_stop: continue if break_now(): PyFunceble.facility.Logger.debug( "Waited sufficiently. Stopping current worker." ) # The real (break) action shouldn't be handled here. self.exit_it.set() continue PyFunceble.facility.Logger.debug( "We need to wait a bit more. Continue waiting." ) self.share_waiting_message(apply_breakoff=wait_for_stop) continue try: result = self.target(consumed) except (EOFError, KeyboardInterrupt): PyFunceble.facility.Logger.info( "Got EOFError/KeyboardInterrupt. Stopping worker." ) self.global_exit_event.set() break if result is not None: self.add_to_output_queue(result) PyFunceble.facility.Logger.info( "Produced: %r", result, ) break_time = datetime.now(timezone.utc) + timedelta( seconds=self.MINING_WAIT_TIME ) except Exception as exception: # pylint: disable=broad-except PyFunceble.facility.Logger.critical( "Error while running target", exc_info=True ) trace = traceback.format_exc() self._child_connection.send((exception, trace)) self.exit_it.set() raise exception def terminate(self) -> None: """ Terminate our worker. """ self.exit_it.set() if self.input_queue: # Necessary to avoid blocking. self.add_to_input_queue("stop", destination_worker=self.name) PyFunceble-4.2.29.dev/PyFunceble/cli/processes/workers/chancy_producer.py000066400000000000000000000104721467462152100264640ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our producer worker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Any, Optional, Tuple import PyFunceble.facility import PyFunceble.storage from PyFunceble.checker.status_base import CheckerStatusBase from PyFunceble.cli.processes.workers.producer import ProducerWorker class ChancyProducerWorker(ProducerWorker): """ Provides our chancy producer worker. .. warning:: This chancy producer does not provide any guarantee. The flow that keep PyFunceble safe are here unleashed. USE AT YOUR OWN RISK. GOOD LUCK! """ STD_NAME: str = "pyfunceble_chancy_producer_worker" def target(self, consumed: Any) -> Optional[Tuple[Any, ...]]: if not isinstance(consumed, tuple): PyFunceble.facility.Logger.info( "Skipping latest dataset because consumed data was not a tuple." ) return None # Just for human brain. test_dataset, test_result = consumed if not isinstance(test_dataset, dict): PyFunceble.facility.Logger.info( "Skipping because test dataset is not a dictionnary." ) return None if self.should_we_ignore(test_result): PyFunceble.facility.Logger.info( "Ignored test dataset. Reason: No output wanted." ) return None if not isinstance(test_result, CheckerStatusBase): PyFunceble.facility.Logger.info( "Skipping latest dataset because consumed status is not " "a status object.." ) return None self.run_whois_backup(test_result) self.run_inactive_backup(test_dataset, test_result) self.run_continue_backup(test_dataset, test_result) if not self.should_we_block_status_file_printer(test_dataset, test_result): self.run_counter(test_dataset, test_result) test_dataset["from_chancy_producer"] = True return test_dataset, test_result PyFunceble-4.2.29.dev/PyFunceble/cli/processes/workers/chancy_tester.py000066400000000000000000000070521467462152100261470ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our chancy tester worker. The chancy tester worker is a worker that abstract from the standard tester worker. It just get rid of the walls between some of the component of our data workflow. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Any, Optional, Tuple from PyFunceble.cli.processes.workers.producer import ProducerWorker from PyFunceble.cli.processes.workers.tester import TesterWorker class ChancyTesterWorker(TesterWorker): """ Provides our chancy tester worker. The chancy worker breaks the walls between some of the core component of our data workflow. .. warning:: This chancy tester does not provide any guarantee. The flow that keep PyFunceble safe are here unleashed. USE AT YOUR OWN RISK. GOOD LUCK! """ STD_NAME: str = "pyfunceble_chancy_tester_worker" def __post_init__(self) -> None: self.producer_worker = ProducerWorker(**self._params) return super().__post_init__() def target(self, consumed: dict) -> Optional[Tuple[Any, ...]]: """ The actually wall destructor. :param consummed: The data that needs to be tested. """ return self.producer_worker.target(super().target(consumed)) PyFunceble-4.2.29.dev/PyFunceble/cli/processes/workers/dir_files_sorter.py000066400000000000000000000135561467462152100266600ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our directory files sorter worker. This is the description of a single directory file sorter worker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 concurrent.futures import os from typing import Any, List, Optional, Tuple import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.cli.processes.workers.file_sorter_base import FileSorterWorkerBase class DireFileSorterWorker(FileSorterWorkerBase): """ Provides our directory files sorter worker. The objective of this worker is to provides a single worker (or process if you prefer) which will be used to handle the sorting of the content of a submitted directory. Expected (input) message: :: { "directory": str, "remove_duplicates": bool, "write_header": bool } Expected (output) message: :: None """ STD_NAME: str = "pyfunceble_dir_files_sorter_worker" @staticmethod def get_files_to_sort(directory: str) -> List[str]: """ Provides the list of files to sort. :param directory: The directory to start from. """ dirs_to_ignore = [ os.path.join( directory, PyFunceble.cli.storage.OUTPUTS.logs.directories.parent, ), os.path.join(directory, PyFunceble.cli.storage.OUTPUTS.splitted.directory), ] files_to_ignore = [ ".gitignore", ".gitkeep", PyFunceble.cli.storage.TEST_RUNNING_FILE, PyFunceble.cli.storage.COUNTER_FILE, PyFunceble.cli.storage.REGISTRAR_COUNTER_FILE, PyFunceble.cli.storage.PRE_LOADER_FILE, ] result = [] for root, _, files in os.walk(directory): if any(x in root for x in dirs_to_ignore): continue for file in files: if file in files_to_ignore: continue result.append(os.path.join(root, file)) PyFunceble.facility.Logger.debug("List of files to sort:\n%r.", result) return result def target(self, consumed: Any) -> Optional[Tuple[Any, ...]]: if ( not isinstance(consumed, dict) and "directory" not in consumed or not consumed["directory"] ): PyFunceble.facility.Logger.info( "Ignoring consumed data because no data to work with." ) return None # Just for human brain :-) directory = consumed["directory"] if "remove_duplicates" in consumed: remove_duplicates = consumed["remove_duplicates"] else: remove_duplicates = True if "write_header" in consumed: write_header = consumed["write_header"] else: write_header = True with concurrent.futures.ThreadPoolExecutor( max_workers=PyFunceble.storage.CONFIGURATION.cli_testing.max_workers, ) as executor: submitted_list = [] for file in self.get_files_to_sort(directory): submitted = executor.submit( self.process_file_sorting, file, remove_duplicates, write_header ) submitted_list.append(submitted) for submitted in concurrent.futures.as_completed(submitted_list): # Ensure that everything is finished if submitted.exception(): raise submitted.exception() return None PyFunceble-4.2.29.dev/PyFunceble/cli/processes/workers/file_sorter.py000066400000000000000000000100441467462152100256240ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our file sorter worker. This is the description of a file sorter worker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Any, Optional, Tuple import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.cli.processes.workers.file_sorter_base import FileSorterWorkerBase class FileSorterWorker(FileSorterWorkerBase): """ Provides our file sorter worker. The objective of this worker is to provides a single worker (or process if you prefer) which will be used to handle the sorting of the content of a given file. Expected (input) message: :: { "file": str, "remove_duplicates": bool, "write_header": bool } Expected (output) message: :: None """ STD_NAME: str = "pyfunceble_file_sorter_worker" def target(self, consumed: Any) -> Optional[Tuple[Any, ...]]: if ( not isinstance(consumed, dict) and "file" not in consumed or not consumed["file"] ): PyFunceble.facility.Logger.info( "Ignoring consumed data because no data to work with." ) return None # Just for human brain :-) file = consumed["file"] if "remove_duplicates" in consumed: remove_duplicates = consumed["remove_duplicates"] else: remove_duplicates = True if "write_header" in consumed: write_header = consumed["write_header"] else: write_header = True self.process_file_sorting( file, remove_duplicates=remove_duplicates, write_header=write_header ) return None PyFunceble-4.2.29.dev/PyFunceble/cli/processes/workers/file_sorter_base.py000066400000000000000000000175341467462152100266310ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our file sorter worker base. This is the base of all our file sorter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 heapq import os import secrets import tempfile from io import TextIOWrapper from itertools import islice from typing import Any, Generator, List, Tuple import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.cli.filesystem.printer.file import FilePrinter from PyFunceble.cli.processes.workers.base import WorkerBase from PyFunceble.cli.utils.sort import get_best_sorting_key from PyFunceble.helpers.file import FileHelper from PyFunceble.helpers.list import ListHelper class FileSorterWorkerBase(WorkerBase): """ Provides our the base of all our file sorters. """ MAX_LINES: int = 32_000 FILE_BUFFER_SIZE: int = 64 * 1024 def __post_init__(self) -> None: # We don't need to wait for anything here :-) self.accept_waiting_delay = False return super().__post_init__() @classmethod def process_file_sorting( cls, file: str, remove_duplicates: bool = True, write_header: bool = True, sorting_key: Any = None, ) -> None: """ Process the sorting of the given file. The idea is to split the file piece by piece and at the end join all sorted files. For that job, we create a temporary directory which will store the temporary files. :param file: The file to sort. :param remove_duplicates: Activates the deletion of duplicates. :param write_header: Activates the writing of the PyFunceble related header. .. warning:: When this is set to :py:class:`True`, we assume that the header itself was already given. Meaning that the first 2 commented lines will be excluded from the sorting and regenerated. :param sorting_key: The sorting key to apply while sorting. This is the lambda/function that goes into the :code:`key` argument of the :py:class:`sorted` function. """ # pylint: disable=too-many-locals,too-many-statements def merge_files( files: List[TextIOWrapper], ) -> Generator[Tuple[List[TextIOWrapper]], str, None]: """ Merges the given files and yield each "lines" of the merged file. :param files: The files to merge. """ result = [] for index, file in enumerate(files): try: iterator = iter(file) value = next(iterator) heapq.heappush( result, ((sorting_key(value), index, value, iterator, file)) ) except StopIteration: file.close() previous = None comment_count = 0 max_comment_count = 2 while result: ignore = False _, index, value, iterator, file = heapq.heappop(result) if remove_duplicates and value == previous: ignore = True if ( write_header and comment_count < max_comment_count and value[0] == "#" ): ignore = True max_comment_count += 1 if not ignore: yield value previous = value try: value = next(iterator) heapq.heappush( result, ((sorting_key(value), index, value, iterator, file)) ) except StopIteration: file.close() temp_directory = tempfile.TemporaryDirectory() temporary_output_file = os.path.join(temp_directory.name, secrets.token_hex(6)) if not sorting_key: sorting_key = get_best_sorting_key() file_helper = FileHelper(file) sorted_files = [] PyFunceble.facility.Logger.info("Started sort of %r.", file) with file_helper.open( "r", encoding="utf-8", buffering=cls.FILE_BUFFER_SIZE ) as file_stream: while True: to_sort = list(islice(file_stream, cls.MAX_LINES)) if not to_sort: break new_file = open( os.path.join(temp_directory.name, secrets.token_hex(6)), "w+", encoding="utf-8", buffering=cls.FILE_BUFFER_SIZE, ) new_file.writelines( ListHelper(to_sort) .remove_duplicates() .custom_sort(key_method=sorting_key) .subject ) new_file.flush() new_file.seek(0) sorted_files.append(new_file) with open( temporary_output_file, "w", cls.FILE_BUFFER_SIZE, encoding="utf-8" ) as file_stream: if write_header: file_stream.write(FilePrinter.STD_FILE_GENERATION) file_stream.write(FilePrinter.get_generation_date_line()) file_stream.write("\n\n") file_stream.writelines(merge_files(sorted_files)) FileHelper(temporary_output_file).move(file) PyFunceble.facility.Logger.info("Finished sort of %r.", file) temp_directory.cleanup() PyFunceble-4.2.29.dev/PyFunceble/cli/processes/workers/migrator.py000066400000000000000000000066571467462152100251520ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our migrator (base) worker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 traceback import PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.cli.processes.workers.base import WorkerBase class MigratorWorker(WorkerBase): """ Provides our migrator (base) worker. The objective of this worker is to provides a single worker (or process if you prefer) which will be used to handle the mining of dataset to test. """ STD_NAME: str = "pyfunceble_migrator_worker" def run(self) -> None: try: try: self.target(self.continuous_integration, db_session=self.db_session) except TypeError: self.target(self.continuous_integration) self._child_connection.send(None) except Exception as exception: # pylint: disable=broad-except PyFunceble.facility.Logger.critical( "Error while running target", exc_info=True ) trace = traceback.format_exc() self._child_connection.send((exception, trace)) raise exception PyFunceble-4.2.29.dev/PyFunceble/cli/processes/workers/miner.py000066400000000000000000000157111467462152100244270ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our miner worker. This is the description of a single miner worker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy import socket from typing import List, Optional, Tuple from domain2idna import domain2idna import PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.checker.status_base import CheckerStatusBase from PyFunceble.cli.processes.workers.base import WorkerBase from PyFunceble.cli.utils.stdout import print_single_line from PyFunceble.converter.url2netloc import Url2Netloc class MinerWorker(WorkerBase): """ Provides our miner worker. The objective of this worker is to provides a single worker (or process if you prefer) which will be used to handle the mining of dataset to test. """ STD_NAME: str = "pyfunceble_miner_worker" INACTIVE_STATUSES: Tuple[str, ...] = ( PyFunceble.storage.STATUS.down, PyFunceble.storage.STATUS.invalid, ) url2netloc: Optional[Url2Netloc] = None def __post_init__(self) -> None: self.url2netloc = Url2Netloc() return super().__post_init__() @staticmethod def mine_from(subject: str) -> Optional[List[str]]: """ Given the subject to work from, try to get the related subjects. :param subject: The URL to start from. """ PyFunceble.facility.Logger.info("Started mining from %r", subject) result = [] try: req = PyFunceble.factory.Requester.get(subject, allow_redirects=True) for element in req.history: if "location" in element.headers: result.append(element.headers["location"]) result.extend([x for x in req.history if isinstance(x, str)]) except ( PyFunceble.factory.Requester.exceptions.RequestException, PyFunceble.factory.Requester.exceptions.ConnectionError, PyFunceble.factory.Requester.exceptions.Timeout, PyFunceble.factory.Requester.exceptions.InvalidURL, PyFunceble.factory.Requester.urllib3_exceptions.InvalidHeader, socket.timeout, ): PyFunceble.facility.Logger.error( "Could not mine from %r", subject, exc_info=True ) PyFunceble.facility.Logger.debug("Mined from %r:\n%r.", subject, result) PyFunceble.facility.Logger.info("Finished mining from %r", subject) return result def target(self, consumed: Tuple[dict, CheckerStatusBase]) -> None: if not isinstance(consumed, tuple) or not isinstance( consumed[1], CheckerStatusBase ): PyFunceble.facility.Logger.info( "Skipping latest dataset because consumed data was not a tuple." ) return None # Just for human brain. test_dataset, test_result = consumed if "from_miner" in test_dataset: PyFunceble.facility.Logger.info( "Skipping dataset because it comes from the mining mechanism." ) return None if test_result.status in self.INACTIVE_STATUSES: PyFunceble.facility.Logger.info( "Skipping dataset because status is not active." ) return None if test_dataset["subject_type"] == "domain": subject = f"http://{test_result.idna_subject}:80" else: # Assuming it's already a URL. subject = test_result.idna_subject print_single_line("M") self.add_to_output_queue("pyfunceble") self.share_waiting_message() mined = self.mine_from(subject) for url in mined: to_send = copy.deepcopy(test_dataset) to_send["from_miner"] = True if test_dataset["subject_type"] == "domain": netloc = self.url2netloc.set_data_to_convert(url).get_converted() if ":" in netloc: netloc = netloc[: netloc.find(":")] to_send["subject"] = netloc to_send["idna_subject"] = domain2idna(netloc) else: if not test_result.idna_subject.endswith("/") and url.endswith("/"): url = url[:-1] to_send["subject"] = url to_send["idna_subject"] = domain2idna(url) if to_send["idna_subject"] == test_result.idna_subject: PyFunceble.facility.Logger.info( "Skipping %r because found in test result.", url ) continue self.add_to_output_queue(to_send) # Returning None because we manually add into the queue. return None PyFunceble-4.2.29.dev/PyFunceble/cli/processes/workers/producer.py000066400000000000000000000417101467462152100251360ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our producer worker. This is the description of a single producer worker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 datetime import os from typing import Any, Optional, Tuple from domain2idna import domain2idna import PyFunceble.facility import PyFunceble.storage from PyFunceble.checker.status_base import CheckerStatusBase from PyFunceble.checker.utils.whois import get_whois_dataset_object from PyFunceble.cli.filesystem.counter import FilesystemCounter from PyFunceble.cli.filesystem.printer.file import FilePrinter from PyFunceble.cli.filesystem.printer.stdout import StdoutPrinter from PyFunceble.cli.filesystem.registrar_counter import RegistrarCounter from PyFunceble.cli.filesystem.status_file import StatusFileGenerator from PyFunceble.cli.processes.workers.base import WorkerBase from PyFunceble.cli.utils.stdout import get_template_to_use, print_single_line from PyFunceble.cli.utils.testing import ( get_continue_databaset_object, get_inactive_dataset_object, ) from PyFunceble.dataset.autocontinue.base import ContinueDatasetBase from PyFunceble.dataset.autocontinue.csv import CSVContinueDataset from PyFunceble.dataset.inactive.base import InactiveDatasetBase from PyFunceble.dataset.whois.base import WhoisDatasetBase from PyFunceble.query.platform import PlatformQueryTool class ProducerWorker(WorkerBase): """ Provides our producer worker. The objective of this worker is to provides a single worker (or process if you prefer) which will be used to handle the production of output to stdout or files. """ STD_NAME: str = "pyfunceble_producer_worker" stdout_printer: Optional[StdoutPrinter] = None file_printer: Optional[FilePrinter] = None whois_dataset: Optional[WhoisDatasetBase] = None inactive_dataset: Optional[InactiveDatasetBase] = None continue_dataset: Optional[ContinueDatasetBase] = None status_file_generator: Optional[StatusFileGenerator] = None counter: Optional[FilesystemCounter] = None registrar_counter: Optional[RegistrarCounter] = None platform_query_tool: Optional[PlatformQueryTool] = None header_already_printed: Optional[bool] = None INACTIVE_STATUSES: Tuple[str, ...] = ( PyFunceble.storage.STATUS.down, PyFunceble.storage.STATUS.invalid, ) def __post_init__(self) -> None: skip_columns = [] if not PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.registrar: skip_columns.append("registrar") self.stdout_printer = StdoutPrinter(skip_column=skip_columns) self.file_printer = FilePrinter(skip_column=skip_columns) self.whois_dataset = get_whois_dataset_object(db_session=self.db_session) self.inactive_dataset = get_inactive_dataset_object(db_session=self.db_session) self.continue_dataset = get_continue_databaset_object( db_session=self.db_session ) self.status_file_generator = StatusFileGenerator().guess_all_settings() self.counter = FilesystemCounter() self.registrar_counter = RegistrarCounter() self.platform_query_tool = PlatformQueryTool() self.header_already_printed = False return super().__post_init__() @staticmethod def should_we_ignore(test_result: CheckerStatusBase) -> bool: """ Checks if we should ignore the given datasets. :param test_result: The test result to check. """ return isinstance(test_result, str) and test_result.startswith("ignored_") @staticmethod def should_we_print_status_to_stdout(status: str) -> bool: """ Checks if we are allows to print the given status (to stdout). :param status: The status to check. """ if isinstance( PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.status, list ): to_keep = PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.status else: to_keep = [PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.status] to_keep = [x.upper() for x in to_keep] status = status.upper() return "ALL" in to_keep or status in to_keep def should_we_block_status_file_printer( self, test_dataset: dict, test_result: CheckerStatusBase ) -> bool: """ Checks if we should block the file printer. The reason behindn this is that we don't want to generate an output when a subject was already into the inactive database. """ return ( "from_inactive" in test_dataset and test_result.status in self.INACTIVE_STATUSES ) def run_stdout_printer(self, test_result: CheckerStatusBase) -> None: """ Runs the stdout printer (if necessary). :param test_result: The rest result dataset. """ if not PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet: # pylint: disable=line-too-long if self.should_we_print_status_to_stdout(test_result.status): self.stdout_printer.template_to_use = get_template_to_use() if not self.header_already_printed: self.stdout_printer.print_header() self.header_already_printed = True self.stdout_printer.set_dataset( test_result.to_dict() ).print_interpolated_line() else: print_single_line() else: print_single_line() def run_whois_backup(self, test_result: CheckerStatusBase) -> None: """ Runs the backup or update of the WHOIS record in our dataset storage. :param test_result: The test result. """ if ( hasattr(test_result, "expiration_date") and test_result.expiration_date and test_result.whois_record ): # Note: The whois record is always given if the status does not come # from the database. self.whois_dataset.update( { "subject": test_result.subject, "idna_subject": test_result.idna_subject, "expiration_date": test_result.expiration_date, "epoch": datetime.datetime.strptime( test_result.expiration_date, "%d-%b-%Y" ).timestamp(), "registrar": test_result.registrar, } ) def run_inactive_backup( self, test_dataset: dict, test_result: CheckerStatusBase ) -> None: """ Runs the backup or update of the Inactive dataset storage. The idea is that if the status is OK (active), we just remove it from the dataset storage. Otherwise, we just keep it in there :-) """ if test_dataset["type"] != "single" and self.inactive_dataset.authorized: dataset = test_result.to_dict() dataset.update(test_dataset) PyFunceble.facility.Logger.debug("Test Dataset: %r", test_dataset) PyFunceble.facility.Logger.debug("Test Result: %r", test_result) if "from_inactive" in dataset: if test_result.status in self.INACTIVE_STATUSES: if dataset["destination"]: # Note: This handles the case that someone try to test a # single subject. # In fact, we should not generate any file if the output # directory is not given. self.inactive_dataset.update(dataset) else: self.inactive_dataset.remove(dataset) elif ( test_result.status in self.INACTIVE_STATUSES and dataset["destination"] ): self.inactive_dataset.update(dataset) def run_continue_backup( self, test_dataset: dict, test_result: CheckerStatusBase ) -> None: """ Runs the backup or update of the auto-continue dataset storage. """ if test_dataset["type"] != "single" and self.continue_dataset.authorized: dataset = test_result.to_dict() dataset.update(test_dataset) if ( isinstance(self.continue_dataset, CSVContinueDataset) and dataset["output_dir"] ): # Note: This handles the case that someone try to test a single subject. # In fact, we should not generate any file if the output directory # is not given. # # The exception handler is just there to catch the case that the # method is not implemented because we are more likely using an # alternative backup (for example mariadb). self.continue_dataset.set_base_directory(dataset["output_dir"]) self.continue_dataset.update(dataset) def run_ignored_file_printer(self, test_dataset: dict, test_result: str) -> None: """ Runs the analytic behind the file printer. .. warning:: Thie method assume that the givne dataset is ignored from the normal file printer. """ if ( test_result == "ignored_inactive" and test_dataset["destination"] and not PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.no_file ): if "idna_subject" not in test_dataset: # The printer always prints the idna subject. test_dataset["idna_subject"] = domain2idna(test_dataset["subject"]) # We use this object just to get the output directory :-) self.status_file_generator.set_parent_dirname(test_dataset["destination"]) # We now generate the file which let the end-user know that # we ignored the test of the current test dataset because there # is no need to retest it yet. # pylint: disable=line-too-long self.file_printer.destination = os.path.join( self.status_file_generator.get_output_basedir(), PyFunceble.cli.storage.OUTPUTS.logs.directories.parent, PyFunceble.cli.storage.OUTPUTS.logs.filenames.inactive_not_retested, ) self.file_printer.template_to_use = "plain" self.file_printer.dataset = test_dataset self.file_printer.print_interpolated_line() def run_status_file_printer( self, test_dataset: dict, test_result: CheckerStatusBase ) -> None: """ Runs the status file printer. """ if ( test_dataset["destination"] and not PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.no_file ): previous_allow_hosts_file = self.status_file_generator.allow_hosts_files previous_allow_plain_file = self.status_file_generator.allow_plain_files self.status_file_generator.parent_dirname = test_dataset["destination"] self.status_file_generator.status = test_result self.status_file_generator.test_dataset = test_dataset if test_dataset["subject_type"] == "url": self.status_file_generator.allow_hosts_files = False self.status_file_generator.allow_plain_files = True self.status_file_generator.start() self.status_file_generator.allow_hosts_files = previous_allow_hosts_file self.status_file_generator.allow_plain_files = previous_allow_plain_file def run_counter(self, test_dataset: dict, test_result: CheckerStatusBase) -> None: """ Runs the counter of the current file. """ if not PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.no_file: # Note: We don't want hidden data to be counted. self.counter.set_differ_to_inline(True).set_parent_dirname( test_dataset["destination"] ) self.registrar_counter.set_differ_to_inline(True).set_parent_dirname( test_dataset["destination"] ) self.counter.count(test_result) if hasattr(test_result, "registrar") and test_result.registrar: self.registrar_counter.count(test_result.registrar) self.counter.set_differ_to_inline(False) self.registrar_counter.set_differ_to_inline(False) if hasattr(test_result, "registrar") and test_result.registrar: self.registrar_counter.set_parent_dirname( test_dataset["destination"] ).count(test_result.registrar) def target(self, consumed: Any) -> Optional[Tuple[Any, ...]]: if not isinstance(consumed, tuple): PyFunceble.facility.Logger.info( "Skipping latest dataset because consumed data was not a tuple." ) return None # Just for human brain. test_dataset, test_result = consumed if not isinstance(test_dataset, dict): PyFunceble.facility.Logger.info( "Skipping because test dataset is not a dictionnary." ) return None if self.should_we_ignore(test_result): PyFunceble.facility.Logger.info( "Ignored test dataset. Reason: No output wanted." ) self.run_ignored_file_printer(test_dataset, test_result) return None if not isinstance(test_result, CheckerStatusBase): PyFunceble.facility.Logger.info( "Skipping latest dataset because consumed status is not " "a status object.." ) return None if test_dataset["type"] == "platform-contribution": self.platform_query_tool.deliver_contract( test_dataset["contract"], test_result ) if ( PyFunceble.storage.CONFIGURATION.platform.push and test_result.status_source != "PLATFORM" ): self.platform_query_tool.push(test_result) if not PyFunceble.storage.CONFIGURATION.cli_testing.chancy_tester: self.run_whois_backup(test_result) self.run_inactive_backup(test_dataset, test_result) self.run_continue_backup(test_dataset, test_result) if not self.should_we_block_status_file_printer(test_dataset, test_result): self.run_status_file_printer(test_dataset, test_result) if not PyFunceble.storage.CONFIGURATION.cli_testing.chancy_tester: self.run_counter(test_dataset, test_result) self.run_stdout_printer(test_result) test_dataset["from_producer"] = True return test_dataset, test_result PyFunceble-4.2.29.dev/PyFunceble/cli/processes/workers/tester.py000066400000000000000000000267311467462152100246270ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our tester worker. This is the description of a single tester worker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 time from typing import Any, Optional, Tuple import PyFunceble.cli.utils.testing import PyFunceble.facility import PyFunceble.factory from PyFunceble.checker.availability.domain_and_ip import DomainAndIPAvailabilityChecker from PyFunceble.checker.availability.url import URLAvailabilityChecker from PyFunceble.checker.base import CheckerBase from PyFunceble.checker.reputation.domain_and_ip import DomainAndIPReputationChecker from PyFunceble.checker.reputation.url import URLReputationChecker from PyFunceble.checker.syntax.domain_and_ip import DomainAndIPSyntaxChecker from PyFunceble.checker.syntax.ip import IPSyntaxChecker from PyFunceble.checker.syntax.url import URLSyntaxChecker from PyFunceble.cli.processes.workers.base import WorkerBase from PyFunceble.cli.utils.stdout import print_single_line from PyFunceble.dataset.autocontinue.base import ContinueDatasetBase from PyFunceble.dataset.autocontinue.csv import CSVContinueDataset from PyFunceble.dataset.inactive.base import InactiveDatasetBase from PyFunceble.helpers.regex import RegexHelper class TesterWorker(WorkerBase): """ Provides our tester worker. The objective of this worker is to provides a single worker (or process if you prefer) which will be used to handle the tests. """ STD_NAME: str = "pyfunceble_tester_worker" continue_dataset: Optional[ContinueDatasetBase] = None inactive_dataset: Optional[InactiveDatasetBase] = None testing_object: Optional[CheckerBase] = None known_testing_objects: dict = {} initiated_testing_objects: dict = {} def __post_init__(self) -> None: self.continue_dataset = ( PyFunceble.cli.utils.testing.get_continue_databaset_object( db_session=self.db_session ) ) self.inactive_dataset = ( PyFunceble.cli.utils.testing.get_inactive_dataset_object( db_session=self.db_session ) ) self.known_testing_objects = { "SYNTAX": {"domain": DomainAndIPSyntaxChecker, "url": URLSyntaxChecker}, "AVAILABILITY": { "domain": DomainAndIPAvailabilityChecker, "url": URLAvailabilityChecker, }, "REPUTATION": { "domain": DomainAndIPReputationChecker, "url": URLReputationChecker, }, } self.initiated_testing_objects = { "SYNTAX": {"domain": None, "url": None}, "AVAILABILITY": { "domain": None, "url": None, }, "REPUTATION": { "domain": None, "url": None, }, } return super().__post_init__() @staticmethod def should_be_ignored(subject: str) -> bool: """ Checks if the given subject should be ignored. """ # pylint: disable=line-too-long regex_ignore = r"localhost$|localdomain$|local$|broadcasthost$|0\.0\.0\.0$|allhosts$|allnodes$|allrouters$|localnet$|loopback$|mcastprefix$|ip6-mcastprefix$|ip6-localhost$|ip6-loopback$|ip6-allnodes$|ip6-allrouters$|ip6-localnet$" if RegexHelper(regex_ignore).match(subject, return_match=False): PyFunceble.facility.Logger.info( "Ignoring %r because it is in our default regex.", subject ) return True if ( not PyFunceble.storage.CONFIGURATION.cli_testing.local_network and IPSyntaxChecker(subject).is_reserved() ): PyFunceble.facility.Logger.info( "Ignoring %r because it is a reserved IP and we are not testing " "for/in a local network.", subject, ) return True if bool( PyFunceble.storage.CONFIGURATION.cli_testing.file_filter ) and not RegexHelper( PyFunceble.storage.CONFIGURATION.cli_testing.file_filter ).match( subject, return_match=False ): PyFunceble.facility.Logger.info( "Ignoring %r because it does not match the filter to look for.", subject, ) return True PyFunceble.facility.Logger.info( "Allowed to test %r.", subject, ) return False def _init_testing_object( self, subject_type: str, checker_type: str ) -> Optional[CheckerBase]: """ Provides the object to use for testing. :raise ValueError: When the given subject type is unknown. """ if checker_type not in self.known_testing_objects: raise ValueError(f" ({checker_type!r}) is unknown.") if subject_type not in self.known_testing_objects[checker_type]: raise ValueError(f" ({subject_type!r}) is unknown.") if not self.initiated_testing_objects[checker_type][subject_type]: self.initiated_testing_objects[checker_type][ subject_type ] = self.known_testing_objects[checker_type][subject_type]( db_session=self.db_session ).set_do_syntax_check_first( # We want to always check the syntax first (ONLY UNDER THE CLI) not bool(PyFunceble.storage.CONFIGURATION.cli_testing.local_network) ) self.testing_object = self.initiated_testing_objects[checker_type][subject_type] return self.testing_object def target(self, consumed: dict) -> Optional[Tuple[Any, ...]]: """ This the target that is run to process something. This method should return a result which will pu send to the output queue. """ if ( PyFunceble.factory.Requester.session and "Connection" not in PyFunceble.factory.Requester.session.headers ): # Just close the connection immediately. This prevent potential infinite # streams. PyFunceble.factory.Requester.session.headers["Connection"] = "close" if not isinstance(consumed, dict): PyFunceble.facility.Logger.debug( "Skipping latest dataset because consumed data was not " "a dictionnary." ) return None # Just for human brain. test_dataset = consumed if self.should_be_ignored(test_dataset["idna_subject"]): # X means that it was ignored because of our core ignore procedure. print_single_line("X") return None if PyFunceble.storage.CONFIGURATION.cli_testing.cooldown_time > 0: PyFunceble.facility.Logger.info( "Sleeping: %rs for our own safety :-)", PyFunceble.storage.CONFIGURATION.cli_testing.cooldown_time, ) # Apply cooldowntime. time.sleep(PyFunceble.storage.CONFIGURATION.cli_testing.cooldown_time) PyFunceble.facility.Logger.info( "Slept: %rs for our own safety :-)", PyFunceble.storage.CONFIGURATION.cli_testing.cooldown_time, ) if test_dataset["type"] != "single": if test_dataset["output_dir"] and "from_preload" not in test_dataset: if isinstance(self.continue_dataset, CSVContinueDataset): self.continue_dataset.set_base_directory(test_dataset["output_dir"]) if self.continue_dataset.exists(test_dataset): # A means that it was ignored because of the continue # logic. PyFunceble.facility.Logger.info( "Ignoring %r because it was already tested previously " "(continue).", test_dataset["idna_subject"], ) PyFunceble.cli.utils.stdout.print_single_line("A") return None if "from_inactive" not in test_dataset and self.inactive_dataset.exists( test_dataset ): # "I" means that it was ignored because of the inactive (db) # logic. PyFunceble.facility.Logger.info( "Ignoring %r because it was already tested previously " "(inactive).", test_dataset["idna_subject"], ) PyFunceble.cli.utils.stdout.print_single_line("I") return test_dataset, "ignored_inactive" PyFunceble.facility.Logger.info( "Started test of %r.", test_dataset["idna_subject"], ) self._init_testing_object( test_dataset["subject_type"], test_dataset["checker_type"] ) result = ( self.testing_object.set_subject(test_dataset["idna_subject"]) .query_status() .get_status() ) PyFunceble.facility.Logger.info( "Successfully handled %r.", test_dataset["idna_subject"], ) PyFunceble.facility.Logger.debug("Got status:\n%r.", result) return test_dataset, result PyFunceble-4.2.29.dev/PyFunceble/cli/scripts/000077500000000000000000000000001467462152100207235ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/scripts/__init__.py000066400000000000000000000046051467462152100230410ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some of our scripts. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/scripts/iana.py000066400000000000000000000233711467462152100222130ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our iana file generator. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 concurrent.futures from typing import Dict, Optional, Tuple import PyFunceble.facility from PyFunceble.dataset.iana import IanaDataset from PyFunceble.helpers.dict import DictHelper from PyFunceble.helpers.download import DownloadHelper from PyFunceble.helpers.regex import RegexHelper from PyFunceble.query.whois.query_tool import WhoisQueryTool class IanaDBGenerator: """ Provides an interface for the generation of the iana database file. """ UPSTREAM_LINK: str = "https://www.iana.org/domains/root/db" """ Provides the upstream link. """ IANA_WHOIS_SERVER: str = "whois.iana.org" """ The WHOIS server provided by the IANA. """ MANUAL_SERVER: Dict[str, str] = { "bm": "whois.afilias-srs.net", "bz": "whois.afilias-grs.net", "cd": "chois.nic.cd", "cm": "whois.netcom.cm", "fj": "whois.usp.ac.fj", "ga": "whois.my.ga", "int": "whois.iana.org", "ipiranga": " whois.nic.ipiranga", "lc": "whois2.afilias-grs.net", "now": " whois.nic.now", "pharmacy": " whois.nic.pharmacy", "piaget": " whois.nic.piaget", "ps": "whois.pnina.ps", "rw": "whois.ricta.org.rw", "shaw": "whois.afilias-srs.net", "xn--1ck2e1b": "whois.nic.xn--1ck2e1b", "xn--2scrj9c": "whois.inregistry.net", "xn--3hcrj9c": "whois.inregistry.net", "xn--45br5cyl": "whois.inregistry.net", "xn--45brj9c": "whois.inregistry.net", "xn--8y0a063a": "whois.nic.xn--8y0a063a", "xn--bck1b9a5dre4c": "whois.nic.xn--bck1b9a5dre4c", "xn--cck2b3b": "whois.nic.xn--cck2b3b", "xn--czr694b": "whois.nic.xn--czr694b", "xn--e1a4c": "whois.eu", "xn--eckvdtc9d": "whois.nic.xn--eckvdtc9d", "xn--fct429k": "whois.nic.xn--fct429k", "xn--fpcrj9c3d": "whois.inregistry.net", "xn--fzc2c9e2c": "whois.nic.lk", "xn--g2xx48c": "whois.nic.xn--g2xx48c", "xn--gckr3f0f": "whois.nic.xn--gckr3f0f", "xn--gecrj9c": "whois.inregistry.net", "xn--gk3at1e": "whois.nic.xn--gk3at1e", "xn--h2breg3eve": "whois.inregistry.net", "xn--h2brj9c": "whois.inregistry.net", "xn--h2brj9c8c": "whois.inregistry.net", "xn--imr513n": "whois.nic.xn--imr513n", "xn--jvr189m": "whois.nic.xn--jvr189m", "xn--kpu716f": "whois.nic.xn--kpu716f", "xn--mgba3a3ejt": "whois.nic.xn--mgba3a3ejt", "xn--mgbb9fbpob": "whois.nic.xn--mgbb9fbpob", "xn--mgbbh1a": "whois.inregistry.net", "xn--mgbbh1a71e": "whois.inregistry.net", "xn--mgbgu82a": "whois.inregistry.net", "xn--nyqy26a": "whois.nic.xn--nyqy26a", "xn--otu796d": "whois.nic.xn--otu796d", "xn--pbt977c": "whois.nic.xn--pbt977c", "xn--rhqv96g": "whois.nic.xn--rhqv96g", "xn--rovu88b": "whois.nic.xn--rovu88b", "xn--rvc1e0am3e": "whois.inregistry.net", "xn--s9brj9c": "whois.inregistry.net", "xn--ses554g": "whois.registry.knet.cn", "xn--wgbh1c": "whois.dotmasr.eg", "xn--xkc2al3hye2a": "whois.nic.lk", "xn--xkc2dl3a5ee0h": "whois.inregistry.net", "za": "whois.registry.net.za", } _destination: Optional[str] = None database: dict = {} """ An internal storage map. """ def __init__(self, destination: Optional[str] = None) -> None: if destination is not None: self.destination = destination else: self.destination = IanaDataset().source_file @property def destination(self) -> Optional[str]: """ Provides the current state of the :code:`_destination` attribute. """ return self._destination @destination.setter def destination(self, value: str) -> None: """ Sets the destination to write. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._destination = value def set_destination(self, value: str) -> "IanaDBGenerator": """ Sets the destination to write. :param value: The value to set. """ self.destination = value return self def get_referrer_from_extension(self, extension: str) -> Optional[str]: """ Given an extension, tries to get or guess its extension. """ whois_query_tool = WhoisQueryTool() dummy_domain = f"hello.{extension}" iana_record = ( whois_query_tool.set_server(self.IANA_WHOIS_SERVER) .set_subject(dummy_domain) .record ) if iana_record and "refer" in iana_record: regex_referrer = r"(?s)refer\:\s+([a-zA-Z0-9._-]+)\n" matched = RegexHelper(regex_referrer).match( iana_record, return_match=True, group=1 ) if matched: return matched possible_server = f"whois.nic.{extension}" response = whois_query_tool.set_server(possible_server).record if response: return possible_server if extension in self.MANUAL_SERVER: possible_server = self.MANUAL_SERVER[extension] response = whois_query_tool.set_server(possible_server).record if response: return possible_server return None def get_extension_and_referrer_from_block( self, block: str ) -> Tuple[Optional[str], Optional[str]]: """ Given an HTML block, we try to extract an extension and it's underlying referrer (WHOIS server). The referrer is extracted from the official IANA page, and guessed if missing. :param block: The block to parse. """ regex_valid_extension = r"(/domains/root/db/)(.*)(\.html)" regex_helper = RegexHelper(regex_valid_extension) if regex_helper.match(block, return_match=False): extension = regex_helper.match(block, return_match=True, group=2) if extension: return extension, self.get_referrer_from_extension(extension) return None, None def start(self, max_workers: Optional[int] = None) -> "IanaDBGenerator": """ Starts the generation of the dataset file. :param max_workers: The maximal number of workers we are allowed to use. """ raw_data = ( DownloadHelper(self.UPSTREAM_LINK) .download_text() .split('') ) with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: for extension, whois_server in executor.map( self.get_extension_and_referrer_from_block, raw_data ): if extension: self.database[extension] = whois_server PyFunceble.facility.Logger.debug( "Got: extension: %r ; whois server: %r", extension, whois_server ) DictHelper(self.database).to_json_file(self.destination) return self PyFunceble-4.2.29.dev/PyFunceble/cli/scripts/production.py000066400000000000000000000365341467462152100234760ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some of our scripts. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy import functools import os import pathlib from typing import List, Optional import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.storage from PyFunceble.cli.filesystem.dir_structure.backup import DirectoryStructureBackup from PyFunceble.helpers.dict import DictHelper from PyFunceble.helpers.file import FileHelper from PyFunceble.helpers.regex import RegexHelper from PyFunceble.utils.version import VersionUtility class ProductionPrep: """ Provides an interface for the production file modification. The idea is that we always have 2 branches: the `dev` and the `master` branch. We want to fix all the URL to point to the right one, so this interface just provides everything needed for that job. Another important part is the cleanup of the production environment. What is meant is the cleanup of the `output/` directory and the construction of the dir_structure file. .. warning:: This class assumes that you know what you are doing. Meaning that you should run this only if your are developing PyFunceble. """ VERSION_FILE_PATH: str = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.DISTRIBUTED_VERSION_FILENAME, ) AVAILABLE_BRANCHES: List[str] = ["dev", "master"] regex_helper: RegexHelper = RegexHelper() file_helper: FileHelper = FileHelper() dict_helper: DictHelper = DictHelper() version_utility: VersionUtility = VersionUtility(PyFunceble.storage.PROJECT_VERSION) version_file_content: Optional[dict] = None """ A copy of the local version file. """ _branch: Optional[str] = None previous_version: Optional[str] = None """ Provides the previous version (from :code:`version_file_content`) """ def __init__(self, branch: Optional[str] = None) -> None: self.version_file_content = self.dict_helper.from_yaml_file( self.VERSION_FILE_PATH ) self.previous_version = copy.deepcopy( self.version_file_content["current_version"] ) if branch is not None: self.branch = branch def ensure_branch_is_given(func): # pylint: disable=no-self-argument """ Ensures that the branch is given before running the decorated method. :raise TypeError: When the :code:`self.branch` is not set. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.branch, str): raise TypeError( f" should be {str}, " f"{type(self.branch)} given." ) return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @property def branch(self) -> Optional[str]: """ Provides the current state of the :code:`_branch` attribute. """ return self._branch @branch.setter def branch(self, value: str) -> None: """ Sets the branch to act with. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._branch = value def set_branch(self, value: str) -> "ProductionPrep": """ Sets the branch to act with. :param value: The value to set. """ self.branch = value return self def should_be_deprecated(self, previous_version: str) -> bool: """ Checks if we should deprecates the current version. """ splitted = self.version_utility.get_splitted(previous_version)[0] local_splitted = self.version_utility.get_splitted( self.version_utility.local_version )[0] for index, version_part in enumerate(splitted[:2]): if int(version_part) < int(local_splitted[index]): return True return False @ensure_branch_is_given def update_urls(self, file: str) -> "ProductionPrep": """ Updates the common URLS which are in the given file. :param file: The file to work with. :raise FileNotFoundError: When the given :code:`file` is not found. """ if self.branch == "dev": regexes = [ (r"PyFunceble\/%s\/" % "master", "PyFunceble/%s/" % "dev"), ("=%s" % "master", "=%s" % "dev"), (r"/{1,}en\/%s" % "latest", "/en/%s" % "dev"), (r"\/pyfunceble-dev.png", "/pyfunceble-%s.png" % "dev"), (r"\/project\/pyfunceble$", "/project/pyfunceble-%s" % "dev"), ( r"\/badge\/pyfunceble(/month|/week|)$", "/badge/pyfunceble-%s\\1" % "dev", ), (r"\/blob\/%s\/" % "master", "/blob/%s/" % "dev"), (r"\/pypi\/v\/pyfunceble\.png$", "/pypi/v/pyfunceble-%s.png" % "dev"), (r"\/(logo|graphmls|gifs\/raw)\/%s\/" % "master", "/\\1/%s/" % "dev"), (r"\/(PyFunceble\/tree)\/%s" % "master", "/\\1/%s" % "dev"), ] elif self.branch == "master": regexes = [ (r"PyFunceble\/%s\/" % "dev", "PyFunceble/%s/" % "master"), ("=%s" % "dev", "=%s" % "master"), (r"/{1,}en\/%s" % "dev", "/en/%s" % "latest"), (r"\/pyfunceble-dev.png", "/pyfunceble-dev.png"), (r"\/project\/pyfunceble-%s$" % "dev", "/project/pyfunceble"), ( r"\/badge\/pyfunceble-%s(/month|/week|)$" % "dev", "/badge/pyfunceble\\1", ), (r"\/blob\/%s\/" % "dev", "/blob/%s/" % "master"), ( r"\/pypi\/v\/pyfunceble-%s\.png$" % "dev", "/pypi/v/pyfunceble.png", ), (r"\/(logo|graphmls|gifs\/raw)\/%s\/" % "dev", "/\\1/%s/" % "master"), (r"\/(PyFunceble\/tree)\/%s" % "dev", "/\\1/%s" % "master"), ] else: regexes = {} self.file_helper.set_path(file) PyFunceble.facility.Logger.info( "Started to update our URL into %r", self.file_helper.path ) if not self.file_helper.exists(): raise FileNotFoundError(self.file_helper.path) to_update = self.file_helper.read() for regex, replacement in regexes: to_update = self.regex_helper.set_regex(regex).replace_match( to_update, replacement, multiline=True ) self.file_helper.write(to_update, overwrite=True) PyFunceble.facility.Logger.info( "Finished to update our URL into %r", self.file_helper.path ) return self @staticmethod def update_code_format() -> "ProductionPrep": """ Updates the format of the source code using black. """ # pylint: disable=import-outside-toplevel, import-error import black import isort def format_file(file: str, isortconfig: isort.settings.Config) -> None: """ Formats the given file using black. :param file: The file to format. :parm isortconfig: The configuration to apply while sorting the imports. """ isort.api.sort_file(pathlib.Path(file), config=isortconfig) black.format_file_in_place( pathlib.Path(file), fast=False, mode=black.Mode(), write_back=black.WriteBack.YES, ) PyFunceble.facility.Logger.info("Update format of %r", file) isort_config = isort.settings.Config(settings_file="setup.cfg") files = [ os.path.join(PyFunceble.storage.CONFIG_DIRECTORY, "setup.py"), ] for file in files: format_file(file, isort_config) for root, _, files in os.walk( os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.PROJECT_NAME ) ): if "__pycache__" in root: continue for file in files: if not file.endswith(".py"): continue format_file(os.path.join(root, file), isort_config) for root, _, files in os.walk( os.path.join(PyFunceble.storage.CONFIG_DIRECTORY, "tests") ): if "__pycache__" in root: continue for file in files: if not file.endswith(".py"): continue format_file(os.path.join(root, file), isort_config) def update_code_urls(self) -> "ProductionPrep": """ Updates all URL in the source code. """ to_ignore = [ ".gitignore", ".keep", ] self.update_urls(os.path.join(PyFunceble.storage.CONFIG_DIRECTORY, "setup.py")) for root, _, files in os.walk( os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.PROJECT_NAME ) ): if "__pycache__" in root: continue for file in files: if file in to_ignore: continue self.update_urls(os.path.join(root, file)) for root, _, files in os.walk( os.path.join(PyFunceble.storage.CONFIG_DIRECTORY, "tests") ): if "__pycache__" in root: continue for file in files: if file in to_ignore: continue self.update_urls(os.path.join(root, file)) @ensure_branch_is_given def update_setup_py(self) -> "ProductionPrep": """ Updates content of :code:`setup.py`. :raise FileNotFoundError: When the :code:`setup.py` file does not exists. """ PyFunceble.facility.Logger.info( "Started to update setup.py.", ) if self.branch == "dev": regexes = [ (r'name=".*"', 'name="PyFunceble-dev"'), (r'"Development\sStatus\s::.*"', '"Development Status :: 4 - Beta"'), ] elif self.branch == "master": regexes = [ (r'name=".*"', 'name="PyFunceble"'), ( r'"Development\sStatus\s::.*"', '"Development Status :: 5 - Production/Stable"', ), ] else: regexes = [ (r'name=".*"', 'name="PyFunceble-dev"'), ( r'"Development\sStatus\s::.*"', '"Development Status :: 3 - Alpha"', ), ] self.file_helper.set_path( os.path.join(PyFunceble.storage.CONFIG_DIRECTORY, "setup.py") ) if not self.file_helper.exists(): raise FileNotFoundError(self.file_helper.path) to_update = self.file_helper.read() for regex, replacement in regexes: to_update = self.regex_helper.set_regex(regex).replace_match( to_update, replacement, multiline=True ) self.file_helper.write(to_update, overwrite=True) PyFunceble.facility.Logger.info( "Started to update setup.py.", ) return self def update_version_file(self) -> "ProductionPrep": """ Updates the version file. """ PyFunceble.facility.Logger.info( "Started to update version file.", ) if self.should_be_deprecated(self.previous_version): to_append = ".".join( self.version_utility.get_splitted(self.version_utility.local_version)[0] ) if to_append not in self.version_file_content["deprecated"]: self.version_file_content["deprecated"].append(to_append) self.version_file_content["current_version"] = ( PyFunceble.storage.PROJECT_VERSION ) self.dict_helper.set_subject(self.version_file_content).to_yaml_file( self.VERSION_FILE_PATH ) PyFunceble.facility.Logger.info( "Finished to update version file.", ) return self def update_dir_structure_file(self) -> "ProductionPrep": """ Updates the directory structure. """ DirectoryStructureBackup().start() return self def start(self) -> "ProductionPrep": """ Starts the production process. """ return ( self.update_setup_py() .update_code_urls() .update_code_format() .update_version_file() ) PyFunceble-4.2.29.dev/PyFunceble/cli/scripts/public_suffix.py000066400000000000000000000145171467462152100241470ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our public suffix file generator. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 concurrent.futures from typing import Optional import PyFunceble.facility from PyFunceble.converter.wildcard2subject import Wildcard2Subject from PyFunceble.dataset.public_suffix import PublicSuffixDataset from PyFunceble.helpers.dict import DictHelper from PyFunceble.helpers.download import DownloadHelper from PyFunceble.helpers.list import ListHelper class PublicSuffixGenerator: """ Provides an interface for the generation of the public suffix file. """ UPSTREAM_LINK: str = ( "https://raw.githubusercontent.com/publicsuffix/list/%s/public_suffix_list.dat" % "master" ) """ Provides the upstream stream. """ COMMENT_SIGN: str = ["//", "!"] """ The sign which we should consider as comment. """ _destination: Optional[str] = None database: dict = {} """ An internal storage of our map. """ wildacrd2subject: Wildcard2Subject = Wildcard2Subject() def __init__(self, destination: Optional[str] = None) -> None: if destination is not None: self.destination = destination else: self.destination = PublicSuffixDataset().source_file @property def destination(self) -> Optional[str]: """ Provides the current state of the :code:`_destination` attribute. """ return self._destination @destination.setter def destination(self, value: str) -> None: """ Sets the destination to write. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._destination = value def set_destination(self, value: str) -> "PublicSuffixGenerator": """ Sets the destination to write. :param value: The value to set. """ self.destination = value return self def parse_line(self, line: str) -> dict: """ Parses and provides the dataset to save. """ line = line.strip() result = {} if not any(line.startswith(x) for x in self.COMMENT_SIGN) and "." in line: lines = [line, line.encode("idna").decode("utf-8")] lines = [ self.wildacrd2subject.set_data_to_convert(x).get_converted() for x in lines ] extension = lines[0].rsplit(".", 1)[-1] for suffix in lines: if extension in result: result[extension].append(suffix) else: result[extension] = [suffix] return result def start(self, max_workers: Optional[int] = None): """ Starts the generation of the dataset file. """ raw_data = DownloadHelper(self.UPSTREAM_LINK).download_text().split("\n") with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: for result in executor.map(self.parse_line, raw_data): for extension, suffixes in result.items(): if extension not in self.database: self.database[extension] = suffixes else: self.database[extension].extend(suffixes) PyFunceble.facility.Logger.debug( "Got: extension: %r ; suffixes: %r.", extension, suffixes ) for extension, suffixes in self.database.items(): self.database[extension] = ( ListHelper(suffixes).remove_duplicates().remove_empty().sort().subject ) DictHelper(self.database).to_json_file(self.destination) return self PyFunceble-4.2.29.dev/PyFunceble/cli/storage.py000066400000000000000000000271701467462152100212610ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the common storage location for all entry points. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import sys from typing import List, Optional import colorama from box import Box import PyFunceble.cli.storage_facility from PyFunceble.helpers.merge import Merge from PyFunceble.utils.platform import PlatformUtility if PlatformUtility.is_unix() and sys.stdin.encoding == "utf-8": STD_EPILOG: str = ( f"Crafted with {colorama.Fore.RED}โ™ฅ{colorama.Fore.RESET} by " f"{colorama.Style.BRIGHT}{colorama.Fore.CYAN}Nissar Chababy (@funilrys)" f"{colorama.Style.RESET_ALL} " f"with the help of\n{colorama.Style.BRIGHT}{colorama.Fore.GREEN}" f"https://pyfunceble.github.io/#/contributors{colorama.Style.RESET_ALL} " f"&& {colorama.Style.BRIGHT}{colorama.Fore.GREEN}" f"https://pyfunceble.github.io/#/special-thanks{colorama.Style.RESET_ALL}" ) ASCII_PYFUNCEBLE = """ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• """ ASCII_PYUNCEBLE_RESULT = """ โ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆ """ DONE: str = f"{colorama.Fore.GREEN}โœ”" ERROR: str = f"{colorama.Fore.RED}โœ˜" else: STD_EPILOG: str = ( f"Crafted with {colorama.Fore.RED}HEART{colorama.Fore.RESET} by " f"{colorama.Style.BRIGHT}{colorama.Fore.CYAN}Nissar Chababy (@funilrys)" f"{colorama.Style.RESET_ALL} " f"with the help of\n{colorama.Style.BRIGHT}{colorama.Fore.GREEN}" f"https://pyfunceble.github.io/#/contributors{colorama.Style.RESET_ALL} " f"&& {colorama.Style.BRIGHT}{colorama.Fore.GREEN}" f"https://pyfunceble.github.io/#/special-thanks{colorama.Style.RESET_ALL}" ) ASCII_PYFUNCEBLE = """ ######## ## ## ######## ## ## ## ## ###### ######## ######## ## ######## ## ## ## ## ## ## ## ### ## ## ## ## ## ## ## ## ## ## #### ## ## ## #### ## ## ## ## ## ## ## ######## ## ###### ## ## ## ## ## ## ###### ######## ## ###### ## ## ## ## ## ## #### ## ## ## ## ## ## ## ## ## ## ## ## ### ## ## ## ## ## ## ## ## ## ## ####### ## ## ###### ######## ######## ######## ######## """ ASCII_PYUNCEBLE_RESULT = """ . :==: :: .:. .. :-=-. .:. .:. .-==- :-=-: .-==: .-==--==-. :-=-: .-==: .-===-==-. :-=-: .-==:. .. .-==-====: :-==. .-==:. :==- .-==--=====-::-==-=:..-==:. ..--. :===============-=======:. :-=: :=-===: .-=-. .-======:. :==-. -=====. --: -====-. :==-. =======--=====-====:. :==-. -=====---:::::---==. :==-. .==--=. -===-==-. .-==--: .-=-===-. :-====-----=====-. .:-=======--:. .... """ DONE: str = f"{colorama.Fore.GREEN}DONE" ERROR: str = f"{colorama.Fore.RED}ERROR" VERSION_DUMP_LINK: str = ( "https://raw.githubusercontent.com/funilrys/PyFunceble/dev/version.yaml" ) HASHES_FILENAME: str = "hashes_tracker.json" ALEMBIC_DIRECTORY_NAME = "alembic" CI_TRIGGER_FILE = ".trigger" DISTRIBUTED_VERSION_FILENAME: str = "version.yaml" AUTOCONTINUE_OLD_FILE: str = "continue.json" INACTIVE_DB_OLD_FILE: str = "inactive_db.json" MINING_OLD_FILE = "mining.json" WHOIS_DB_OLD_FILE = "whois_db.json" AUTOCONTINUE_FILE: str = "continue.csv" INACTIVE_DB_FILE = "inactive.csv" RESULTS_RAW_FILE = "results.txt" WHOIS_DB_FILE = "whois.csv" EXECUTION_TIME_FILE = "execution_time.json" COUNTER_FILE = "counter.json" REGISTRAR_COUNTER_FILE = "registrar_counter.json" TEST_RUNNING_FILE = ".running" PRE_LOADER_FILE = "preload.json" STD_PARENT_DIRNAME: str = "__pyfunceble_origin__" STD_LOGGING_DIRNAME: str = "__pyfunceble_loggging__" UNIX_OUTPUTS: dict = { "domains": {"filename": "list"}, "ips": {"filename": "list"}, "hosts": {"filename": "hosts", "ip_filename": "ips"}, "analytic": { "filenames": { "potentially_down": "down_or_potentially_down", "potentially_up": "potentially_up", "up": "active_and_merged_in_results", "suspicious": "suspicious_and_merged_in_results", } }, "logs": { "filenames": { "inactive_not_retested": "inactive_not_retested", }, }, } WIN_OUTPUTS: dict = { "domains": {"filename": "list.txt"}, "ips": {"filename": "list.txt"}, "hosts": {"filename": "hosts.txt", "ip_filename": "ips.txt"}, "analytic": { "filenames": { "potentially_down": "down_or_potentially_down.txt", "potentially_up": "potentially_up.txt", "up": "active_and_merged_in_results.txt", "suspicious": "suspicious_and_merged_in_results.txt", } }, "logs": { "filenames": { "inactive_not_retested": "inactive_not_retested.txt", }, }, } UNIVERSAL_OUTPUTS: dict = { "domains": {"directory": "domains", "filename": "list"}, "ips": {"directory": "ips", "filename": "list"}, "hosts": {"directory": "hosts", "filename": "hosts", "ip_filename": "ips"}, "analytic": { "directories": { "parent": "Analytic", "potentially_down": "POTENTIALLY_INACTIVE", "potentially_up": "POTENTIALLY_ACTIVE", "up": "ACTIVE", "suspicious": "SUSPICIOUS", }, "filenames": { "potentially_down": "down_or_potentially_down", "potentially_up": "potentially_up", "up": "active_and_merged_in_results", "suspicious": "suspicious_and_merged_in_results", }, }, "logs": { "directories": { "parent": "logs", "percentage": "percentage", }, "filenames": { "auto_continue": "continue.json", "execution_time": "execution_time.json", "percentage": "percentage.txt", "registrar": "registrar.txt", "whois": "whois.json", "date_format": "date_format.json", "no_referrer": "no_referrer.json", "inactive_not_retested": "inactive_not_retested", }, }, "parent_directory": "output", "merged_directory": "merged_results", "splitted": {"directory": "splitted"}, } OUTPUTS: Optional[Box] = Box( ( Merge(UNIX_OUTPUTS).into(UNIVERSAL_OUTPUTS) if PlatformUtility.is_unix() else Merge(WIN_OUTPUTS).into(UNIVERSAL_OUTPUTS) ), frozen_box=True, ) OUTPUT_DIRECTORY: str = os.path.join( PyFunceble.cli.storage_facility.get_output_directory(), OUTPUTS.parent_directory, ) # This one will store some extra messages to print to the user. EXTRA_MESSAGES: Optional[List[str]] = [] PyFunceble-4.2.29.dev/PyFunceble/cli/storage_facility.py000066400000000000000000000061241467462152100231410ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some facilities for the storage module. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from PyFunceble.helpers.directory import DirectoryHelper from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper def get_output_directory() -> str: # pragma: no cover ## Not relevant """ Provides the location of the output directory. """ env_var_helper = EnvironmentVariableHelper() directory_helper = DirectoryHelper() if env_var_helper.set_name("PYFUNCEBLE_OUTPUT_LOCATION").exists(): output_directory = env_var_helper.get_value() else: output_directory = directory_helper.get_current(with_end_sep=True) if not output_directory.endswith(os.sep): output_directory += os.sep return output_directory PyFunceble-4.2.29.dev/PyFunceble/cli/system/000077500000000000000000000000001467462152100205605ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/system/__init__.py000066400000000000000000000047141467462152100226770ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our system handlers. Actually, every success CLI parsing will ends in on of the submodules. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/system/base.py000066400000000000000000000114121467462152100220430ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our subclasses related to the system management. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 argparse import functools from typing import Callable, Optional class SystemBase: """ Provides the base of all system classes. The idea is that every system classes will have access to the argument given by end-user. Each of them will have a start method which will run a set of predefined action. But the start method -in comparison to previous versions - starts on purpose. :param args: The arguments from :py:class:`argparse.ArgumentParser`. """ _args: Optional[argparse.Namespace] = None def __init__(self, args: Optional[argparse.Namespace] = None) -> None: if args is not None: self.args = args def ensure_args_is_given( func: Callable[["SystemBase"], "SystemBase"] ): # pylint: disable=no-self-argument """ Ensures that the :code:`self.args` attribute is given before launching the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.args, argparse.Namespace): raise TypeError(" is not given.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @property def args(self) -> Optional[argparse.Namespace]: """ Provides the current state of the :code:`_args` attribute. """ return self._args @args.setter def args(self, value: argparse.Namespace) -> None: """ Sets the given args. :param value: The arguments to work with. :raise TypeError: When the given :code:`value` is not a :py:class:`argparse.Namespace` """ if not isinstance(value, argparse.Namespace): raise TypeError( f" should be {argparse.Namespace}, {type(value)} given." ) self._args = value def set_args(self, value: argparse.Namespace) -> "SystemBase": """ Sets the given args. :param value: The arguments to work with. """ self.args = value return self @ensure_args_is_given def start(self) -> "SystemBase": """ Provides a launcher for a brunch of predefined actions defined by the current object. """ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/cli/system/integrator.py000066400000000000000000000251001467462152100233060ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our very own argument parser. Take this as a splitter which runs some actions against other resource before returning the arguments. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import colorama import PyFunceble.cli.facility import PyFunceble.cli.factory import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.storage from PyFunceble.cli.system.base import SystemBase from PyFunceble.helpers.dict import DictHelper class SystemIntegrator(SystemBase): """ Provides our system integrator. The idea is that we given an argparse Namespace, we should be able to parse it into our system. To simplify the trick and headache in the CLI management, I explicitely mapped the :code:`dest` argument to what we are supposed to have in the flatten version of the configuration. That way, we only need to compare against the flatten version instead of looping over all possible levels of the configuration tree. """ @SystemBase.ensure_args_is_given def init_logger(self) -> "SystemIntegrator": """ Initiate the loggers. In fact, before this moment, in a normal case the logger was not properly initiated. To avoid multiple management place, I took it to the essential. .. warning:: If you plan to play with the logger on your own, be sure to follow the same procedure. """ PyFunceble.facility.Logger.set_output_directory( os.path.join( PyFunceble.cli.storage.OUTPUT_DIRECTORY, PyFunceble.cli.storage.STD_LOGGING_DIRNAME, ) ) if hasattr(self.args, "debug__active") and self.args.debug__active: PyFunceble.facility.Logger.set_activated(True) if hasattr(self.args, "debug__level") and self.args.debug__level: PyFunceble.facility.Logger.set_min_level(self.args.debug__level) PyFunceble.facility.Logger.set_activated(True) if not PyFunceble.facility.Logger.activated: PyFunceble.facility.Logger.guess_all_settings() # We do this because the starting point is here under the CLI :-) PyFunceble.facility.Logger.init_loggers() @SystemBase.ensure_args_is_given def inject_into_config(self) -> "SystemIntegrator": """ Injects the configuration variables into the configuration after comparing each value with the current one. """ PyFunceble.facility.Logger.info( "Started to inject arguments info configuration." ) dict_helper = DictHelper(PyFunceble.storage.CONFIGURATION) flatten_config = dict_helper.flatten() to_update = {} reserved_lookup_mode = [] for key, value in vars(self.args).items(): if value in (False, None): continue if "__" in key: key = key.replace("__", ".") if key in flatten_config: if isinstance(flatten_config[key], bool) and isinstance(value, bool): to_update[key] = not flatten_config[key] else: to_update[key] = value elif key.startswith("self_contained") and "lookup" in key: reserved_lookup_mode.append(key[key.rfind(".") + 1 :]) if reserved_lookup_mode: for lookup_key in PyFunceble.storage.CONFIGURATION.lookup.keys(): if lookup_key in {"timeout"}: continue if lookup_key not in reserved_lookup_mode: to_update[f"lookup.{lookup_key}"] = False else: to_update[f"lookup.{lookup_key}"] = True dict_helper.set_subject(to_update) unflatten_to_update = dict_helper.unflatten() # We assume that the configuration was already loaded. PyFunceble.facility.ConfigLoader.custom_config = unflatten_to_update PyFunceble.facility.Logger.debug( "Injected into config: %r", unflatten_to_update ) PyFunceble.facility.Logger.info( "Finished to inject arguments info configuration." ) return self @SystemBase.ensure_args_is_given def check_config(self) -> "SystemIntegrator": """ Checks or do some sanity check of the configuration. This method will basically check that the common mistakes while mixing configuration and CLI arguments are not found. .. warning:: The messages are not directly printed, but rather stored in the PyFunceble.cli.storage.EXTRA_MESSAGES list. """ if ( not PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.hosts and not PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.plain ): PyFunceble.cli.storage.EXTRA_MESSAGES.append( f"{colorama.Style.BRIGHT}{colorama.Fore.MAGENTA}Your setup won't " "generate any output! " "Reason: file_generation.hosts and file_generation.plain are " "both disabled." ) if "url_base" in PyFunceble.storage.CONFIGURATION.platform: PyFunceble.cli.storage.EXTRA_MESSAGES.append( f"{colorama.Style.BRIGHT}{colorama.Fore.MAGENTA}Your are still " "defining the 'platform.url_base' configuration key which has " "been deprecated and deleted. Please remove it from your " "configuration file." ) if ( "collection" in PyFunceble.storage.CONFIGURATION or "collection" in PyFunceble.storage.CONFIGURATION.lookup ): PyFunceble.cli.storage.EXTRA_MESSAGES.append( f"{colorama.Style.BRIGHT}{colorama.Fore.MAGENTA}The 'collection' " "configuration key is not supported anymore. Please switch to " "'platform'." ) if "PYFUNCEBLE_COLLECTION_API_TOKEN" in os.environ: PyFunceble.cli.storage.EXTRA_MESSAGES.append( f"{colorama.Style.BRIGHT}{colorama.Fore.MAGENTA}The " "'PYFUNCEBLE_COLLECTION_API_TOKEN' environment variable is not " "supported anymore. Please switch to 'PYFUNCEBLE_PLATFORM_API_TOKEN'." ) if "PYFUNCEBLE_COLLECTION_API_URL" in os.environ: PyFunceble.cli.storage.EXTRA_MESSAGES.append( f"{colorama.Style.BRIGHT}{colorama.Fore.MAGENTA}The " "'PYFUNCEBLE_COLLECTION_API_URL' environment variable is not " "supported anymore. Please switch to 'PYFUNCEBLE_PLATFORM_API_URL'." ) @SystemBase.ensure_args_is_given def check_deprecated(self) -> "SystemIntegrator": """ Checks or do some deprecation checks. This method will basically check if deprecated keys are still given and provide guidance for end-users. !!! warning The messages are not directly printed, but rather stored in the PyFunceble.cli.storage.EXTRA_MESSAGES list. """ if "adblock_aggressive" in PyFunceble.storage.CONFIGURATION.cli_decoding: PyFunceble.cli.storage.EXTRA_MESSAGES.append( f"{colorama.Style.BRIGHT}{colorama.Fore.MAGENTA}The " "'cli_decoding.adblock_aggressive' configuration key has been " "replaced by the 'cli_decoding.aggressive' key but you are " "still setting it." ) @SystemBase.ensure_args_is_given def start(self) -> "SystemIntegrator": """ Starts a group of actions provided by this interface. """ if hasattr(self.args, "output_location") and self.args.output_location: PyFunceble.cli.storage.OUTPUT_DIRECTORY = os.path.realpath( os.path.join( self.args.output_location, PyFunceble.cli.storage.OUTPUTS.parent_directory, ) ) self.init_logger() PyFunceble.facility.Logger.debug("Given arguments:\n%r", self.args) self.inject_into_config() self.check_config() self.check_deprecated() PyFunceble.cli.facility.CredentialLoader.start() PyFunceble.cli.factory.DBSession.init_db_sessions() return self PyFunceble-4.2.29.dev/PyFunceble/cli/system/launcher.py000066400000000000000000001307251467462152100227430ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the system launcher. From here, it's all about real testing. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: disable=too-many-lines import argparse import copy import datetime import multiprocessing import os import secrets import sys import time import traceback from typing import List, Optional, Union import colorama import domain2idna from sqlalchemy.orm import Session import PyFunceble.checker.utils.whois import PyFunceble.cli.storage import PyFunceble.cli.utils.ascii_logo import PyFunceble.cli.utils.sort import PyFunceble.cli.utils.stdout import PyFunceble.facility import PyFunceble.storage from PyFunceble.checker.syntax.url import URLSyntaxChecker from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase from PyFunceble.cli.continuous_integration.exceptions import StopExecution from PyFunceble.cli.continuous_integration.utils import ci_object from PyFunceble.cli.execution_time import ExecutionTime from PyFunceble.cli.file_preloader import FilePreloader from PyFunceble.cli.filesystem.cleanup import FilesystemCleanup from PyFunceble.cli.filesystem.counter import FilesystemCounter from PyFunceble.cli.filesystem.dir_base import FilesystemDirBase from PyFunceble.cli.filesystem.dir_structure.restore import ( DirectoryStructureRestoration, ) from PyFunceble.cli.filesystem.printer.file import FilePrinter from PyFunceble.cli.filesystem.printer.stdout import StdoutPrinter from PyFunceble.cli.filesystem.registrar_counter import RegistrarCounter from PyFunceble.cli.processes.chancy_producer import ChancyProducerProcessesManager from PyFunceble.cli.processes.chancy_tester import ChancyTesterProcessesManager from PyFunceble.cli.processes.dir_files_sorter import DirFileSorterProcessesManager from PyFunceble.cli.processes.migrator import MigratorProcessesManager from PyFunceble.cli.processes.miner import MinerProcessesManager from PyFunceble.cli.processes.producer import ProducerProcessesManager from PyFunceble.cli.processes.tester import TesterProcessesManager from PyFunceble.cli.system.base import SystemBase from PyFunceble.cli.utils.testing import ( get_continue_databaset_object, get_destination_from_origin, get_inactive_dataset_object, get_subjects_from_line, get_testing_mode, ) from PyFunceble.cli.utils.version import print_central_messages from PyFunceble.converter.adblock_input_line2subject import AdblockInputLine2Subject from PyFunceble.converter.cidr2subject import CIDR2Subject from PyFunceble.converter.input_line2subject import InputLine2Subject from PyFunceble.converter.rpz_input_line2subject import RPZInputLine2Subject from PyFunceble.converter.rpz_policy2subject import RPZPolicy2Subject from PyFunceble.converter.subject2complements import Subject2Complements from PyFunceble.converter.url2netloc import Url2Netloc from PyFunceble.converter.wildcard2subject import Wildcard2Subject from PyFunceble.dataset.autocontinue.base import ContinueDatasetBase from PyFunceble.dataset.autocontinue.csv import CSVContinueDataset from PyFunceble.dataset.inactive.base import InactiveDatasetBase from PyFunceble.helpers.directory import DirectoryHelper from PyFunceble.helpers.download import DownloadHelper from PyFunceble.helpers.file import FileHelper from PyFunceble.query.platform import PlatformQueryTool class SystemLauncher(SystemBase): """ Provides the system tests launcher. """ testing_protocol: List[dict] = [] """ Saves the protocol which we are going to generate. The protocol will saves a set of information about what to test, what kind of output to produce and most importantly where. """ subject2complements: Subject2Complements = Subject2Complements() inputline2subject: InputLine2Subject = InputLine2Subject() adblock_inputline2subject: AdblockInputLine2Subject = AdblockInputLine2Subject() wildcard2subject: Wildcard2Subject = Wildcard2Subject() rpz_policy2subject: RPZPolicy2Subject = RPZPolicy2Subject() rpz_inputline2subject: RPZInputLine2Subject = RPZInputLine2Subject() url2netloc: Url2Netloc = Url2Netloc() cidr2subject: CIDR2Subject = CIDR2Subject() stdout_printer: StdoutPrinter = StdoutPrinter() file_printer: FilePrinter = FilePrinter() counter: FilesystemCounter = FilesystemCounter() registrar_counter: RegistrarCounter = RegistrarCounter() execution_time_holder: Optional[ExecutionTime] = None file_preloader: Optional[FilePreloader] = None manager: Optional[multiprocessing.Manager] tester_process_manager: Optional[ Union[TesterProcessesManager, ChancyTesterProcessesManager] ] = None producer_process_manager: Optional[ Union[ProducerProcessesManager, ChancyProducerProcessesManager] ] = None miner_process_manager: Optional[MinerProcessesManager] = None dir_files_sorter_process_manager: Optional[DirFileSorterProcessesManager] = None migrator_process_manager: Optional[MigratorProcessesManager] = None continue_dataset: Optional[ContinueDatasetBase] = None inactive_dataset: Optional[InactiveDatasetBase] = None continuous_integration: Optional[ContinuousIntegrationBase] = None db_session: Optional[Session] = None checker_type: Optional[str] = None sessions_id: dict = {} def __init__(self, args: Optional[argparse.Namespace] = None) -> None: try: self.db_session = ( PyFunceble.cli.factory.DBSession.get_db_session().get_new_session()() ) except TypeError: self.db_session = None self.execution_time_holder = ExecutionTime().set_start_time() self.checker_type = get_testing_mode() self.continue_dataset = get_continue_databaset_object( db_session=self.db_session ) self.inactive_dataset = get_inactive_dataset_object(db_session=self.db_session) self.continuous_integration = ci_object() if self.continuous_integration.authorized: self.continuous_integration.init() self.stdout_printer.guess_allow_coloration() self.manager = multiprocessing.Manager() if not PyFunceble.storage.CONFIGURATION.cli_testing.chancy_tester: self.tester_process_manager = TesterProcessesManager( self.manager, max_worker=PyFunceble.storage.CONFIGURATION.cli_testing.max_workers, continuous_integration=self.continuous_integration, daemon=True, output_workers_count=1, output_queue_num=2, ) self.producer_process_manager = ProducerProcessesManager( self.manager, max_worker=1, continuous_integration=self.continuous_integration, input_queue=self.tester_process_manager.output_queue[0], daemon=True, generate_output_queue=False, ) else: self.tester_process_manager = ChancyTesterProcessesManager( self.manager, max_worker=PyFunceble.storage.CONFIGURATION.cli_testing.max_workers, continuous_integration=self.continuous_integration, daemon=True, output_workers_count=1, output_queue_num=2, ) self.producer_process_manager = ChancyProducerProcessesManager( self.manager, max_worker=PyFunceble.storage.CONFIGURATION.cli_testing.max_workers, continuous_integration=self.continuous_integration, input_queue=self.tester_process_manager.output_queue[0], daemon=True, generate_output_queue=False, ) self.dir_files_sorter_process_manager = DirFileSorterProcessesManager( self.manager, max_worker=PyFunceble.storage.CONFIGURATION.cli_testing.max_workers, continuous_integration=self.continuous_integration, daemon=True, generate_output_queue=False, output_workers_count=0, ) self.migrator_process_manager = MigratorProcessesManager( self.manager, continuous_integration=self.continuous_integration, daemon=True, generate_input_queue=False, generate_output_queue=False, output_workers_count=0, ) if PyFunceble.storage.CONFIGURATION.cli_testing.mining: self.miner_process_manager = MinerProcessesManager( self.manager, max_worker=1, continuous_integration=self.continuous_integration, input_queue=self.tester_process_manager.output_queue[1], output_queue=self.tester_process_manager.input_queue, generate_input_queue=False, generate_output_queue=False, daemon=True, output_workers_count=self.tester_process_manager.max_worker, ) if self.continuous_integration.authorized: self.continuous_integration.set_start_time() self.file_preloader = FilePreloader( continuous_integration=self.continuous_integration, checker_type=self.checker_type, adblock_inputline2subject=self.adblock_inputline2subject, wildcard2subject=self.wildcard2subject, rpz_policy2subject=self.rpz_policy2subject, rpz_inputline2subject=self.rpz_inputline2subject, inputline2subject=self.inputline2subject, subject2complements=self.subject2complements, url2netloc=self.url2netloc, continue_dataset=self.continue_dataset, inactive_dataset=self.inactive_dataset, ) super().__init__(args) def __del__(self) -> None: if self.db_session is not None: self.db_session.close() @staticmethod def print_home_ascii() -> None: """ Prints our ASCII home logo. """ if not PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet: if PyFunceble.cli.utils.stdout.get_template_to_use() != "simple": print(PyFunceble.cli.utils.ascii_logo.get_home_representation()) @SystemBase.ensure_args_is_given def fill_protocol(self) -> "SystemLauncher": """ Fills the protocol with the information about what we are supposed to test. """ filesytem_dirbase = FilesystemDirBase() if self.args.domains: for domain in self.args.domains: to_append = { "type": "single", "subject_type": "domain", "destination": None, "subject": domain, "idna_subject": domain2idna.domain2idna(domain), "source": None, "output_dir": None, "checker_type": self.checker_type, "session_id": None, } self.testing_protocol.append(to_append) PyFunceble.facility.Logger.debug( "Added to the protocol:\n%r", to_append ) if self.args.urls: for url in self.args.urls: to_append = { "type": "single", "subject_type": "url", "destination": None, "subject": url, "idna_subject": domain2idna.domain2idna(url), "source": None, "output_dir": None, "checker_type": self.checker_type, "session_id": None, } self.testing_protocol.append(to_append) PyFunceble.facility.Logger.debug( "Added to the protocol:\n%r", to_append ) if self.args.files: for file in self.args.files: # pylint: disable=line-too-long if ( not PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.merge_output_dirs ): destination = get_destination_from_origin(file) else: destination = get_destination_from_origin( PyFunceble.cli.storage.OUTPUTS.merged_directory ) to_append = { "type": "file", "subject_type": "domain", # pylint: disable=line-too-long "destination": destination, "source": file, "subject": file, "checker_type": self.checker_type, "session_id": None, } to_append["output_dir"] = filesytem_dirbase.set_parent_dirname( to_append["destination"] ).get_output_basedir() self.testing_protocol.append(to_append) PyFunceble.facility.Logger.debug( "Added to the protocol:\n%r", to_append ) if self.args.url_files: for file in self.args.url_files: # pylint: disable=line-too-long if ( not PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.merge_output_dirs ): destination = get_destination_from_origin(file) else: destination = get_destination_from_origin( PyFunceble.cli.storage.OUTPUTS.merged_directory ) to_append = { "type": "file", "subject_type": "url", # pylint: disable=line-too-long "destination": destination, "source": file, "subject": file, "checker_type": self.checker_type, "session_id": None, } to_append["output_dir"] = filesytem_dirbase.set_parent_dirname( to_append["destination"] ).get_output_basedir() self.testing_protocol.append(to_append) PyFunceble.facility.Logger.debug( "Added to the protocol:\n%r", to_append ) # pylint: disable=line-too-long if ( not self.testing_protocol and PyFunceble.storage.CONFIGURATION.cli_testing.testing_mode.platform_contribution ): self.testing_protocol.append( { "type": "platform-contribution", "subject_type": "any", "destination": None, "checker_type": None, "output_dir": None, "session_id": None, } ) def ci_stop_in_the_middle_if_time_exceeded(self) -> "SystemLauncher": """ Stops our processes as soon as the time is exceeded. """ if self.continuous_integration.is_time_exceeded(): self.run_ci_saving_instructions() return self # pylint: disable=too-many-statements def fill_to_test_queue_from_protocol(self) -> "SystemLauncher": """ Read the protocol and fill the testing queue. """ def download_file(file: str, destination: str) -> bool: """ Downloads the given file (if it's an URL). :param file: The file to download. :param destination. The file to write. :return: A boolean which represent the action state. """ if URLSyntaxChecker(file).is_valid(): DownloadHelper(file).download_text(destination=destination) return True return False def create_trigger_file_if_necessary(parent_dirname: str) -> None: """ Create the trigger file if necessary. The purpose of the trigger file is to have a file that is always updated until a test is completed done. """ if self.continuous_integration.authorized: cleanup_tool = FilesystemCleanup(parent_dirname) trigger_file_helper = FileHelper( os.path.join( cleanup_tool.get_output_basedir(), PyFunceble.cli.storage.CI_TRIGGER_FILE, ) ) # Ensures that we always have something to commit. trigger_file_helper.write( f"{self.sessions_id[parent_dirname]} " f"{secrets.token_hex(8)}", overwrite=True, ) def cleanup_if_necessary(parent_dirname: str) -> None: """ Process the cleanup if it's necessary. """ cleanup_tool = FilesystemCleanup(parent_dirname) running_file_helper = FileHelper( os.path.join( cleanup_tool.get_output_basedir(), PyFunceble.cli.storage.TEST_RUNNING_FILE, ) ) if not running_file_helper.exists(): self.sessions_id[parent_dirname] = secrets.token_hex(12) cleanup_tool.clean_output_files() running_file_helper.write( f"{self.sessions_id[parent_dirname]} " f"{datetime.datetime.now(datetime.timezone.utc).isoformat()}", overwrite=True, ) else: possible_session_id = running_file_helper.read().split()[0] try: _ = datetime.datetime.fromisoformat(possible_session_id).astimezone( datetime.timezone.utc ) self.sessions_id[parent_dirname] = None except (ValueError, TypeError): self.sessions_id[parent_dirname] = possible_session_id def match_output_directory_if_necessary(parent_dirname: str) -> None: """ Restore missing directories from the current directory. """ if not PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.no_file: DirectoryStructureRestoration(parent_dirname).restore_from_backup() def handle_file(protocol: dict) -> None: """ Given a protocol related to a given file, we handle every possible decoding case before submitting a new subject to the queue. """ cleanup_if_necessary(protocol["destination"]) create_trigger_file_if_necessary(protocol["destination"]) match_output_directory_if_necessary(protocol["destination"]) if download_file(protocol["subject"], protocol["destination"]): protocol["subject"] = os.path.relpath(protocol["destination"]) else: protocol["subject"] = os.path.relpath(protocol["subject"]) protocol["source"] = os.path.relpath(protocol["source"]) protocol["session_id"] = self.sessions_id[protocol["destination"]] if isinstance(self.continue_dataset, CSVContinueDataset): self.continue_dataset.set_base_directory(protocol["output_dir"]) if self.file_preloader.authorized: if not PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet: print( f"{colorama.Fore.MAGENTA}{colorama.Style.BRIGHT}" f"Started preloading of {protocol['source']}..." ) self.file_preloader.set_protocol(protocol).start( # pylint: disable=line-too-long print_dots=( PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet or bool( PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.dots ) ) ) if not PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet: print( f"\n{colorama.Fore.GREEN}{colorama.Style.BRIGHT}" f"Finished preloading of {protocol['source']}." ) self.__start_core_processes() for subject in self.continue_dataset.get_to_test( protocol["session_id"] ): self.ci_stop_in_the_middle_if_time_exceeded() to_send = copy.deepcopy(protocol) to_send["subject"], to_send["idna_subject"] = subject, subject to_send["from_preload"] = True self.tester_process_manager.add_to_input_queue( to_send, worker_name="main" ) else: with FileHelper(protocol["subject"]).open( "r", encoding="utf-8" ) as file_stream: for line in file_stream: self.ci_stop_in_the_middle_if_time_exceeded() line = line.strip() if "SOA" in line: self.rpz_policy2subject.set_soa(line.split()[0]) for subject in get_subjects_from_line( line, self.checker_type, subject_type=protocol["subject_type"], adblock_inputline2subject=self.adblock_inputline2subject, wildcard2subject=self.wildcard2subject, rpz_policy2subject=self.rpz_policy2subject, rpz_inputline2subject=self.rpz_inputline2subject, inputline2subject=self.inputline2subject, subject2complements=self.subject2complements, url2netloc=self.url2netloc, cidr2subject=self.cidr2subject, ): to_send = copy.deepcopy(protocol) to_send["subject"] = subject to_send["idna_subject"] = domain2idna.domain2idna(subject) self.tester_process_manager.add_to_input_queue( to_send, worker_name="main" ) # Now, let's handle the inactive one :-) if bool(PyFunceble.storage.CONFIGURATION.cli_testing.inactive_db): for dataset in self.inactive_dataset.get_to_retest( protocol["destination"], protocol["checker_type"], # pylint: disable=line-too-long min_days=PyFunceble.storage.CONFIGURATION.cli_testing.days_between.db_retest, ): self.ci_stop_in_the_middle_if_time_exceeded() to_send = copy.deepcopy(protocol) to_send["from_inactive"] = True # Note: Our test infrastructure need a subject # but there is no subject in the table. to_send["subject"] = dataset["idna_subject"] to_send["idna_subject"] = dataset["idna_subject"] self.tester_process_manager.add_to_input_queue( to_send, worker_name="main" ) self.dir_files_sorter_process_manager.input_datasets.append( {"directory": protocol["output_dir"]} ) def handle_platform_contribution() -> None: """ Assuming that we are testing a platform contribution, proceed with the testing. """ query_tool = PlatformQueryTool() max_breakoff = 120.0 initial_breakoff = ( max_breakoff / PyFunceble.storage.CONFIGURATION.cli_testing.max_workers ) breakoff = initial_breakoff while True: for next_contract in next( query_tool.pull_contract( PyFunceble.storage.CONFIGURATION.cli_testing.max_workers ) ): if "subject" not in next_contract or not next_contract["subject"]: continue protocol_data = copy.deepcopy(protocol) protocol_data["checker_type"] = next_contract[ "checker_type" ].upper() protocol_data["subject_type"] = next_contract["subject_type"] protocol_data["subject"] = protocol_data["idna_subject"] = ( next_contract["subject"]["subject"] ) protocol_data["contract"] = copy.deepcopy(next_contract) self.tester_process_manager.add_to_input_queue( protocol_data, worker_name="main" ) self.ci_stop_in_the_middle_if_time_exceeded() if PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.dots: PyFunceble.cli.utils.stdout.print_single_line("S") time.sleep(breakoff) if breakoff < max_breakoff: breakoff += 0.02 else: breakoff = initial_breakoff for protocol in self.testing_protocol: self.ci_stop_in_the_middle_if_time_exceeded() if protocol["type"] == "single": for subject in get_subjects_from_line( protocol["idna_subject"], self.checker_type, subject_type=protocol["subject_type"], adblock_inputline2subject=self.adblock_inputline2subject, wildcard2subject=self.wildcard2subject, rpz_policy2subject=self.rpz_policy2subject, rpz_inputline2subject=self.rpz_inputline2subject, inputline2subject=self.inputline2subject, subject2complements=self.subject2complements, url2netloc=self.url2netloc, cidr2subject=self.cidr2subject, ): to_send = copy.deepcopy(protocol) to_send["subject"], to_send["idna_subject"] = ( subject, domain2idna.domain2idna(subject), ) self.tester_process_manager.add_to_input_queue( to_send, worker_name="main" ) elif protocol["type"] == "file": handle_file(protocol) elif protocol["type"] == "platform-contribution": handle_platform_contribution() return self def generate_waiting_files(self) -> "SystemLauncher": """ Generates all the files that needs to be generated when all status are proceeses. """ def generate_percentage_file(parent_dirname: Union[str, None]) -> None: """ Generates the percentage file. """ if not PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.no_file: self.counter.set_differ_to_inline(True).set_parent_dirname( parent_dirname ) destination = os.path.join( self.counter.get_output_basedir(), PyFunceble.cli.storage.OUTPUTS.logs.directories.parent, PyFunceble.cli.storage.OUTPUTS.logs.directories.percentage, PyFunceble.cli.storage.OUTPUTS.logs.filenames.percentage, ) stdout_header_printed = False self.stdout_printer.template_to_use = "percentage" self.file_printer.template_to_use = "percentage" self.file_printer.destination = destination for data in self.counter.get_dataset_for_printer(): self.file_printer.set_dataset(data).print_interpolated_line() # pylint: disable=line-too-long if ( PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.percentage and not PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet ): self.stdout_printer.dataset = data if not stdout_header_printed: self.stdout_printer.print_header() stdout_header_printed = True self.stdout_printer.print_interpolated_line() def generate_registrar_file(parent_dirname: Union[str, None]) -> None: """ Generates the registrar file. """ if not PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.no_file: self.registrar_counter.set_differ_to_inline(True).set_parent_dirname( parent_dirname ) destination = os.path.join( self.counter.get_output_basedir(), PyFunceble.cli.storage.OUTPUTS.logs.directories.parent, PyFunceble.cli.storage.OUTPUTS.logs.directories.percentage, PyFunceble.cli.storage.OUTPUTS.logs.filenames.registrar, ) stdout_header_printed = False self.stdout_printer.template_to_use = "registrar" self.file_printer.template_to_use = "registrar" self.file_printer.destination = destination registrar_limit = 0 for data in self.registrar_counter.get_dataset_for_printer(): self.file_printer.set_dataset(data).print_interpolated_line() # pylint: disable=line-too-long if ( PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.registrar and not PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet and registrar_limit < PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.max_registrar ): self.stdout_printer.dataset = data if not stdout_header_printed: self.stdout_printer.print_header() stdout_header_printed = True self.stdout_printer.print_interpolated_line() registrar_limit += 1 def print_result_ascii(parent_dirname: Union[str, None]) -> None: """ Generates the result repr. """ # pylint: disable=line-too-long if ( not PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.no_file and not PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet and PyFunceble.cli.utils.stdout.get_template_to_use() != "simple" ): self.counter.set_differ_to_inline(True).set_parent_dirname( parent_dirname ) print( PyFunceble.cli.utils.ascii_logo.get_result_representation( self.counter.get_sorted_dataset()[0][0] ) ) no_destination_found = [] amount_protocol_without_dest = len( [x["destination"] for x in self.testing_protocol if not x["destination"]] ) for protocol in self.testing_protocol: if not protocol["destination"]: if any(no_destination_found): continue if amount_protocol_without_dest >= 2: # Show percentage, only if the amount of subjects is > 2. generate_percentage_file(protocol["destination"]) else: generate_percentage_file(protocol["destination"]) if protocol["checker_type"] in self.registrar_counter.SUPPORTED_TEST_MODES: generate_registrar_file(protocol["destination"]) print_result_ascii(protocol["destination"]) no_destination_found.append(not protocol["destination"]) if protocol["checker_type"] in self.registrar_counter.SUPPORTED_TEST_MODES: generate_registrar_file(protocol["destination"]) # pylint: disable=line-too-long if ( PyFunceble.storage.CONFIGURATION.cli_testing.file_generation.merge_output_dirs ): break return self def remove_unwanted_files(self) -> "SystemLauncher": """ Deletes some unwanted files that needs to be deleted when all status are processed. """ def remove_running_file(protocol: str) -> None: """ Removes the running file. :param parent_dirname: The name of the directory to work from (under the output directory). """ if protocol["output_dir"]: file_helper.set_path( os.path.join( protocol["output_dir"], PyFunceble.cli.storage.TEST_RUNNING_FILE, ) ).delete() PyFunceble.facility.Logger.debug("Deleted: %r.", file_helper.path) def remove_trigger_file(protocol: str) -> None: """ Removes the trigger file. :param protocol: The protocol to work with. """ if protocol["output_dir"]: file_helper.set_path( os.path.join( protocol["output_dir"], PyFunceble.cli.storage.CI_TRIGGER_FILE, ) ).delete() PyFunceble.facility.Logger.debug("Deleted: %r.", file_helper.path) def remove_continue_dataset(protocol: dict) -> None: """ Removes the continue file. :param protocol: The protocol to work with. """ if ( isinstance(self.continue_dataset, CSVContinueDataset) and protocol["output_dir"] ): # CSV file :-) self.continue_dataset.set_base_directory(protocol["output_dir"]) file_helper.set_path(self.continue_dataset.source_file).delete() PyFunceble.facility.Logger.debug("Deleted: %r.", file_helper.path) elif protocol["destination"]: # MariaDB / MySQL # ## We specially have different signature. self.continue_dataset.cleanup( # pylint: disable=unexpected-keyword-arg session_id=self.sessions_id[protocol["destination"]] ) def remove_preload_dataset(protocol: dict) -> None: """ Removes the preloader dataset file. :param protocol: The protocol to work with. """ if self.file_preloader.authorized and protocol["output_dir"]: file_helper.set_path( os.path.join( protocol["output_dir"], PyFunceble.cli.storage.PRE_LOADER_FILE, ) ).delete() PyFunceble.facility.Logger.debug("Deleted: %r.", file_helper.path) def remove_inline_dest(protocol: dict) -> None: """ Remove the inline destination - when necessary. :param protocl: The protocol to work with. """ if not protocol["destination"]: DirectoryHelper( self.counter.set_differ_to_inline(True) .set_parent_dirname(protocol["destination"]) .get_output_basedir() ).delete() file_helper = FileHelper() for protocol in self.testing_protocol: if "destination" in protocol or "output_dir" in protocol: remove_running_file(protocol) remove_trigger_file(protocol) remove_continue_dataset(protocol) remove_preload_dataset(protocol) remove_inline_dest(protocol) return self def run_standard_end_instructions(self) -> "SystemLauncher": """ Runns our standard "end" instructions. The instructions executed by this method are the one we execute normally. The purpose of this method is to make our standard end instructions available to everybody instead of hiding them into the :code:`start` method. :-) .. warning:: This is the standard "end" instructions. Do not call this method if you are trying to run an action after the CI execution time exceeded. """ self.generate_waiting_files() self.remove_unwanted_files() return self def run_ci_saving_instructions(self) -> "SystemLauncher": """ Runns our CI "saving" instructions. The instructions executed by this method are the one we execute before ending a testing session under one of the supported CI engines. The purpose of this method is to make our instructions available to everybody instead of hiding them into the :code:`start` method. :-) .. warning:: This is the standard "end" instructions. Do not call this method if you are trying to run an action after the CI execution time exceeded. """ if self.continuous_integration.authorized: self.continuous_integration.apply_commit() return self def run_ci_end_saving_instructions(self) -> "SystemLauncher": """ Runns our CI END "saving" instructions. The instructions executed by this method are the one we execute before ending a testing session under one of the supported CI engines. The purpose of this method is to make our instructions available to everybody instead of hiding them into the :code:`start` method. :-) .. warning:: This is the standard "end" instructions. Do not call this method if you are trying to run an action after the CI execution time exceeded. """ self.run_standard_end_instructions() if self.continuous_integration.authorized: self.continuous_integration.apply_end_commit() return self def stop_and_wait_for_all_manager(self) -> "SystemLauncher": """ Sends our stop signal and wait until all managers are finished. """ # The idea out here is to propate the stop signal. # Meaning that the tester will share it's stop signal to all # subsequencial queues after all submitted tasks are done. self.tester_process_manager.send_stop_signal(worker_name="main") if self.miner_process_manager: self.miner_process_manager.wait() self.tester_process_manager.wait() self.producer_process_manager.wait() try: # From here, we are sure that every test and files are produced. # We now format the generated file(s). self.dir_files_sorter_process_manager.start() self.dir_files_sorter_process_manager.send_stop_signal() self.dir_files_sorter_process_manager.wait() except AssertionError: # Example: Already started previously. pass if self.execution_time_holder.authorized: self.execution_time_holder.set_end_time() self.stdout_printer.set_template_to_use("execution_time").set_dataset( self.execution_time_holder.get_info() ).print_interpolated_line() return self def __start_core_processes(self): """ Starts our core processes. """ if not self.producer_process_manager.is_running(): self.producer_process_manager.start() self.tester_process_manager.start() if self.miner_process_manager: self.miner_process_manager.start() @SystemBase.ensure_args_is_given def start(self) -> "SystemLauncher": try: self.print_home_ascii() print_central_messages(check_force_update=True) # This tries to bypass the execution when the continuous integration # is given and the last commit message (the one we are testing for) # match any of our known marker. Please report to the method itself # for more information about the markers. self.continuous_integration.bypass() if self.args.files or self.args.url_files: self.migrator_process_manager.start() self.migrator_process_manager.wait() del self.migrator_process_manager if not self.file_preloader.authorized or ( not self.args.files and not self.args.url_files ): self.__start_core_processes() self.fill_protocol() self.fill_to_test_queue_from_protocol() self.stop_and_wait_for_all_manager() if self.continuous_integration.is_time_exceeded(): # Does not includes the run_standard_end_instructions call. # Reason: We have to continue. self.run_ci_saving_instructions() elif self.continuous_integration.authorized: # Includes the run_standard_end_instructions call. self.run_ci_end_saving_instructions() else: self.run_standard_end_instructions() except (KeyboardInterrupt, StopExecution): pass except Exception as exception: # pylint: disable=broad-except PyFunceble.facility.Logger.critical( "Fatal error.", exc_info=True, ) print( f"{colorama.Fore.RED}{colorama.Style.BRIGHT}Fatal Error: " f"{exception}" ) print(traceback.format_exc()) sys.exit(1) PyFunceble.cli.utils.stdout.print_thanks() return self PyFunceble-4.2.29.dev/PyFunceble/cli/utils/000077500000000000000000000000001467462152100203745ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/cli/utils/__init__.py000066400000000000000000000046231467462152100225120ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some utilities related to the CLI. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/cli/utils/ascii_logo.py000066400000000000000000000101761467462152100230630ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some utilities related to the ascii logo. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 colorama import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.storage def colorify(color: str, *, text=None) -> str: """ Colorify the logo with the given color. :param color: The name of the color to apply. .. warning:: The given color name must be one of the supported by colorama. :raise ValueError: When the given :code:`color` is unsupported. """ color = color.upper() if not text: to_color = PyFunceble.cli.storage.ASCII_PYFUNCEBLE else: to_color = text if not hasattr(colorama.Fore, color): raise ValueError(f" ({color!r}) is not supported.") color_to_apply = getattr(colorama.Fore, color) result = [] if ( PyFunceble.facility.ConfigLoader.is_already_loaded() and PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.colour ): for line in to_color.split("\n"): result.append(f"{color_to_apply}{line}{colorama.Fore.RESET}") return "\n".join(result) return to_color def get_home_representation() -> str: """ Provides our home ASCII logo representation. """ return colorify("yellow") def get_result_representation(status: str) -> str: """ Provides our result ASCII logo representation. """ if status in ( PyFunceble.storage.STATUS.up, PyFunceble.storage.STATUS.valid, PyFunceble.storage.STATUS.sane, ): color = "green" elif status in ( PyFunceble.storage.STATUS.down, PyFunceble.storage.STATUS.malicious, ): color = "red" else: color = "cyan" return colorify(color, text=PyFunceble.cli.storage.ASCII_PYFUNCEBLE) PyFunceble-4.2.29.dev/PyFunceble/cli/utils/sort.py000066400000000000000000000104111467462152100217320ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some utilities related to the sorting mechanism. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Any, Callable, List, Union import PyFunceble.facility import PyFunceble.storage from PyFunceble.converter.url2netloc import Url2Netloc from PyFunceble.helpers.regex import RegexHelper def standard(element: Any) -> List[Union[int, Any]]: """ Provides the key to use for the standard sorting. :param element: The element to format. """ element = element.strip() if not element: return [] regex_helper = RegexHelper() element = Url2Netloc(element).get_converted().strip() if PyFunceble.facility.ConfigLoader.is_already_loaded(): element = regex_helper.set_regex( r"^%s\s+" % PyFunceble.storage.CONFIGURATION.cli_testing.hosts_ip ).replace_match(element, "") cleaned = regex_helper.set_regex(r"[^a-zA-Z0-9\.]").replace_match(element, "") return [ int(x) if x.isdigit() else x for x in regex_helper.set_regex(r"(\d+)").split(cleaned) ] def hierarchical(element: Any) -> List[Union[int, Any]]: """ Provides the key to use for the hierarchical sorting. :param element: The element to format. """ element = element.strip() if not element: return [] element = Url2Netloc(element).get_converted().strip() if PyFunceble.facility.ConfigLoader.is_already_loaded(): element = RegexHelper( r"^%s\s+" % PyFunceble.storage.CONFIGURATION.cli_testing.hosts_ip ).replace_match(element, "") return standard(".".join(reversed(element.split(".")))) def get_best_sorting_key() -> Callable[[Any], List[Union[int, Any]]]: """ Provides the best sorting key from the configuration. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if PyFunceble.storage.CONFIGURATION.cli_testing.sorting_mode.hierarchical: return hierarchical return standard PyFunceble-4.2.29.dev/PyFunceble/cli/utils/stdout.py000066400000000000000000000127701467462152100222770ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some utilities related to the CLI stdout. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 secrets import colorama import PyFunceble.facility import PyFunceble.storage def get_template_to_use() -> str: """ Provides the template to use. """ if PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.simple: return "simple" if PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.all: return "all" return "less" def print_single_line(value: str = ".", end: str = "", *, force: bool = False) -> None: """ Prints the given :code:`value` in the current line. :param value: The default value :param end: Same as the end argument of the built-in print function. :param force: Forces the printing. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if ( force or PyFunceble.storage.CONFIGURATION.cli_testing.ci.active or PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.dots ): print(value, end=end) def print_thanks() -> None: """ Randomly prints our thanks message. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if ( not PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet and not PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.simple ): if PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.colour: print( f"\n{colorama.Fore.GREEN}{colorama.Style.BRIGHT}" f"Thank you for using PyFunceble!{colorama.Style.RESET_ALL}" ) else: print("\nThank you for using PyFunceble!") if int(secrets.token_hex(8), 16) % 3 == 0: if PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.colour: print( f"{colorama.Fore.YELLOW}{colorama.Style.BRIGHT}" f"Share your experience on {colorama.Fore.CYAN}Twitter " f"{colorama.Fore.YELLOW}with {colorama.Fore.CYAN}" f"#PyFunceble{colorama.Fore.YELLOW} " f"or {colorama.Fore.CYAN}@PyFunceble" f"{colorama.Fore.YELLOW}!" ) else: print( "Share your experience on Twitter with #PyFunceble or " "@PyFunceble!" ) if int(secrets.token_hex(8), 16) % 3 == 0: if PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.colour: print( f"{colorama.Fore.YELLOW}{colorama.Style.BRIGHT}" f"Do you have a feedback, an issue or an improvement idea? " f"{colorama.Fore.YELLOW}Let us know on {colorama.Fore.CYAN}" f"GitHub{colorama.Fore.YELLOW}!" ) else: print( "Do you ave a feedback, an issue or an improvement idea? " "Let us know on GitHub!" ) PyFunceble-4.2.29.dev/PyFunceble/cli/utils/testing.py000066400000000000000000000237101467462152100224260ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some testing related utilities Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from typing import List, Optional, Union from sqlalchemy.orm import Session import PyFunceble.storage from PyFunceble.converter.adblock_input_line2subject import AdblockInputLine2Subject from PyFunceble.converter.cidr2subject import CIDR2Subject from PyFunceble.converter.input_line2subject import InputLine2Subject from PyFunceble.converter.rpz_input_line2subject import RPZInputLine2Subject from PyFunceble.converter.rpz_policy2subject import RPZPolicy2Subject from PyFunceble.converter.subject2complements import Subject2Complements from PyFunceble.converter.url2netloc import Url2Netloc from PyFunceble.converter.wildcard2subject import Wildcard2Subject from PyFunceble.dataset.autocontinue.csv import CSVContinueDataset from PyFunceble.dataset.autocontinue.sql import SQLDBContinueDataset from PyFunceble.dataset.base import DatasetBase from PyFunceble.dataset.csv_base import CSVDatasetBase from PyFunceble.dataset.db_base import DBDatasetBase from PyFunceble.dataset.inactive.csv import CSVInactiveDataset from PyFunceble.dataset.inactive.sql import SQLDBInactiveDataset from PyFunceble.helpers.list import ListHelper from PyFunceble.helpers.regex import RegexHelper def get_testing_mode() -> str: """ Tries to provides the testing mode to apply to the CLI. """ if PyFunceble.storage.CONFIGURATION.cli_testing.testing_mode.syntax: return "SYNTAX" if PyFunceble.storage.CONFIGURATION.cli_testing.testing_mode.reputation: return "REPUTATION" if PyFunceble.storage.CONFIGURATION.cli_testing.testing_mode.availability: return "AVAILABILITY" return "UNKNOWN" def get_continue_databaset_object( db_session: Optional[Session] = None, ) -> Union[DatasetBase, CSVDatasetBase, DBDatasetBase]: """ Provides the continue object to work with. :param db_session: A database session to use. :raise ValueError: When the given database type is unkown. """ result = None if PyFunceble.storage.CONFIGURATION.cli_testing.db_type in "csv": result = CSVContinueDataset() elif PyFunceble.storage.CONFIGURATION.cli_testing.db_type in ( "mariadb", "mysql", "postgresql", ): result = SQLDBContinueDataset(db_session=db_session) if result: result.set_authorized( bool(PyFunceble.storage.CONFIGURATION.cli_testing.autocontinue) ) return result raise ValueError( " " f"({PyFunceble.storage.CONFIGURATION.cli_testing.db_type}) is unknown." ) def get_inactive_dataset_object( db_session: Optional[Session] = None, ) -> Union[DatasetBase, CSVDatasetBase, DBDatasetBase]: """ Provides the inactive object to work with. :param db_session: A database session to use. :raise ValueError: When the given database type is unkown. """ result = None if PyFunceble.storage.CONFIGURATION.cli_testing.db_type == "csv": result = CSVInactiveDataset() elif PyFunceble.storage.CONFIGURATION.cli_testing.db_type in ( "mariadb", "mysql", "postgresql", ): result = SQLDBInactiveDataset(db_session=db_session) if result: result.set_authorized( bool(PyFunceble.storage.CONFIGURATION.cli_testing.inactive_db) ) return result raise ValueError( " " f"({PyFunceble.storage.CONFIGURATION.cli_testing.db_type}) is unknown." ) def get_destination_from_origin(origin: str) -> str: """ Given the origin, we provides the destination. """ if "/" in origin: origin = origin.rsplit("/", 1)[-1] if os.sep in origin: origin = origin.rsplit(os.sep, 1)[-1] return RegexHelper("[^a-zA-Z0-9._-]").replace_match(origin, "_") def get_subjects_from_line( line: str, checker_type: str, *, subject_type: str = "domain", adblock_inputline2subject: Optional[AdblockInputLine2Subject] = None, wildcard2subject: Optional[Wildcard2Subject] = None, rpz_policy2subject: Optional[RPZPolicy2Subject] = None, rpz_inputline2subject: Optional[RPZInputLine2Subject] = None, inputline2subject: Optional[InputLine2Subject] = None, subject2complements: Optional[Subject2Complements] = None, url2netloc: Optional[Url2Netloc] = None, cidr2subject: Optional[CIDR2Subject] = None, ) -> List[str]: """ Provides the list of subject to test. """ result = [] if adblock_inputline2subject is None: adblock_inputline2subject = AdblockInputLine2Subject( aggressive=bool(PyFunceble.storage.CONFIGURATION.cli_decoding.aggressive) ) if wildcard2subject is None: wildcard2subject = Wildcard2Subject( aggressive=bool(PyFunceble.storage.CONFIGURATION.cli_decoding.aggressive) ) if rpz_policy2subject is None: rpz_policy2subject = RPZPolicy2Subject() if rpz_inputline2subject is None: rpz_inputline2subject = RPZInputLine2Subject( aggressive=bool(PyFunceble.storage.CONFIGURATION.cli_decoding.aggressive) ) if inputline2subject is None: inputline2subject = InputLine2Subject( aggressive=bool(PyFunceble.storage.CONFIGURATION.cli_decoding.aggressive) ) if subject2complements is None: subject2complements = Subject2Complements() if url2netloc is None: url2netloc = Url2Netloc( aggressive=bool(PyFunceble.storage.CONFIGURATION.cli_decoding.aggressive) ) if cidr2subject is None: cidr2subject = CIDR2Subject() adblock_inputline2subject.aggressive = wildcard2subject.aggressive = ( rpz_inputline2subject.aggressive ) = inputline2subject.aggressive = url2netloc.aggressive = bool( PyFunceble.storage.CONFIGURATION.cli_decoding.aggressive ) if inputline2subject.aggressive and subject_type == "url": # URL Decoder doesn't have an aggressive mode. # Therefore, we fix the "misconfiguration" inputline2subject.aggressive = not inputline2subject.aggressive if PyFunceble.storage.CONFIGURATION.cli_decoding.adblock: result.extend( # pylint: disable=line-too-long adblock_inputline2subject.set_data_to_convert(line).get_converted() ) elif PyFunceble.storage.CONFIGURATION.cli_decoding.wildcard: result.append(wildcard2subject.set_data_to_convert(line).get_converted()) elif PyFunceble.storage.CONFIGURATION.cli_decoding.rpz: result.extend( [ rpz_policy2subject.set_data_to_convert(x).get_converted() for x in rpz_inputline2subject.set_data_to_convert(line).get_converted() ] ) else: result.extend(inputline2subject.set_data_to_convert(line).get_converted()) if PyFunceble.storage.CONFIGURATION.cli_testing.complements: result.extend( [ y for x in result for y in subject2complements.set_data_to_convert(x).get_converted() ] ) if PyFunceble.storage.CONFIGURATION.cli_testing.cidr_expand: result = [ y for x in result for y in cidr2subject.set_data_to_convert(x).get_converted() ] if checker_type.lower() != "syntax": for index, subject in enumerate(result): if not subject: continue netloc = url2netloc.set_data_to_convert(subject).get_converted() result[index] = subject.replace(netloc, netloc.lower()) return ListHelper(result).remove_duplicates().remove_empty().subject PyFunceble-4.2.29.dev/PyFunceble/cli/utils/version.py000066400000000000000000000322241467462152100224360ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the version comparison tool. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import sys from datetime import datetime, timezone import colorama from box import Box import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.storage from PyFunceble.cli.utils.stdout import print_single_line from PyFunceble.converter.internal_url import InternalUrlConverter from PyFunceble.helpers.dict import DictHelper from PyFunceble.helpers.download import DownloadHelper from PyFunceble.utils.version import VersionUtility def get_upstream_version() -> Box: """ Provides the state of the upstream version. """ return Box( DictHelper().from_yaml( DownloadHelper( InternalUrlConverter( PyFunceble.cli.storage.VERSION_DUMP_LINK ).get_converted() ).download_text() ), frozen_box=True, ) def get_local_version() -> Box: """ Provides the state of the local version file. """ return Box( DictHelper().from_yaml_file( os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.DISTRIBUTED_VERSION_FILENAME, ) ), frozen_box=True, ) def handle_force_update(upstream_version: Box) -> None: """ Checks if we should force the end-user to update. """ version_utility = VersionUtility(PyFunceble.storage.PROJECT_VERSION) if ( PyFunceble.facility.ConfigLoader.is_already_loaded() and PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.colour ): message = ( f"{colorama.Style.BRIGHT}{colorama.Fore.RED}A critical issue has " f"been fixed.{colorama.Style.RESET_ALL}\n" f"{colorama.Style.BRIGHT}{colorama.Fore.GREEN}Please take the time to" f"update {PyFunceble.storage.PROJECT_NAME}!{colorama.Style.RESET_ALL}" ) else: message = ( "A critical issue has been fixed.\nPlease take the time to " f"update {PyFunceble.storage.PROJECT_NAME}!" ) if upstream_version.force_update.status: for minimal in upstream_version.force_update.minimal_version: if version_utility.is_older_than(minimal): print(message) sys.exit(1) def handle_deprecated_version(upstream_version: Box) -> bool: """ Checks if the current version (local) is deprecated and provides a message to the end-user. :return: :py:class:`True` if local is deprecated. :py:class:`False` otherwise. """ version_utility = VersionUtility(PyFunceble.storage.PROJECT_VERSION) if PyFunceble.facility.ConfigLoader.is_already_loaded(): if PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet: message = "Version deprecated." elif PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.colour: message = ( f"{colorama.Style.BRIGHT}{colorama.Fore.RED}Your current version " f"is considered as deprecated.{colorama.Style.RESET_ALL}\n" f"{colorama.Style.BRIGHT}{colorama.Fore.GREEN}Please take the " "time to " f"update {PyFunceble.storage.PROJECT_NAME}!{colorama.Style.RESET_ALL}" ) else: message = ( "Your current version is considered as deprecated.\nPlease take " "the time to " f"update {PyFunceble.storage.PROJECT_NAME}!" ) else: message = ( "Your current version is considered as deprecated.\nPlease take the " "time to " f"update {PyFunceble.storage.PROJECT_NAME}!" ) for version in reversed(upstream_version.deprecated): if version_utility.is_older_than(version): print(message) return True return False def handle_greater_version(upstream_version: Box) -> None: """ Checks if the current version (local) is more recent than the upstream one and provides a message. :return: :py:class:`True` if local is greater. :py:class:`False` otherwise. """ version_utility = VersionUtility(PyFunceble.storage.PROJECT_VERSION) if PyFunceble.facility.ConfigLoader.is_already_loaded(): if PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet: message = "" elif PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.colour: message = ( f"{colorama.Style.BRIGHT}{colorama.Fore.CYAN}Your current version " f"is more recent!{colorama.Style.RESET_ALL}\n" f"{colorama.Style.BRIGHT}{colorama.Fore.GREEN}You should " "really consider to submit a Pull Request to " f"{PyFunceble.storage.PROJECT_NAME}!" f"{colorama.Style.RESET_ALL}\n" f"{colorama.Style.BRIGHT}Your version:{colorama.Style.RESET_ALL} " f"{PyFunceble.storage.PROJECT_VERSION}\n" f"{colorama.Style.BRIGHT}Upstream version:{colorama.Style.RESET_ALL} " f"{upstream_version.current_version}\n" ) else: message = ( "Your current version is more recent!\nYou should really " "consider to submit a Pull Request to " f"{PyFunceble.storage.PROJECT_NAME}!\n" f"Your version: {PyFunceble.storage.PROJECT_VERSION}\n" f"Upstream version: {upstream_version.current_version}" ) else: message = ( "Your current version is more recent!\nYou should really " "consider to submit a Pull Request to " f"{PyFunceble.storage.PROJECT_NAME}!\n" f"Your version: {PyFunceble.storage.PROJECT_VERSION}\n" f"Upstream version: {upstream_version.current_version}" ) if version_utility.is_recent(upstream_version.current_version): print(message) return True return False def handle_older_version(upstream_version: Box) -> bool: """ Checks if the current version (local) is older than the upstream one and provides a message to the end-user. :return: :py:class:`True` if local is older. :py:class:`False` otherwise. """ version_utility = VersionUtility(PyFunceble.storage.PROJECT_VERSION) if PyFunceble.facility.ConfigLoader.is_already_loaded(): if PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet: message = "New version available." elif PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.colour: message = ( f"{colorama.Style.BRIGHT}{colorama.Fore.GREEN}Please take the " "time to " f"update {PyFunceble.storage.PROJECT_NAME}!" f"{colorama.Style.RESET_ALL}\n" f"{colorama.Style.BRIGHT}Your version:{colorama.Style.RESET_ALL} " f"{PyFunceble.storage.PROJECT_VERSION}\n" f"{colorama.Style.BRIGHT}Upstream version:{colorama.Style.RESET_ALL} " f"{upstream_version.current_version}\n" ) else: message = ( f"Please take the time to update " f"{PyFunceble.storage.PROJECT_NAME}!\n" f"Your version: {PyFunceble.storage.PROJECT_VERSION}\n" f"Upstream version: {upstream_version.current_version}" ) else: message = ( "Please take the time to " f"update {PyFunceble.storage.PROJECT_NAME}!\n" f"Your version: {PyFunceble.storage.PROJECT_VERSION}\n" f"Upstream version: {upstream_version.current_version}" ) if version_utility.is_older_than(upstream_version.current_version): print(message) return True return False def handle_messages(upstream_version: Box) -> None: """ Handles and prints the upstream messages. """ version_utility = VersionUtility(PyFunceble.storage.PROJECT_VERSION) iso_dateformat = "%Y-%m-%dT%H:%M:%S%z" if PyFunceble.facility.ConfigLoader.is_already_loaded(): if ( PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.quiet or PyFunceble.storage.CONFIGURATION.cli_testing.display_mode.simple ): authorized = False else: authorized = True else: authorized = True if authorized: local_timezone = datetime.now(timezone.utc).astimezone().tzinfo for minimal_version, data in upstream_version.messages.items(): if not version_utility.is_equal_to( minimal_version ) and not version_utility.is_recent(minimal_version): continue remaining_days = None for single_message in data: if "until_date" in single_message: try: remaining_days = ( datetime.strptime(single_message.until_date, iso_dateformat) - datetime.now(tz=local_timezone) ).days except ValueError: remaining_days = 0 if remaining_days is not None and remaining_days <= 0: continue if "until" in single_message and ( version_utility.is_recent(single_message.until) or version_utility.is_equal_to(single_message.until) ): continue if "type" in single_message: if single_message.type == "info": coloration = colorama.Fore.YELLOW elif single_message.type == "warning": coloration = colorama.Fore.MAGENTA else: coloration = colorama.Fore.BLUE else: coloration = colorama.Fore.CYAN coloration += colorama.Style.BRIGHT print( f"{coloration}{single_message.message}" f"{colorama.Style.RESET_ALL}\n" ) def print_central_messages(check_force_update: bool = False) -> None: """ Collect all possible messages from upstream and downstream and print them. """ upstream_version = get_upstream_version() if check_force_update: handle_force_update(upstream_version) _ = ( not handle_deprecated_version(upstream_version) and not handle_greater_version(upstream_version) and not handle_older_version(upstream_version) ) handle_messages(upstream_version) prefix = " - " if len(PyFunceble.cli.storage.EXTRA_MESSAGES) > 1 else "" for extra_message in PyFunceble.cli.storage.EXTRA_MESSAGES: print_single_line(prefix + extra_message, force=True, end="\n") PyFunceble-4.2.29.dev/PyFunceble/config/000077500000000000000000000000001467462152100177325ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/config/__init__.py000066400000000000000000000046261467462152100220530ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the configuration related submodules. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/config/compare.py000066400000000000000000000324111467462152100217330ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the configuration comparision interface. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy from typing import List, Optional import PyFunceble.storage from PyFunceble.helpers.dict import DictHelper from PyFunceble.helpers.merge import Merge class ConfigComparison: """ Provides an interface for comparing 2 configuration. """ DELETED_LINKS: List[str] = [ "config", "dir_structure", "iana", "ipv4_reputation", "mariadb", "mysql", "psl", "repo", "requirements", "user_agents", ] DELETED_CORE: List[str] = [ "dns_lookup_over_tcp", "generate_json", "header_printed", "iana_whois_server", "idna_conversion", "logs", "maximal_processes", "multiprocess_merging_mode", "multiprocess", "no_http_codes", "outputs", "shadow_file", "status", "store_whois_record", "unified", ] OLD_TO_NEW: dict = { "adblock": "cli_decoding.adblock", "aggressive": "cli_decoding.adblock_aggressive", "auto_continue": "cli_testing.autocontinue", "command": "cli_testing.ci.command", "command_before_end": "cli_testing.ci.end_command", "cooldown_time": "cli_testing.cooldown_time", "custom_ip": "cli_testing.hosts_ip", "days_between_inactive_db_clean": "cli_testing.days_between.db_clean", "days_between_db_retest": "cli_testing.days_between.db_retest", "db_type": "cli_testing.db_type", "debug": "debug.active", "dns_server": "dns.server", "filter": "cli_testing.file_filter", "generate_complements": "cli_testing.complements", "generate_hosts": "cli_testing.file_generation.hosts", "hierarchical_sorting": "cli_testing.sorting_mode.hierarchical", "inactive_database": "cli_testing.inactive_db", "less": "cli_testing.display_mode.less", "local": "cli_testing.local_network", "mining": "cli_testing.mining", "no_files": "cli_testing.file_generation.no_file", "plain_list_domain": "cli_testing.file_generation.plain", "print_dots": "cli_testing.display_mode.dots", "quiet": "cli_testing.display_mode.dots", "use_reputation_data": "lookup.reputation", "reputation": "lookup.reputation", "rpz": "cli_decoding.rpz", "show_execution_time": "cli_testing.display_mode.execution_time", "show_percentage": "cli_testing.display_mode.percentage", "simple": "cli_testing.display_mode.simple", "syntax": "cli_testing.testing_mode.syntax", "timeout": "lookup.timeout", "ci": "cli_testing.ci.active", "ci_autosave_commit": "cli_testing.ci.commit_message", "ci_autosave_final_commit": "cli_testing.ci.end_commit_message", "ci_autosave_minutes": "cli_testing.ci.max_exec_minutes", "ci_branch": "cli_testing.ci.branch", "ci_distribution_branch": "cli_testing.ci.distribution_branch", "whois_database": "cli_testing.whois_db", "wildcard": "cli_decoding.wildcard", "cli_decoding.adblock_aggressive": "cli_decoding.aggressive", "lookup.collection": "lookup.platform", "collection.push": "platform.push", "collection.preferred_status_origin": "platform.preferred_status_origin", } OLD_TO_NEW_NEGATE: dict = { "no_special": "lookup.special", "no_whois": "lookup.whois", "split": "cli_testing.file_generation.unified_results", } DELETE_FLATTEN: List[str] = [ "platform.url_base", ] NEW_STATUS_CODES: dict = { "up": [102, 207, 208, 226, 429], "potentially_down": [451], "potentially_up": [ 308, 403, 418, 421, 422, 423, 424, 426, 428, 431, 506, 507, 508, 510, 511, ], } _local_config: dict = {} _upsteam_config: dict = {} dict_helper: DictHelper = DictHelper() def __init__( self, *, local_config: Optional[dict] = None, upstream_config: Optional[dict] = None, ) -> None: if local_config: self.local_config = local_config if upstream_config: self.upstream_config = upstream_config @property def local_config(self) -> dict: """ Provides the current state of the :code:`_local_config`. """ return self._local_config @local_config.setter def local_config(self, value: dict) -> None: """ Sets the local configuration to work with. :raise TypeError: When :code:`value` is not a :py:class:`dict`. """ if not isinstance(value, dict): raise TypeError(f" should be {dict}, {type(value)} given.") self._local_config = copy.deepcopy(value) def set_local_config(self, value: dict) -> "ConfigComparison": """ Sets the local configuration to work with. """ self.local_config = value return self @property def upstream_config(self) -> dict: """ Provides the current state of the :code:`_upstream_config`. """ return self._upsteam_config @upstream_config.setter def upstream_config(self, value: dict) -> None: """ Sets the upstram configuration to work with. :raise TypeError: When :code:`value` is not a :py:class:`dict` """ if not isinstance(value, dict): raise TypeError(f" should be {dict}, {type(value)} given.") self._upsteam_config = copy.deepcopy(value) def set_upstream_config(self, value: dict) -> "ConfigComparison": """ Sets the upstram configuration to work with. """ self.upstream_config = value return self def is_local_identical(self) -> bool: """ Checks if the local configuration is identical to the upstream one. """ # pylint: disable=too-many-boolean-expressions,too-many-return-statements if ( not self.dict_helper.set_subject(self.local_config).has_same_keys_as( self.upstream_config ) or "user_agent" not in self.local_config or not isinstance(self.local_config["user_agent"], dict) or "active" in self.local_config["http_codes"] or "not_found_default" in self.local_config["http_codes"] or "self_managed" not in self.local_config["http_codes"] or "dns" not in self.local_config or "proxy" not in self.local_config or "follow_server_order" not in self.local_config["dns"] or "trust_server" not in self.local_config["dns"] or "platform" not in self.local_config or "platform" not in self.local_config["lookup"] ): return False for index in self.local_config: if index in self.DELETED_CORE: return False for index in self.local_config["links"]: if index in self.DELETED_LINKS: return False if "self_managed" in self.local_config["http_codes"] and not bool( self.local_config["http_codes"]["self_managed"] ): if "http_codes" not in self.upstream_config: return False for index, values in self.local_config["http_codes"]["list"].items(): if set(self.upstream_config["http_codes"]["list"][index]) != set( values ): return False if ( "platform" in self.local_config and "url_base" in self.local_config["platform"] ): return False return True def get_merged(self) -> dict: """ Provides the merged configuration. """ # pylint: disable=too-many-branches if self.is_local_identical(): return self.local_config if not self.local_config: return self.upstream_config original_local = copy.deepcopy(self.local_config) original_upstream = copy.deepcopy(self.upstream_config) flatten_original = self.dict_helper.set_subject(original_local).flatten() flatten_upstream = self.dict_helper.set_subject(original_upstream).flatten() for key, value in self.OLD_TO_NEW.items(): if key not in flatten_original: continue if value not in flatten_upstream: # pragma: no cover ## Safety. raise RuntimeError(f" ({value!r}) not found.") if "." not in key: flatten_original[value] = original_local[key] else: flatten_original[value] = flatten_original[key] del flatten_original[key] for key, value in self.OLD_TO_NEW_NEGATE.items(): if key not in flatten_original: continue if value not in flatten_upstream: # pragma: no cover ## Safety.0 raise RuntimeError(f" ({value!r}) not found.") if "." not in key: flatten_original[value] = not original_local[key] else: flatten_original[value] = not flatten_original[key] del flatten_original[key] for key in self.DELETE_FLATTEN: if key in flatten_original: del flatten_original[key] original_local = self.dict_helper.set_subject(flatten_original).unflatten() del flatten_original merged = Merge(original_local).into(original_upstream) if "dns_lookup_over_tcp" in merged and merged["dns_lookup_over_tcp"]: merged["dns"]["protocol"] = "TCP" for index in self.DELETED_CORE: if index in merged: del merged[index] for index in self.DELETED_LINKS: if index in merged["links"]: del merged["links"][index] if not bool(merged["http_codes"]["self_managed"]): for index, values in PyFunceble.storage.STD_HTTP_CODES.list.items(): merged["http_codes"]["list"][index] = list(values) if merged["cli_testing"]["db_type"] == "json": merged["cli_testing"]["db_type"] = "csv" if merged["cli_testing"]["cooldown_time"] is None: merged["cli_testing"]["cooldown_time"] = self.upstream_config[ "cli_testing" ]["cooldown_time"] if "user_agent" not in self.local_config or not isinstance( self.local_config["user_agent"], dict ): merged["user_agent"] = self.upstream_config["user_agent"] if "active" in merged["http_codes"]: del merged["http_codes"]["active"] if "not_found_default" in merged["http_codes"]: del merged["http_codes"]["not_found_default"] return merged PyFunceble-4.2.29.dev/PyFunceble/config/loader.py000066400000000000000000000364621467462152100215650ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the configuration loader. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools import os from typing import Any, Optional try: import importlib.resources as package_resources except ImportError: # pragma: no cover ## Retro compatibility import importlib_resources as package_resources from box import Box from yaml.error import MarkedYAMLError import PyFunceble.cli.storage import PyFunceble.storage from PyFunceble.config.compare import ConfigComparison from PyFunceble.downloader.iana import IANADownloader from PyFunceble.downloader.public_suffix import PublicSuffixDownloader from PyFunceble.downloader.user_agents import UserAgentsDownloader from PyFunceble.helpers.dict import DictHelper from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper from PyFunceble.helpers.file import FileHelper from PyFunceble.helpers.merge import Merge class ConfigLoader: """ Provides the interface which loads and updates the configuration (if needed). :param merge_upstream: Authorizes the merging of the upstream configuration. .. note:: If value is set to :py:class:`None` (default), we fallback to the :code:`PYFUNCEBLE_AUTO_CONFIGURATION` environment variable. """ path_to_config: Optional[str] = None path_to_default_config: Optional[str] = None path_to_overwrite_config: Optional[str] = None _custom_config: dict = {} _merge_upstream: bool = False file_helper: FileHelper = FileHelper() dict_helper: DictHelper = DictHelper() def __init__(self, merge_upstream: Optional[bool] = None) -> None: with package_resources.path( "PyFunceble.data.infrastructure", PyFunceble.storage.DISTRIBUTED_CONFIGURATION_FILENAME, ) as file_path: self.path_to_default_config = str(file_path) self.path_to_config = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.CONFIGURATION_FILENAME, ) self.path_to_overwrite_config = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.CONFIGURATION_OVERWRITE_FILENAME, ) if merge_upstream is not None: self.merge_upstream = merge_upstream elif EnvironmentVariableHelper("PYFUNCEBLE_AUTO_CONFIGURATION").exists(): self.merge_upstream = True def __del__(self) -> None: self.destroy() def reload_config(func): # pylint: disable=no-self-argument """ Reload the configuration (if it was already loaded) after launching the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) # pylint: disable=not-callable if self.is_already_loaded(): self.start() return result return wrapper @staticmethod def conditional_switch(config: dict) -> dict: """ Given the configuration that we are going to load, switches some of setting. :param config: The configuration we are going to load. """ # pylint: disable=too-many-boolean-expressions if ( "cli_testing" in config and "ci" in config["cli_testing"] and "active" in config["cli_testing"]["ci"] and "autocontinue" in config["cli_testing"] and bool(config["cli_testing"]["ci"]["active"]) and not bool(config["cli_testing"]["autocontinue"]) ): # Conditional autocontinue. # If we are under continuous integration, the autocontinue should be # activated. config["cli_testing"]["autocontinue"] = True if ( "lookup" in config and "timeout" in config["lookup"] and config["lookup"]["timeout"] and config["lookup"]["timeout"] < 0 ): # If timeout is set to a negative digit, switch to the default one. config["lookup"]["timeout"] = 5 if ( "cli_testing" in config and "testing_mode" in config["cli_testing"] and "platform_contribution" in config["cli_testing"]["testing_mode"] and config["cli_testing"]["testing_mode"]["platform_contribution"] ): # If we are under a special testing mode. We shouldn't generate # any files config["cli_testing"]["file_generation"]["no_file"] = True config["cli_testing"]["display_mode"]["dots"] = True config["cli_testing"]["autocontinue"] = False config["cli_testing"]["inactive_db"] = False config["cli_testing"]["mining"] = False config["cli_testing"]["local_network"] = False config["cli_testing"]["preload_file"] = False config["cli_testing"]["display_mode"]["percentage"] = False config["lookup"]["platform"] = False return config @staticmethod def is_already_loaded() -> bool: """ Checks if the configuration was already loaded. """ return bool(PyFunceble.storage.CONFIGURATION) @property def custom_config(self) -> dict: """ Provides the current state of the :code:`_custom_config` attribute. """ return self._custom_config @custom_config.setter @reload_config def custom_config(self, value: dict) -> None: """ Sets the custom configuration to set after loading. Side Effect: Directly inject into the configuration variables if it was already loaded. :raise TypeError: When :code:`value` is not a :py:class:`dict`. """ if not isinstance(value, dict): raise TypeError(f" should be {dict}, {type(value)} given.") if not self._custom_config: self._custom_config = value else: self._custom_config.update(value) def set_custom_config(self, value: dict) -> "ConfigLoader": """ Sets the custom configuration to set after loading. Side Effect: Directly inject into the configuration variables if it was already loaded. """ self.custom_config = value return self @property def merge_upstream(self) -> bool: """ Provides the current state of the :code:`_merge_upstream` attribute. """ return self._merge_upstream @merge_upstream.setter def merge_upstream(self, value: bool) -> None: """ Updates the value of :code:`_merge_upstream` attribute. :raise TypeError: When :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._merge_upstream = value def set_merge_upstream(self, value: bool) -> "ConfigLoader": """ Updates the value of :code:`_merge_upstream` attribute. """ self.merge_upstream = value return self def config_file_exist( self, ) -> bool: # pragma: no cover ## Existance checker already tested. """ Checks if the config file exists. """ return FileHelper(self.path_to_config).exists() def default_config_file_exist( self, ) -> bool: # pragma: no cover ## Existance checker already tested. """ Checks if the default configuration file exists. """ return self.file_helper.set_path(self.path_to_default_config).exists() def install_missing_infrastructure_files( self, ) -> "ConfigLoader": # pragma: no cover ## Copy method already tested """ Installs the missing files (when needed). .. note:: Installed if missing: - The configuration file. - The directory structure file. """ if not self.is_already_loaded(): if not self.file_helper.set_path(self.path_to_config).exists(): self.file_helper.set_path(self.path_to_default_config).copy( self.path_to_config ) return self @classmethod def download_dynamic_infrastructure_files( cls, ) -> "ConfigLoader": """ Downloads all the dynamicly (generated) infrastructure files. .. note:: Downloaded if missing: - The IANA dump file. - The Public Suffix dump file. """ ## pragma: no cover ## Underlying download methods already tested. if not cls.is_already_loaded(): IANADownloader().start() PublicSuffixDownloader().start() UserAgentsDownloader().start() def get_config_file_content(self) -> dict: """ Provides the content of the configuration file or the one already loaded. """ def is_3_x_version(config: dict) -> bool: """ Checks if the given configuration is an old one. :param config: The config to work with. """ return config and "days_between_inactive_db_clean" in config if not self.is_already_loaded(): self.install_missing_infrastructure_files() self.download_dynamic_infrastructure_files() try: config = self.dict_helper.from_yaml_file(self.path_to_config) except MarkedYAMLError: self.file_helper.set_path(self.path_to_default_config).copy( self.path_to_config ) config = self.dict_helper.from_yaml_file(self.path_to_config) config_comparer = ConfigComparison( local_config=config, upstream_config=self.dict_helper.from_yaml_file( self.path_to_default_config ), ) if ( not config or not isinstance(config, dict) or self.merge_upstream or is_3_x_version(config) or not config_comparer.is_local_identical() ): # pragma: no cover ## Testing the underlying comparison method is sufficent config = config_comparer.get_merged() self.dict_helper.set_subject(config).to_yaml_file(self.path_to_config) if self.file_helper.set_path(self.path_to_overwrite_config).exists(): overwrite_data = self.dict_helper.from_yaml_file( self.path_to_overwrite_config ) if isinstance(overwrite_data, dict): config = Merge( self.dict_helper.from_yaml_file(self.path_to_overwrite_config) ).into(config) else: # pragma: no cover ## Just make it visible to end-user. self.file_helper.write("") return config def get_configured_value(self, entry: str) -> Any: """ Provides the currently configured value. :param entry: An entry to check. multilevel should be separated with a point. :raise RuntimeError: When the configuration is not loaded yet. :raise ValueError: When the given :code:`entry` is not found. """ if not self.is_already_loaded(): raise RuntimeError("Configuration not loaded, yet.") if entry not in PyFunceble.storage.FLATTEN_CONFIGURATION: raise ValueError(f" ({entry!r}) not in loaded configuration.") return PyFunceble.storage.FLATTEN_CONFIGURATION[entry] def start(self) -> "ConfigLoader": """ Starts the loading processIs. """ config = self.get_config_file_content() if self.custom_config: config = Merge(self.custom_config).into(config) config = self.conditional_switch(config) PyFunceble.storage.CONFIGURATION = Box( config, ) PyFunceble.storage.FLATTEN_CONFIGURATION = DictHelper( PyFunceble.storage.CONFIGURATION ).flatten() PyFunceble.storage.HTTP_CODES = Box( config["http_codes"], ) if "platform" in config and config["platform"]: PyFunceble.storage.PLATFORM = Box(config["platform"]) PyFunceble.storage.LINKS = Box(config["links"]) if "proxy" in config and config["proxy"]: PyFunceble.storage.PROXY = Box(config["proxy"]) return self def destroy(self) -> "ConfigLoader": """ Destroys everything loaded. """ try: PyFunceble.storage.CONFIGURATION = Box( {}, ) PyFunceble.storage.FLATTEN_CONFIGURATION = {} PyFunceble.storage.HTTP_CODES = Box({}) PyFunceble.storage.PLATFORM = Box({}) PyFunceble.storage.LINKS = Box({}) PyFunceble.storage.PROXY = Box({}) except (AttributeError, TypeError): # pragma: no cover ## Safety. pass # This is not a mistake. self._custom_config = {} return self PyFunceble-4.2.29.dev/PyFunceble/converter/000077500000000000000000000000001467462152100204745ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/converter/__init__.py000066400000000000000000000046041467462152100226110ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides all the converters. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/converter/adblock_input_line2subject.py000066400000000000000000000311751467462152100263440ustar00rootroot00000000000000# pylint:disable=line-too-long """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the conversion of an AdBlock input line into testable subjests. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Any, List, Optional, Set, Union from PyFunceble.converter.base import ConverterBase from PyFunceble.converter.url2netloc import Url2Netloc from PyFunceble.helpers.list import ListHelper from PyFunceble.helpers.regex import RegexHelper class AdblockInputLine2Subject(ConverterBase): """ Provides an interface for the conversion or extraction of valuable subjects from an inputted AdBlock line. """ _aggressive: bool = False _regex_helper: Optional[RegexHelper] = None def __init__( self, data_to_convert: Optional[Any] = None, *, aggressive: bool = False, regex_helper: Optional[RegexHelper] = None, ) -> None: if regex_helper is None: self._regex_helper = RegexHelper() else: self._regex_helper = regex_helper super().__init__(data_to_convert=data_to_convert, aggressive=aggressive) @ConverterBase.data_to_convert.setter def data_to_convert(self, value: Any) -> None: """ Overrites the default behavior. :raise TypeError: When the given data to convert is not :py:class:`str` """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") # pylint: disable=no-member super(AdblockInputLine2Subject, self.__class__).data_to_convert.fset( self, value ) @staticmethod def should_be_ignored(line: str) -> bool: """ Checks if we should ignore the given line. """ starting_chars = ["!", "@@", "/", "[", ".", "-", "_", "?", "&"] return any(line.startswith(x) for x in starting_chars) @staticmethod def extract_base(subject: Union[str, List[str]]) -> Union[str, List[str]]: """ Extracts the base of the given subject (supposely URL). :param subject: The subject to work with. Example: Giving :code:`"hello.world/?is=beautiful"` returns :code:`"hello.world"` """ subject = subject.replace("*", "").replace("~", "") try: return Url2Netloc(subject).get_converted() except ValueError: return subject def _decode_multiple_subject(self, decoded: str) -> Set[str]: """ Implementation of the decoding of the case that multiple subjects are possible in the given :py:class:`str`. :param decoded: The decoded part to split. """ result = set() rematch = self._regex_helper.set_regex(r"((?:[^~\*,]+))").match( decoded, rematch=True, return_match=True ) if rematch: result.update({self.extract_base(x) for x in rematch}) return result def _decode_options(self, decoded_options: List[str]) -> Set[str]: """ Handle the decoding of the options. What it does: - It extracts all :code:`domain=` component - when found. - It extracts all :code:`href` URL base - when found. :param decoded_options: The splitted list of options. """ result = set() for rule in decoded_options: if "domain=" in rule: rule = rule.replace("domain=", "").replace("|", ",") result.update(self._decode_multiple_subject(rule)) continue if "href" in rule: matched = self._regex_helper.set_regex( r"((?:\"|\')(.*)(?:\"|\'))" ).match(rule, return_match=True, rematch=True, group=1) if matched: result.add(self.extract_base(matched)) continue return result def _decode_v1(self, line: str) -> Set[str]: """ Implementation of our first decoding mode. In this mode we try to decode the simple: ||ads.example.com^ rule. :param line: The line to decode. """ result = set() local_line = line.strip() if local_line.startswith("||") and ( local_line.endswith("^") or local_line.endswith("$") ): local_line = local_line.replace("||", "", 1) if local_line.endswith("^"): local_line = "".join(local_line.rsplit("^", 1)) elif local_line.endswith("$"): local_line = "".join(local_line.rsplit("$", 1)) result.update(self._decode_multiple_subject(local_line)) return {x for x in result if "." in x} def _decode_v2(self, line: str) -> Set[str]: """ Implementation of our second decoding mode. In this mode, we try to decode the simple: |https://ads.example.com| rule. :param line: The line to decode. """ result = set() local_line = line.strip() if local_line.startswith("|") and local_line.endswith("|"): local_line = local_line.replace("|", "", 1) local_line = "".join(local_line.rsplit("|", 1)) result.add(self.extract_base(local_line)) return {x for x in result if "." in x} def _decode_v3(self, line: str, *, aggressive: bool = False) -> Set[str]: """ Implementation of our third decoding mode. In this mode, we try to decode the simple: ||ads.example.com^$script,image,domain=example.com|~foo.example.info ||ads.example.com$script,image,domain=example.com|~foo.example.info rule. :param line: The line to decode. :param aggressive: Whether we should aggressively extract datasets. """ result = set() local_line = line.strip() if not local_line.startswith("||"): return result if "$" in local_line: v1_mode, options = local_line.split("$", 1) if not v1_mode.endswith("^"): v1_mode += "^" result.update(self._decode_v1(v1_mode)) if aggressive: result.update(self._decode_options(options.split(","))) elif "^" not in local_line: result.update(self._decode_v1(f"{local_line}^")) else: result.update(self._decode_v1(local_line[: local_line.find("^") + 1])) return {x for x in result if "." in x} def _decode_v4(self, line: str, *, aggressive: bool = False) -> Set[str]: """ Implementation of our fourth decoding mode. In this mode, we try to decode the simple: @@||ads.example.com/notbanner^$~script rule. :param line: The line to decode. :param aggressive: Whether we should aggressively extract datasets. """ result = set() local_line = line.strip() if ( not aggressive or not local_line.startswith("@@||") or "^$" not in local_line ): return result v1_mode, options = local_line.split("$", 1) result.update( {self.extract_base(x) for x in self._decode_v1(v1_mode.replace("@@", ""))} ) result.update(self._decode_options(options.split(","))) return {x for x in result if "." in x} def _decode_v5(self, line: str, *, aggressive: bool = False) -> Set[str]: """ Implementation of our fifth decoding mode. In this mode, we try to decode the simple: example.com,example.net##.advert exception.example.com#@#.advert example.com,example.net#?#div:-abp-has(> div > img.advert) exception.example.com#@#div:-abp-has(> div > img.advert) rule. :param line: The line to decode. :param aggressive: Whether we should aggressively extract datasets. """ local_line = line.strip() result = set() if not aggressive: return result separators = ["##", "#@#", "#?#"] obj_of_interest, options = "", "" for separator in separators: if separator in local_line: obj_of_interest, options = local_line.split(separator, 1) break result.update(self._decode_multiple_subject(obj_of_interest)) result.update(self._decode_options(options.split(","))) return {x for x in result if "." in x} def _decode_v6(self, line: str, *, aggressive: bool = False) -> Set[str]: """ Implementation of our sixth decoding mode. In this mode we try to decode the simple: $domain=exam.pl|elpmaxe.pl|example.pl ^hello^$domain=example.com rule. :param line: The line to decode. :param aggressive: Whether we should aggressively extract datasets. """ local_line = line.strip() result = set() if not aggressive: return result separators = ["$"] for separator in separators: if separator not in line: continue options = local_line[local_line.find(separator) + 1 :] result.update(self._decode_options(options.split(","))) return {x for x in result if "." in x} def get_converted(self) -> List[str]: """ Provides the converted data. """ return self.convert(self.data_to_convert, aggressive=self.aggressive) def convert(self, data: Any, *, aggressive: bool = False) -> List[str]: """ Converts the given dataset. :param data: The data to convert. :param aggressive: Whether we should aggressively extract datasets. """ result = set() if not self.should_be_ignored(data.strip()): result.update(self._decode_v1(data)) result.update(self._decode_v2(data)) result.update(self._decode_v3(data, aggressive=aggressive)) result.update(self._decode_v5(data, aggressive=aggressive)) result.update(self._decode_v6(data, aggressive=aggressive)) result.update(self._decode_v4(data, aggressive=aggressive)) return ListHelper(list(result)).sort().subject PyFunceble-4.2.29.dev/PyFunceble/converter/base.py000066400000000000000000000114631467462152100217650ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our converter class. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Any, Optional class ConverterBase: """ Provides the base of all converter class. """ _aggressive: bool = False _data_to_convert: Optional[Any] = None def __init__( self, data_to_convert: Optional[Any] = None, *, aggressive: bool = None, ) -> None: if data_to_convert is not None: self.data_to_convert = data_to_convert if aggressive is not None: self.aggressive = aggressive @property def data_to_convert(self) -> Optional[Any]: """ Provides the current state of the :code:`_data_to_convert` attribute. """ return self._data_to_convert @data_to_convert.setter def data_to_convert(self, value: Any) -> None: """ Sets the data to convert / to work with. :param value: The value to set. """ self._data_to_convert = value def set_data_to_convert(self, value: Any) -> "ConverterBase": """ Sets the data to convert / to work with. :param value: The value to set. """ self.data_to_convert = value return self @property def aggressive(self) -> bool: """ Provides the state of the :code:`_aggressive` attribute. """ return self._aggressive @aggressive.setter def aggressive(self, value: bool) -> None: """ Provides a way to activate/deactivate the aggressive decoding. :raise TypeError: When the given data to convert is not :py:class:`str` """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._aggressive = value def set_aggressive(self, value: bool) -> "ConverterBase": """ Provides a way to activate/deactivate the aggressive decoding. """ self.aggressive = value return self def get_converted(self) -> Optional[Any]: """ Provides the converted data. """ raise NotImplementedError() def convert(self, data: Any, *, aggressive: bool = False) -> Optional[Any]: """ Converts the given dataset. :param data: The data to convert. :param aggressive. Whether we should aggressively extract datasets. """ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/converter/cidr2subject.py000066400000000000000000000112101467462152100234240ustar00rootroot00000000000000# pylint:disable=line-too-long """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the converter of CIDR to subjects. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from ipaddress import IPv4Network from typing import Any, List, Optional from PyFunceble.checker.syntax.ip import IPSyntaxChecker from PyFunceble.converter.base import ConverterBase class CIDR2Subject(ConverterBase): """ Converts/Extracts the subjects of from the given CIDR. """ ip_syntax_checker: Optional[IPSyntaxChecker] = None def __init__( self, data_to_convert: Optional[Any] = None, *, ip_syntax_checker: Optional[IPSyntaxChecker] = None, ) -> None: super().__init__(data_to_convert=data_to_convert) if ip_syntax_checker is None: self.ip_syntax_checker = IPSyntaxChecker() else: self.ip_syntax_checker = ip_syntax_checker @ConverterBase.data_to_convert.setter def data_to_convert(self, value: Any) -> None: """ Overrites the default behavior. :raise TypeError: When the given data to convert is not :py:class:`str` """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") # pylint: disable=no-member super(CIDR2Subject, self.__class__).data_to_convert.fset(self, value) def get_converted(self) -> List[str]: """ Provides the subject-s to test. """ return self.convert(self.data_to_convert) def convert(self, data: Any, *, aggressive: bool = False) -> List[str]: """ Converts the given dataset. :param data: The data to convert. """ _ = aggressive result = set() subject = data.strip() if subject: try: self.ip_syntax_checker.set_subject(subject) if self.ip_syntax_checker.is_valid_v4_range(): result.update( str(x) for x in IPv4Network(self.ip_syntax_checker.subject) ) elif self.ip_syntax_checker.is_valid_v6_range(): # Not Implemented yet. result.add(subject) else: result.add(subject) except ValueError: result.add(subject) return list(result) PyFunceble-4.2.29.dev/PyFunceble/converter/input_line2subject.py000066400000000000000000000133321467462152100246600ustar00rootroot00000000000000# pylint:disable=line-too-long """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the default input line converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Any, List from PyFunceble.checker.syntax.ip import IPSyntaxChecker from PyFunceble.converter.base import ConverterBase from PyFunceble.converter.url2netloc import Url2Netloc class InputLine2Subject(ConverterBase): """ Converts/Extract the subjcts to test from an inputed line. """ COMMENT: str = "#" PARTICULAR_COMMENT: List[str] = ["!"] SPACE: str = " " NSLOOKUP_SPACE: str = "\\032" TAB: str = "\t" @ConverterBase.data_to_convert.setter def data_to_convert(self, value: Any) -> None: """ Overrites the default behavior. :raise TypeError: When the given data to convert is not :py:class:`str` """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") # pylint: disable=no-member super(InputLine2Subject, self.__class__).data_to_convert.fset(self, value) def get_converted(self) -> List[str]: """ Provides the subject to test. """ return self.convert(self.data_to_convert, aggressive=self.aggressive) @staticmethod def extract_base(subject: str) -> str: """ Extracts the base of the given subject - assuming that it may be a URL. :param subject: The subject to work with. """ try: return Url2Netloc(subject).get_converted() except ValueError: return subject def convert(self, data: Any, *, aggressive: bool = False) -> List[str]: """ Converts the given dataset. :param data: The data to convert. :param bool aggressive: Whether we should aggressively decode subjects. """ result = [] subject = data.strip() if subject and ( not subject.startswith(self.COMMENT) and any(not subject.startswith(x) for x in self.PARTICULAR_COMMENT) ): if self.COMMENT in subject: subject = subject[: subject.find(self.COMMENT)].strip() if self.NSLOOKUP_SPACE in subject: # Comply with RFC 6367: # Note that nslookup escapes spaces as "\032" for display # purposes, but a graphical DNS-SD browser should not. subject = subject.replace(self.NSLOOKUP_SPACE, self.SPACE) if self.SPACE in subject or self.TAB in subject: splitted = subject.split() if IPSyntaxChecker(splitted[0]).is_valid(): # This is for the hosts format. # If the first entry is an IP, we will only extract # the entries after the first one. datasets = splitted[1:] if aggressive: datasets = [self.extract_base(x) for x in datasets] result.extend(datasets) else: if aggressive: splitted = [self.extract_base(x) for x in splitted] # All other cases, we extract every entries. result.extend(splitted) else: if aggressive: subject = self.extract_base(subject) result.append(subject) return result PyFunceble-4.2.29.dev/PyFunceble/converter/internal_url.py000066400000000000000000000075201467462152100235500ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides a way to convert our internal URL. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Any import PyFunceble.storage from PyFunceble.converter.base import ConverterBase from PyFunceble.utils.version import VersionUtility class InternalUrlConverter(ConverterBase): """ Converter of the internal URLs. .. note:: The internal URLs are actually the URL that has nothing to do with what we are going to test. They are only relevant for the software itself. """ @ConverterBase.data_to_convert.setter def data_to_convert(self, value: Any) -> None: """ Overrites the default behavior. :raise TypeError: When the given data to convert is not :py:class:`str` """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") # pylint: disable=no-member super(InternalUrlConverter, self.__class__).data_to_convert.fset(self, value) def get_converted(self) -> str: """ Provides the converted data (after conversion) """ return self.convert(self.data_to_convert) def convert(self, data: Any, *, aggressive: bool = False) -> str: """ Converts the given dataset. :param data: The data to convert. """ _ = aggressive if VersionUtility(PyFunceble.storage.PROJECT_VERSION).is_dev(): return data.replace("master", "dev") return data.replace("dev", "master") PyFunceble-4.2.29.dev/PyFunceble/converter/rpz_input_line2subject.py000066400000000000000000000075031467462152100255560ustar00rootroot00000000000000# pylint:disable=line-too-long """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the conversion of the an RPZ input line into testable subjects. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: enable=line-too-long from typing import Any, List from PyFunceble.converter.input_line2subject import InputLine2Subject class RPZInputLine2Subject(InputLine2Subject): """ Converts/Extracts the subject from the given RPZ inputline. """ COMMENT: list = [";", "//", "#"] SPECIAL: list = ["$", "@"] def get_converted(self) -> List[str]: """ Provides the converted data. """ return self.convert(self.data_to_convert) def convert(self, data: Any, *, aggressive: bool = False) -> List[str]: """ Converts the given dataset. :param data: The data to convert. """ _ = aggressive result = [] subject = data.strip() if ( subject and not any(subject.startswith(x) for x in self.COMMENT) and not any(subject.startswith(x) for x in self.SPECIAL) ): for comment_sign in self.COMMENT: if comment_sign in subject: subject = subject[: subject.find(comment_sign)].strip() if self.SPACE in subject or self.TAB in subject: subject = subject.split()[0] if not subject.isdigit(): result.append(subject) elif not subject.isdigit(): result.append(subject) return result PyFunceble-4.2.29.dev/PyFunceble/converter/rpz_policy2subject.py000066400000000000000000000225211467462152100247040ustar00rootroot00000000000000# pylint:disable=line-too-long """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the conversion of the an RPZ POlicy into testable subjects. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: enable=line-too-long from typing import Any, List, Optional from PyFunceble.converter.rpz_input_line2subject import RPZInputLine2Subject from PyFunceble.converter.wildcard2subject import Wildcard2Subject class RPZPolicy2Subject(RPZInputLine2Subject): """ Converts/Extracts the subject from the given RPZ Policy into a subject. """ CLEANUP_MARKERS: list = [".rpz-nsdname"] IP_MARKERS: list = [".rpz-client-ip", ".rpz-ip", ".rpz-nsip"] _soa: Optional[str] = None _soas: List[str] = [] wilcard2subject: Optional[Wildcard2Subject] = None def __init__( self, data_to_convert: Optional[Any] = None, soas: Optional[List[str]] = None, soa: Optional[str] = None, *, wildcard2subject: Optional[Wildcard2Subject] = None, ) -> None: if soas is not None: self.soas = soas if soa is not None: self.soa = soa if wildcard2subject is not None: self.wilcard2subject = wildcard2subject else: self.wilcard2subject = Wildcard2Subject() super().__init__(data_to_convert=data_to_convert) @property def soa(self) -> Optional[str]: """ Provides the currently set SOA. """ return self._soa @soa.setter def soa(self, value: str) -> None: """ Sets the current SOA. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._soa = value if value not in self._soas: self._soas.append(value) def set_soa(self, value: str) -> "RPZPolicy2Subject": """ Sets the current SOA. :param value: The value to set. """ self.soa = value return self @property def soas(self) -> Optional[str]: """ Provides the currently set SOAs. """ return self._soas @soas.setter def soas(self, value: List[str]) -> None: """ Sets the current SOAs. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class`list`. :raise ValueError: When one of the given value is not a string. """ if not isinstance(value, list): raise TypeError(f" should be {list}, {type(value)} given.") if any(not isinstance(x, str) for x in value): raise ValueError(f" {value!r} should only contain strings.") self._soas = value def set_soas(self, value: List[str]) -> "RPZPolicy2Subject": """ Sets the current SOAs. :param value: The value to set. """ self.soas = value return self @staticmethod def remove_marker(subject: str, marker: str) -> str: """ Removes the given marker from the given subject. """ if marker in subject: return subject[: subject.find(marker)] return subject @classmethod def get_matching_cleanup_marker(cls, subject: str) -> Optional[str]: """ Checks if the given subject has a cleanup marker and provides it if found. """ for marker in cls.CLEANUP_MARKERS: if subject.endswith(marker): return marker return None @classmethod def get_matching_ip_marker(cls, subject: str) -> Optional[str]: """ Checks if the given subject has an IP marker and provides it if found. """ for marker in cls.IP_MARKERS: if subject.endswith(marker): return marker return None @classmethod def get_subject_from_ip_marker(cls, subject: str, marker: str) -> str: """ Removes the ip marker and converts the IP into a testable subject. """ result = cls.remove_marker(subject, marker) splitted_reversed_result = list(reversed(result.split("."))) if ( len(splitted_reversed_result) > 4 and splitted_reversed_result[-1].isdigit() and len(splitted_reversed_result[-1]) <= 2 and 0 <= int(splitted_reversed_result[-1]) <= 32 ): result = ( ".".join(splitted_reversed_result[:-1]) + f"/{splitted_reversed_result[-1]}" ) else: result = ".".join(splitted_reversed_result) possible_range = result[result.rfind(".") + 1 :] if ( ".zz." in result and possible_range.isdigit() and len(possible_range) <= 3 and 0 <= int(possible_range) <= 128 ): result = "/".join(result.rsplit(".", 1)).replace(".", ":") if "zz" in result: result = ( result.replace(".zz.", "::") .replace(":zz:", "::") .replace(".zz", "::") .replace(":zz", "::") .replace("zz.", "::") .replace("zz:", "::") .replace(".", ":") ) if any(x.isalpha() for x in result): result = result.replace(".", ":") return result def get_converted(self) -> Optional[str]: """ Provides the converted data. """ return self.convert(self.data_to_convert) def convert(self, data: Any, *, aggressive: bool = False) -> Optional[str]: """ Converts the given dataset. :param data: The data to convert. """ _ = aggressive subject = data.strip() if ( subject and not any(subject.startswith(x) for x in self.COMMENT) and not any(subject.startswith(x) for x in self.SPECIAL) ): for comment_sign in self.COMMENT: if comment_sign in subject: subject = self.remove_marker(subject, comment_sign).strip() subject = self.wilcard2subject.convert(subject) if self._soas: for soa in self._soas: subject = self.remove_marker(subject, f".{soa}") subject = self.remove_marker(subject, soa) found_cleanup_marker = self.get_matching_cleanup_marker(subject) if found_cleanup_marker: return self.remove_marker(subject, found_cleanup_marker) found_ip_marker = self.get_matching_ip_marker(subject) if found_ip_marker: return self.get_subject_from_ip_marker(subject, found_ip_marker) return subject return None PyFunceble-4.2.29.dev/PyFunceble/converter/subject2complements.py000066400000000000000000000122271467462152100250420ustar00rootroot00000000000000# pylint:disable=line-too-long """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an easy way to convert and get the complements of a subject. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: enable=line-too-long from typing import Any, List, Optional from PyFunceble.checker.syntax.domain import DomainSyntaxChecker from PyFunceble.converter.base import ConverterBase class Subject2Complements(ConverterBase): """ Converts a given wildcard into a testable subject. """ _include_given: bool = False def __init__( self, data_to_convert: Optional[Any] = None, *, include_given: Optional[bool] = False, ) -> None: if include_given is not None: self.include_given = include_given super().__init__(data_to_convert=data_to_convert) @ConverterBase.data_to_convert.setter def data_to_convert(self, value: Any) -> None: """ Overrites the default behavior. :raise TypeError: When the given data to convert is not :py:class:`str` or a :py:class:`list`. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") # pylint: disable=no-member super(Subject2Complements, self.__class__).data_to_convert.fset(self, value) @property def include_given(self) -> bool: """ Provides the state of the :code:`_include_given` attribute. """ return self._include_given @include_given.setter def include_given(self, value: bool) -> None: """ Provides a way to activate/deactivate the inclusion of the given subject into the result. :raise TypeError: When the given data to convert is not :py:class:`str` """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._include_given = value def set_include_given(self, value: bool) -> "Subject2Complements": """ Provides a way to activate/deactivate the inclusion of the given subject into the result. """ self.include_given = value return self def get_converted(self) -> List[str]: """ Provides the converted data. """ return self.convert(self.data_to_convert) def convert(self, data: Any, *, aggressive: bool = False) -> List[str]: """ Converts the given dataset. :param data: The data to convert. """ _ = aggressive result = [] checker = DomainSyntaxChecker(data) if self.include_given and data not in result: result.append(data) if data.startswith("www."): result.append(data[4:]) elif checker.is_valid_second_level(): result.append(f"www.{data}") return result PyFunceble-4.2.29.dev/PyFunceble/converter/url2netloc.py000066400000000000000000000116751467462152100231510ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides a way to convert/extract the network location of a given URL. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 urllib.parse from typing import Any, Optional from PyFunceble.converter.base import ConverterBase class Url2Netloc(ConverterBase): """ Provides the interface for the conversion/extration of the network location of a given URL. """ parsed_url: Optional[urllib.parse.ParseResult] = None """ Expose the parsed URL. """ @ConverterBase.data_to_convert.setter def data_to_convert(self, value: Any) -> None: """ Overrites the default behavior. :raise TypeError: When the given data to convert is not :py:class:`str` :raise ValueError: When the given data to convert is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") # pylint: disable=no-member super(Url2Netloc, self.__class__).data_to_convert.fset(self, value) @staticmethod def parse_single_url(data) -> Optional[urllib.parse.ParseResult]: """ Parses the URL. """ if data: if "[" in data and "]" not in data or "]" in data and "[" not in data: # Own wrapper around "Invalid IPv6 URL" when # http://example.org."] is given (for example.) data = data.replace("[", "").replace("]", "") return urllib.parse.urlparse(data) return None def parse_url(self) -> "Url2Netloc": """ Parses the URL. """ self.parsed_url = self.parse_single_url(self.data_to_convert) return self def get_converted(self) -> str: """ Provides the converted data (after conversion) """ # Retrocompatibility. self.parse_url() return self.convert(self.data_to_convert) def convert(self, data: Any, *, aggressive: bool = False) -> str: """ Converts the given dataset. :param data: The data to convert. """ _ = aggressive parsed_url = self.parse_single_url(data) if not parsed_url.netloc and parsed_url.path: netloc = parsed_url.path elif parsed_url.netloc: netloc = parsed_url.netloc else: # pragma: no cover ## Safety netloc = data if "//" in netloc: netloc = netloc[netloc.find("//") + 2 :] if "/" in netloc: netloc = netloc[: netloc.find("/")] return netloc PyFunceble-4.2.29.dev/PyFunceble/converter/wildcard2subject.py000066400000000000000000000073131467462152100243050ustar00rootroot00000000000000# pylint:disable=line-too-long """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an easy way to convert wildcard subject into a testable subject. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: enable=line-too-long from typing import Any from PyFunceble.converter.base import ConverterBase class Wildcard2Subject(ConverterBase): """ Converts a given wildcard into a testable subject. """ WILDCARD: str = "*." @ConverterBase.data_to_convert.setter def data_to_convert(self, value: Any) -> None: """ Overrites the default behavior. :raise TypeError: When the given data to convert is not :py:class:`str` """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") # pylint: disable=no-member super(Wildcard2Subject, self.__class__).data_to_convert.fset(self, value) def get_converted(self) -> str: """ Provides the converted data. """ return self.convert(self.data_to_convert) def convert(self, data: Any, *, aggressive: bool = False) -> str: """ Converts the given dataset. :param data: The data to convert. """ _ = aggressive subject = data.strip() if not subject: return None if subject.startswith(self.WILDCARD): return subject[2:] return subject PyFunceble-4.2.29.dev/PyFunceble/data/000077500000000000000000000000001467462152100173765ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/__init__.py000066400000000000000000000000001467462152100214750ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/000077500000000000000000000000001467462152100207725ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/__init__.py000066400000000000000000000046101467462152100231040ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the alembic data. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/000077500000000000000000000000001467462152100221375ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/__init__.py000066400000000000000000000046101467462152100242510ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the alembic data. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/env.py000066400000000000000000000111451467462152100233030ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the environment file of alembic. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: skip-file # flake8: noqa from alembic import context from sqlalchemy import engine_from_config, pool import PyFunceble.cli.facility import PyFunceble.database.sqlalchemy.all_schemas import PyFunceble.facility from PyFunceble.database.sqlalchemy.base_schema import SchemaBase config = context.config target_metadata = SchemaBase.metadata if not PyFunceble.facility.ConfigLoader.is_already_loaded(): # We load the configuration because we don't want to manually give # the db type. In fact, we may not know about it yet. PyFunceble.facility.ConfigLoader.start() PyFunceble.cli.facility.CredentialLoader.set_db_type( PyFunceble.storage.CONFIGURATION.cli_testing.db_type ) PyFunceble.cli.facility.CredentialLoader.start() credential_uri = PyFunceble.cli.facility.CredentialLoader.get_uri() def run_migrations_offline(): """ Run migrations in 'offline' mode. This configures the context with just a URL and not an Engine, though an Engine is acceptable here as well. By skipping the Engine creation we don't even need a DBAPI to be available. Calls to context.execute() here emit the given string to the script output. """ context.configure( url=credential_uri, target_metadata=target_metadata, literal_binds=True, dialect_opts={"paramstyle": "named"}, compare_type=True, ) with context.begin_transaction(): context.run_migrations() def run_migrations_online(): """ Run migrations in 'online' mode. In this scenario we need to create an Engine and associate a connection with the context. """ configuration = config.get_section(config.config_ini_section) configuration["sqlalchemy.url"] = credential_uri connectable = engine_from_config( configuration, prefix="sqlalchemy.", poolclass=pool.NullPool, ) with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata, compare_type=True ) with context.begin_transaction(): context.run_migrations() if context.is_offline_mode(): run_migrations_offline() else: run_migrations_online() PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/script.py.mako000066400000000000000000000007561467462152100247530ustar00rootroot00000000000000"""${message} Revision ID: ${up_revision} Revises: ${down_revision | comma,n} Create Date: ${create_date} """ from alembic import op import sqlalchemy as sa ${imports if imports else ""} # revision identifiers, used by Alembic. revision = ${repr(up_revision)} down_revision = ${repr(down_revision)} branch_labels = ${repr(branch_labels)} depends_on = ${repr(depends_on)} def upgrade(): ${upgrades if upgrades else "pass"} def downgrade(): ${downgrades if downgrades else "pass"} PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions/000077500000000000000000000000001467462152100240075ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions/35c79626ecb9_fix_some_columns.py000066400000000000000000000034171467462152100315720ustar00rootroot00000000000000"""Fix some columns Revision ID: 35c79626ecb9 Revises: ade87195b0a0 Create Date: 2020-08-21 11:42:07.044762 """ from alembic import op from sqlalchemy.exc import OperationalError # pylint: skip-file # revision identifiers, used by Alembic. revision = "35c79626ecb9" down_revision = "ade87195b0a0" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### try: op.create_index( op.f("ix_pyfunceble_mined_mined"), "pyfunceble_mined", ["mined"], unique=False, ) except OperationalError: pass try: op.drop_index("mined", table_name="pyfunceble_mined") except OperationalError: pass try: op.create_index( op.f("ix_pyfunceble_status_tested"), "pyfunceble_status", ["tested"], unique=False, ) except OperationalError: pass try: op.drop_index("tested", table_name="pyfunceble_status") except OperationalError: pass # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### try: op.create_index("tested", "pyfunceble_status", ["tested"], unique=True) except OperationalError: pass try: op.drop_index( op.f("ix_pyfunceble_status_tested"), table_name="pyfunceble_status" ) except OperationalError: pass try: op.create_index("mined", "pyfunceble_mined", ["mined"], unique=True) except OperationalError: pass try: op.drop_index(op.f("ix_pyfunceble_mined_mined"), table_name="pyfunceble_mined") except OperationalError: pass # ### end Alembic commands ### PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions/3a4c55a9320d_add_continue_table.py000066400000000000000000000022561467462152100320000ustar00rootroot00000000000000"""Add continue table. Revision ID: 3a4c55a9320d Revises: 3d6f4a33cdb2 Create Date: 2020-12-13 22:52:56.968513 """ import sqlalchemy as sa from alembic import op # pylint: skip-file # revision identifiers, used by Alembic. revision = "3a4c55a9320d" down_revision = "3d6f4a33cdb2" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.create_table( "pyfunceble_continue", sa.Column("id", sa.Integer(), nullable=False), sa.Column("created_at", sa.DateTime(), nullable=False), sa.Column("modified_at", sa.DateTime(), nullable=True), sa.Column("idna_subject", sa.Text(), nullable=False), sa.Column("checker_type", sa.String(length=50), nullable=False), sa.Column("destination", sa.Text(), nullable=False), sa.Column("source", sa.Text(), nullable=False), sa.Column("tested_at", sa.DateTime(), nullable=False), sa.PrimaryKeyConstraint("id"), ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_table("pyfunceble_continue") # ### end Alembic commands ### PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions/3d6f4a33cdb2_add_inactive_table.py000066400000000000000000000022571467462152100321200ustar00rootroot00000000000000"""Add inactive table. Revision ID: 3d6f4a33cdb2 Revises: 7bcf7fa64ba1 Create Date: 2020-12-13 19:45:41.893657 """ import sqlalchemy as sa from alembic import op # pylint: skip-file # revision identifiers, used by Alembic. revision = "3d6f4a33cdb2" down_revision = "7bcf7fa64ba1" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.create_table( "pyfunceble_inactive", sa.Column("id", sa.Integer(), nullable=False), sa.Column("created_at", sa.DateTime(), nullable=False), sa.Column("modified_at", sa.DateTime(), nullable=True), sa.Column("idna_subject", sa.Text(), nullable=False), sa.Column("checker_type", sa.String(length=50), nullable=False), sa.Column("destination", sa.Text(), nullable=False), sa.Column("source", sa.Text(), nullable=False), sa.Column("tested_at", sa.DateTime(), nullable=False), sa.PrimaryKeyConstraint("id"), ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_table("pyfunceble_inactive") # ### end Alembic commands ### 45713fea8097_deletion_uneeded_columns_from_whois_.py000066400000000000000000000024171467462152100355040ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions"""Deletion uneeded columns from whois record Revision ID: 45713fea8097 Revises: e04e8301d1a2 Create Date: 2020-12-07 12:36:04.818466 """ import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import mysql # pylint: skip-file # revision identifiers, used by Alembic. revision = "45713fea8097" down_revision = "e04e8301d1a2" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_column("pyfunceble_whois_record", "state") op.drop_column("pyfunceble_whois_record", "record") op.drop_column("pyfunceble_whois_record", "server") # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column( "pyfunceble_whois_record", sa.Column("server", mysql.TEXT(collation="utf8mb4_unicode_ci"), nullable=True), ) op.add_column( "pyfunceble_whois_record", sa.Column("record", mysql.TEXT(collation="utf8mb4_unicode_ci"), nullable=True), ) op.add_column( "pyfunceble_whois_record", sa.Column( "state", mysql.VARCHAR(collation="utf8mb4_unicode_ci", length=80), nullable=False, ), ) # ### end Alembic commands ### 459a0d7b8f09_add_idna_subject_column_into_whois.py000066400000000000000000000013661467462152100352170ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions"""Add idna_subject column into whois record Revision ID: 459a0d7b8f09 Revises: 45713fea8097 Create Date: 2020-12-07 12:37:52.018637 """ import sqlalchemy as sa from alembic import op # pylint: skip-file # revision identifiers, used by Alembic. revision = "459a0d7b8f09" down_revision = "45713fea8097" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column( "pyfunceble_whois_record", sa.Column("idna_subject", sa.Text(), nullable=True) ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_column("pyfunceble_whois_record", "idna_subject") # ### end Alembic commands ### 6f4729deaf03_delete_inactive_source_column.py000066400000000000000000000014471467462152100342750ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions"""Delete inactive.source column Revision ID: 6f4729deaf03 Revises: 95dc17ddd729 Create Date: 2021-02-13 12:21:00.493002 """ import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import mysql # pylint: skip-file # revision identifiers, used by Alembic. revision = "6f4729deaf03" down_revision = "95dc17ddd729" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_column("pyfunceble_inactive", "source") # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column( "pyfunceble_inactive", sa.Column("source", mysql.TEXT(collation="utf8mb4_unicode_ci"), nullable=False), ) # ### end Alembic commands ### 7bcf7fa64ba1_rename_created_to_created_at_and.py000066400000000000000000000053601467462152100350000ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions"""Rename created to created_at and modified_to_modified_at Revision ID: 7bcf7fa64ba1 Revises: 83ada95132bf Create Date: 2020-12-08 17:34:59.349943 """ import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import mysql # pylint: skip-file # revision identifiers, used by Alembic. revision = "7bcf7fa64ba1" down_revision = "83ada95132bf" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column( "pyfunceble_status", sa.Column("created_at", sa.DateTime(), nullable=False) ) op.add_column( "pyfunceble_status", sa.Column("modified_at", sa.DateTime(), nullable=True) ) op.drop_column("pyfunceble_status", "created") op.drop_column("pyfunceble_status", "modified") op.add_column( "pyfunceble_whois_record", sa.Column("created_at", sa.DateTime(), nullable=False), ) op.add_column( "pyfunceble_whois_record", sa.Column("modified_at", sa.DateTime(), nullable=True), ) op.drop_column("pyfunceble_whois_record", "created") op.drop_column("pyfunceble_whois_record", "modified") # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column( "pyfunceble_whois_record", sa.Column("modified", mysql.DATETIME(), nullable=True), ) op.add_column( "pyfunceble_whois_record", sa.Column("created", mysql.DATETIME(), nullable=False), ) op.drop_column("pyfunceble_whois_record", "modified_at") op.drop_column("pyfunceble_whois_record", "created_at") op.add_column( "pyfunceble_status", sa.Column("modified", mysql.DATETIME(), nullable=True) ) op.add_column( "pyfunceble_status", sa.Column("created", mysql.DATETIME(), nullable=False) ) op.drop_column("pyfunceble_status", "modified_at") op.drop_column("pyfunceble_status", "created_at") op.create_table( "pyfunceble_file", sa.Column( "id", mysql.INTEGER(display_width=11), autoincrement=True, nullable=False ), sa.Column("created", mysql.DATETIME(), nullable=False), sa.Column("modified", mysql.DATETIME(), nullable=True), sa.Column("path", mysql.TEXT(collation="utf8mb4_unicode_ci"), nullable=False), sa.Column( "test_completed", mysql.TINYINT(display_width=1), autoincrement=False, nullable=False, ), sa.CheckConstraint("`test_completed` in (0,1)", name="CONSTRAINT_1"), sa.PrimaryKeyConstraint("id"), mysql_collate="utf8mb4_unicode_ci", mysql_default_charset="utf8mb4", mysql_engine="InnoDB", ) # ### end Alembic commands ### PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions/83ada95132bf_delete_the_file_table.py000066400000000000000000000042061467462152100325270ustar00rootroot00000000000000"""Delete the file table. Revision ID: 83ada95132bf Revises: 459a0d7b8f09 Create Date: 2020-12-07 12:49:48.797794 """ import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import mysql # pylint: skip-file # revision identifiers, used by Alembic. revision = "83ada95132bf" down_revision = "459a0d7b8f09" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.alter_column( "pyfunceble_status", "file_id", existing_type=mysql.INTEGER(display_width=11), nullable=True, ) op.drop_constraint( "pyfunceble_status_ibfk_1", "pyfunceble_status", type_="foreignkey" ) op.drop_index("path", table_name="pyfunceble_file") # op.drop_table('pyfunceble_file') # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.create_foreign_key( "pyfunceble_status_ibfk_1", "pyfunceble_status", "pyfunceble_file", ["file_id"], ["id"], onupdate="CASCADE", ondelete="CASCADE", ) op.alter_column( "pyfunceble_status", "file_id", existing_type=mysql.INTEGER(display_width=11), nullable=False, ) op.create_table( "pyfunceble_file", sa.Column( "id", mysql.INTEGER(display_width=11), autoincrement=True, nullable=False ), sa.Column("created", mysql.DATETIME(), nullable=False), sa.Column("modified", mysql.DATETIME(), nullable=True), sa.Column("path", mysql.TEXT(collation="utf8mb4_unicode_ci"), nullable=False), sa.Column( "test_completed", mysql.TINYINT(display_width=1), autoincrement=False, nullable=False, ), sa.CheckConstraint("`test_completed` in (0,1)", name="CONSTRAINT_1"), sa.PrimaryKeyConstraint("id"), mysql_collate="utf8mb4_unicode_ci", mysql_default_charset="utf8mb4", mysql_engine="InnoDB", ) op.create_index("path", "pyfunceble_file", ["path"], unique=True) # ### end Alembic commands ### PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions/912bbcb77a6c_add_registrar_column.py000066400000000000000000000013331467462152100325240ustar00rootroot00000000000000"""Add registrar column Revision ID: 912bbcb77a6c Revises: 6f4729deaf03 Create Date: 2021-12-04 23:52:11.861732 """ import sqlalchemy as sa from alembic import op # pylint: skip-file # revision identifiers, used by Alembic. revision = "912bbcb77a6c" down_revision = "6f4729deaf03" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column( "pyfunceble_whois_record", sa.Column("registrar", sa.Text(), nullable=True) ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_column("pyfunceble_whois_record", "registrar") # ### end Alembic commands ### 95dc17ddd729_introduction_of_the_session_id_column.py000066400000000000000000000013461467462152100360610ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions"""Introduction of the session_id column Revision ID: 95dc17ddd729 Revises: bef7bcaac3f2 Create Date: 2020-12-23 02:26:21.647125 """ import sqlalchemy as sa from alembic import op # pylint: skip-file # revision identifiers, used by Alembic. revision = "95dc17ddd729" down_revision = "bef7bcaac3f2" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column( "pyfunceble_continue", sa.Column("session_id", sa.Text(), nullable=True) ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_column("pyfunceble_continue", "session_id") # ### end Alembic commands ### PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions/__init__.py000066400000000000000000000046241467462152100261260ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the alembic migrations files. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions/ade87195b0a0_base.py000066400000000000000000000102151467462152100271640ustar00rootroot00000000000000"""Base Revision ID: ade87195b0a0 Revises: Create Date: 2020-08-15 20:12:26.768419 """ import sqlalchemy as sa from alembic import op # pylint: skip-file # revision identifiers, used by Alembic. revision = "ade87195b0a0" down_revision = None branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.create_table( "pyfunceble_file", sa.Column("id", sa.Integer(), nullable=False), sa.Column("created", sa.DateTime(), nullable=False), sa.Column("modified", sa.DateTime(), nullable=True), sa.Column("path", sa.Text(), nullable=False), sa.Column("test_completed", sa.Boolean(), nullable=False), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("path"), ) op.create_table( "pyfunceble_whois_record", sa.Column("id", sa.Integer(), nullable=False), sa.Column("created", sa.DateTime(), nullable=False), sa.Column("modified", sa.DateTime(), nullable=True), sa.Column("subject", sa.Text(), nullable=False), sa.Column("expiration_date", sa.Text(), nullable=False), sa.Column("epoch", sa.Integer(), nullable=False), sa.Column("state", sa.String(length=80), nullable=False), sa.Column("record", sa.Text(), nullable=False), sa.Column("server", sa.Text(), nullable=True), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("subject"), ) op.create_table( "pyfunceble_status", sa.Column("id", sa.Integer(), nullable=False), sa.Column("created", sa.DateTime(), nullable=False), sa.Column("modified", sa.DateTime(), nullable=True), sa.Column("file_id", sa.Integer(), nullable=False), sa.Column("tested", sa.Text(), nullable=False), sa.Column("_status", sa.Text(), nullable=True), sa.Column("status", sa.Text(), nullable=True), sa.Column("_status_source", sa.Text(), nullable=True), sa.Column("status_source", sa.Text(), nullable=True), sa.Column("domain_syntax_validation", sa.Boolean(), nullable=True), sa.Column("expiration_date", sa.Text(), nullable=True), sa.Column("http_status_code", sa.Integer(), nullable=True), sa.Column("ipv4_range_syntax_validation", sa.Boolean(), nullable=True), sa.Column("ipv4_syntax_validation", sa.Boolean(), nullable=True), sa.Column("ipv6_range_syntax_validation", sa.Boolean(), nullable=True), sa.Column("ipv6_syntax_validation", sa.Boolean(), nullable=True), sa.Column("subdomain_syntax_validation", sa.Boolean(), nullable=True), sa.Column("url_syntax_validation", sa.Boolean(), nullable=True), sa.Column("is_complement", sa.Boolean(), nullable=True), sa.Column("test_completed", sa.Boolean(), nullable=False), sa.Column("tested_at", sa.DateTime(), nullable=False), sa.ForeignKeyConstraint( ["file_id"], ["pyfunceble_file.id"], onupdate="CASCADE", ondelete="CASCADE" ), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("tested"), ) op.create_table( "pyfunceble_mined", sa.Column("id", sa.Integer(), nullable=False), sa.Column("created", sa.DateTime(), nullable=False), sa.Column("modified", sa.DateTime(), nullable=True), sa.Column("subject_id", sa.Integer(), nullable=False), sa.Column("file_id", sa.Integer(), nullable=False), sa.Column("mined", sa.Text(), nullable=False), sa.ForeignKeyConstraint( ["file_id"], ["pyfunceble_file.id"], onupdate="CASCADE", ondelete="CASCADE" ), sa.ForeignKeyConstraint( ["subject_id"], ["pyfunceble_status.id"], onupdate="CASCADE", ondelete="CASCADE", ), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("mined"), ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_table("pyfunceble_mined") op.drop_table("pyfunceble_status") op.drop_table("pyfunceble_whois_record") op.drop_table("pyfunceble_file") # ### end Alembic commands ### PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions/bef7bcaac3f2_make_id_a_bigint.py000066400000000000000000000032721467462152100320020ustar00rootroot00000000000000"""Make id a bigint. Revision ID: bef7bcaac3f2 Revises: 3a4c55a9320d Create Date: 2020-12-16 19:09:41.212679 """ import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import mysql # pylint: skip-file # revision identifiers, used by Alembic. revision = "bef7bcaac3f2" down_revision = "3a4c55a9320d" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.alter_column( "pyfunceble_continue", "id", existing_type=mysql.INTEGER(display_width=11), type_=sa.BigInteger(), autoincrement=True, ) op.alter_column( "pyfunceble_inactive", "id", existing_type=mysql.INTEGER(display_width=11), type_=sa.BigInteger(), autoincrement=True, ) op.alter_column( "pyfunceble_whois_record", "id", existing_type=mysql.INTEGER(display_width=11), type_=sa.BigInteger(), autoincrement=True, ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.alter_column( "pyfunceble_whois_record", "id", existing_type=sa.BigInteger(), type_=mysql.INTEGER(display_width=11), autoincrement=True, ) op.alter_column( "pyfunceble_inactive", "id", existing_type=sa.BigInteger(), type_=mysql.INTEGER(display_width=11), autoincrement=True, ) op.alter_column( "pyfunceble_continue", "id", existing_type=sa.BigInteger(), type_=mysql.INTEGER(display_width=11), autoincrement=True, ) # ### end Alembic commands ### d8893cd406db_allow_whois_record_to_be_empty_null.py000066400000000000000000000016431467462152100355210ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions"""Allow whois record to be empty/NULL Revision ID: d8893cd406db Revises: 35c79626ecb9 Create Date: 2020-08-22 17:27:52.087506 """ from alembic import op from sqlalchemy.dialects import mysql # pylint: skip-file # revision identifiers, used by Alembic. revision = "d8893cd406db" down_revision = "35c79626ecb9" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.alter_column( "pyfunceble_whois_record", "record", existing_type=mysql.TEXT(collation="utf8mb4_unicode_ci"), nullable=True, ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.alter_column( "pyfunceble_whois_record", "record", existing_type=mysql.TEXT(collation="utf8mb4_unicode_ci"), nullable=False, ) # ### end Alembic commands ### e04e8301d1a2_deletion_of_the_mined_table.py000066400000000000000000000041161467462152100335570ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/mysql/versions"""Deletion of the mined table Revision ID: e04e8301d1a2 Revises: d8893cd406db Create Date: 2020-12-07 12:33:43.650514 """ import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import mysql # pylint: skip-file # revision identifiers, used by Alembic. revision = "e04e8301d1a2" down_revision = "d8893cd406db" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_index("ix_pyfunceble_mined_mined", table_name="pyfunceble_mined") op.drop_table("pyfunceble_mined") # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.create_table( "pyfunceble_mined", sa.Column( "id", mysql.INTEGER(display_width=11), autoincrement=True, nullable=False ), sa.Column("created", mysql.DATETIME(), nullable=False), sa.Column("modified", mysql.DATETIME(), nullable=True), sa.Column( "subject_id", mysql.INTEGER(display_width=11), autoincrement=False, nullable=False, ), sa.Column( "file_id", mysql.INTEGER(display_width=11), autoincrement=False, nullable=False, ), sa.Column("mined", mysql.TEXT(collation="utf8mb4_unicode_ci"), nullable=False), sa.ForeignKeyConstraint( ["file_id"], ["pyfunceble_file.id"], name="pyfunceble_mined_ibfk_1", onupdate="CASCADE", ondelete="CASCADE", ), sa.ForeignKeyConstraint( ["subject_id"], ["pyfunceble_status.id"], name="pyfunceble_mined_ibfk_2", onupdate="CASCADE", ondelete="CASCADE", ), sa.PrimaryKeyConstraint("id"), mysql_collate="utf8mb4_unicode_ci", mysql_default_charset="utf8mb4", mysql_engine="InnoDB", ) op.create_index( "ix_pyfunceble_mined_mined", "pyfunceble_mined", ["mined"], unique=False ) # ### end Alembic commands ### PyFunceble-4.2.29.dev/PyFunceble/data/alembic/postgresql/000077500000000000000000000000001467462152100231755ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/postgresql/__init__.py000066400000000000000000000046101467462152100253070ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the alembic data. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/data/alembic/postgresql/env.py000066400000000000000000000111451467462152100243410ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the environment file of alembic. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: skip-file # flake8: noqa from alembic import context from sqlalchemy import engine_from_config, pool import PyFunceble.cli.facility import PyFunceble.database.sqlalchemy.all_schemas import PyFunceble.facility from PyFunceble.database.sqlalchemy.base_schema import SchemaBase config = context.config target_metadata = SchemaBase.metadata if not PyFunceble.facility.ConfigLoader.is_already_loaded(): # We load the configuration because we don't want to manually give # the db type. In fact, we may not know about it yet. PyFunceble.facility.ConfigLoader.start() PyFunceble.cli.facility.CredentialLoader.set_db_type( PyFunceble.storage.CONFIGURATION.cli_testing.db_type ) PyFunceble.cli.facility.CredentialLoader.start() credential_uri = PyFunceble.cli.facility.CredentialLoader.get_uri() def run_migrations_offline(): """ Run migrations in 'offline' mode. This configures the context with just a URL and not an Engine, though an Engine is acceptable here as well. By skipping the Engine creation we don't even need a DBAPI to be available. Calls to context.execute() here emit the given string to the script output. """ context.configure( url=credential_uri, target_metadata=target_metadata, literal_binds=True, dialect_opts={"paramstyle": "named"}, compare_type=True, ) with context.begin_transaction(): context.run_migrations() def run_migrations_online(): """ Run migrations in 'online' mode. In this scenario we need to create an Engine and associate a connection with the context. """ configuration = config.get_section(config.config_ini_section) configuration["sqlalchemy.url"] = credential_uri connectable = engine_from_config( configuration, prefix="sqlalchemy.", poolclass=pool.NullPool, ) with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata, compare_type=True ) with context.begin_transaction(): context.run_migrations() if context.is_offline_mode(): run_migrations_offline() else: run_migrations_online() PyFunceble-4.2.29.dev/PyFunceble/data/alembic/postgresql/script.py.mako000066400000000000000000000007561467462152100260110ustar00rootroot00000000000000"""${message} Revision ID: ${up_revision} Revises: ${down_revision | comma,n} Create Date: ${create_date} """ from alembic import op import sqlalchemy as sa ${imports if imports else ""} # revision identifiers, used by Alembic. revision = ${repr(up_revision)} down_revision = ${repr(down_revision)} branch_labels = ${repr(branch_labels)} depends_on = ${repr(depends_on)} def upgrade(): ${upgrades if upgrades else "pass"} def downgrade(): ${downgrades if downgrades else "pass"} PyFunceble-4.2.29.dev/PyFunceble/data/alembic/postgresql/versions/000077500000000000000000000000001467462152100250455ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/alembic/postgresql/versions/__init__.py000066400000000000000000000046241467462152100271640ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the alembic migrations files. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/data/alembic/postgresql/versions/a32ac5d66eee_initial_version.py000066400000000000000000000046671467462152100326670ustar00rootroot00000000000000"""Initial Version Revision ID: a32ac5d66eee Revises: Create Date: 2022-12-28 07:20:50.310072 """ import sqlalchemy as sa from alembic import op # pylint: skip-file # revision identifiers, used by Alembic. revision = "a32ac5d66eee" down_revision = None branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.create_table( "pyfunceble_continue", sa.Column("id", sa.BigInteger(), nullable=False), sa.Column("created_at", sa.DateTime(), nullable=False), sa.Column("modified_at", sa.DateTime(), nullable=True), sa.Column("idna_subject", sa.Text(), nullable=False), sa.Column("checker_type", sa.String(length=50), nullable=False), sa.Column("destination", sa.Text(), nullable=False), sa.Column("source", sa.Text(), nullable=False), sa.Column("tested_at", sa.DateTime(), nullable=False), sa.Column("session_id", sa.Text(), nullable=True), sa.PrimaryKeyConstraint("id"), ) op.create_table( "pyfunceble_inactive", sa.Column("id", sa.BigInteger(), nullable=False), sa.Column("created_at", sa.DateTime(), nullable=False), sa.Column("modified_at", sa.DateTime(), nullable=True), sa.Column("idna_subject", sa.Text(), nullable=False), sa.Column("checker_type", sa.String(length=50), nullable=False), sa.Column("destination", sa.Text(), nullable=False), sa.Column("tested_at", sa.DateTime(), nullable=False), sa.PrimaryKeyConstraint("id"), ) op.create_table( "pyfunceble_whois_record", sa.Column("id", sa.BigInteger(), nullable=False), sa.Column("created_at", sa.DateTime(), nullable=False), sa.Column("modified_at", sa.DateTime(), nullable=True), sa.Column("subject", sa.Text(), nullable=False), sa.Column("idna_subject", sa.Text(), nullable=True), sa.Column("expiration_date", sa.Text(), nullable=False), sa.Column("epoch", sa.Integer(), nullable=False), sa.Column("registrar", sa.Text(), nullable=True), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("subject"), ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_table("pyfunceble_whois_record") op.drop_table("pyfunceble_inactive") op.drop_table("pyfunceble_continue") # ### end Alembic commands ### PyFunceble-4.2.29.dev/PyFunceble/data/infrastructure/000077500000000000000000000000001467462152100224565ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/infrastructure/.PyFunceble_production.yaml000066400000000000000000000604641467462152100277340ustar00rootroot00000000000000# .PyFunceble.yaml # This is the default configuration of the PyFunceble project. # # Behavior while using CLI switch: # # When using the CLI Argument of boolean parameters, they act like a light # switch. Meaning that if `no` is defined in the configuration file, using # the CLI argument will switch it to `yes`. # # However, if `yes` is defined in the configuration file, using the CLI # argument will switch it to `no`. # debug: # Provides everything related to the debug mode. # Enable/Disable the debug mode. # # NOTE: # When enabled, the output will be found inside the logs output directory. # If you prefer to have the output to STDOUT, you should declare the # following environment variable. # # PYFUNCEBLE_DEBUG_ON_SCREEN=yes # Environment Variable: PYFUNCEBLE_DEBUG # CLI Switch: `--debug` active: no # Set the logging level. # # Available: info, error, debug, critical # # Environment Variables: PYFUNCEBLE_DEBUG_LVL | PYFUNCEBLE_LOGGING_LVL # CLI Switch: --logging-level level: info cli_decoding: # Provides everything related to the decoding of input files from the CLI. # Enable/Disable the aggressive decoding. # # The aggressive mode is a mode that tries to decode as much as possible without # trying to follow any technical conventions. # # When decoding AdBlock filter lists, it will try to decode almost every # domains it finds. # # When decoding hosts file or plain text files, it will try to convert URLS # (e.g https://example.org/hello/world) into domains to test (e.g example.org). # # CLI Argument: --aggressive aggressive: no # Enable/Disable the (exclusive) decoding using the adblock decoder. # # WARNING: # Activating this parameter in your configuration file, will make # PyFunceble assume that it has to decode adblock files - exclusively. # # CLI Argument: --adblock adblock: no # Enable/Disable the (exclusive) decoding using the RPZ decoder. # # WARNING: # Activating this parameter in your configuration file, will make # PyFunceble assume that it has to decode RPZ files - exclusively. # # CLI Argument: --rpz rpz: no # Enable or disable the reduction of wildcards. # # Meaning that any caught wildcards (e.g. *.example.org) will be reduced so # that we have a "valid" domain to test (e.g. example.org). # # WARNING: # Activating this parameter will reduce wildcards (e.g *.example.org) to # match domains (e.g ecample.org) # # CLI Argument: --wildcard wildcard: no cli_testing: # Provides everything directly related to the testing through the CLI. # Set the IP to prefix each hosts file lines with. # # CLI Argument: -ip | --hosts-ip hosts_ip: "0.0.0.0" # Set the amount of maximal workers to use to perform tests. # # NOTE: # If set to `null`, the value is implicitly CPU * Cores - 2 # # CLI Argument: -w | --max-workers max_workers: null # Enable/Disable the autocontinue datasets. # # The autocontinue datasets/database is a database that temporarily store the # result of the tested subject in the hope to continue as soon as possible # after a break or shortage. # # CLI Argument: -c | --auto-continue | --continue autocontinue: no # Enable/Disable the inactive datasets. # # The inactive datasets/database is used to store the INACTIVE and INVALID # subjects to purposely retest then at a later time. # # This mechanism let you cleanup your source file while being sure that # pyfunceble will retest the old entries of your source file. After retesting, # pyfunceble will throw the newly ACTIVE subject from the database and put # it into your ACTIVE output files so that you can reintroduce them into # your list. # # CLI Argument: --inactive-db inactive_db: yes # Enable/Disable the whois storage of whois records. # # This mechanism let us avoid spaming the WHOIS servers by storing the # expiration dates from the whois record into a local datasets/database. # Later on, PyFunceble will query the local database first. # # CLI Argument: -wdb | --whois-database whois_db: yes # Enable/Disable the testing and generation of complements. # # A complement is `www.example.org` when `example.org` is given and vice-versa. # # CLI Argument: --complements complements: no # Enable/Disable the expension and testing of single addresses of a CIDR. # # CLI Argument: --cidr cidr_expand: no # Set the cooldown time to apply between each tests. # # This is essential to avoid spaming remote resources - especially WHOIS servers. # # WARNING: # This must be a value >= 0.0 # # CLI Argument: --cooldown-time cooldown_time: 0.0 # Sets the Database Connector type to use. # Available: csv | mariadb | mysql | postgresql # # Set the type of database to use or generate to store long term information-s. # # When set to `mariadb`, `mysql` or `postgesql` the following environment # variables are required. # # PYFUNCEBLE_DB_HOST - The host or unix socket path of the database server. # PYFUNCEBLE_DB_PORT - The port to use to reach the database server. # PYFUNCEBLE_DB_USERNAME - The username to use to connect to the database server - when applicable. # PYFUNCEBLE_DB_PASSWORD - The password to use to connect to the database server - when applicable. # PYFUNCEBLE_DB_NAME - The name of the database to work with. # PYFUNCEBLE_DB_CHARSET - The charset to use - when applicable. # # Available Values: csv | mariadb | mysql | postgresql # # CLI Argument: --database-type db_type: csv # Set the filter to apply while reading inputs. # # In other words, a global filter to apply to select the subject to tests. # Meaning that if you give `\.info$` (for example), we will only test the # subjects that ends with `.info`. # # CLI Argument: --filter file_filter: null # Enable/Disable the mining of subjects. # # When enabled, PyFunceble will follow the HTTP redirects and put all redirected # subjects into the testing queue and outputs. # # CLI Argument: --mining mining: no # Acknowledge/Dismiss that we are testing for subjects that are only on the # local network. # # NOTE: # When enabled, no syntax checking will be processed when performing # availability and reputation tests. # # CLI Argument: --local local_network: no # Enable/Disable the preloading of the given input file(s). # # When enabled, we take the time to pre-load subjects by decoding inputs files # and storing the informatino in the chosen datasets/database format. # The hope is to optimise some of our process by only focusing on testing. # # WARNING: # While this is helpful for long running tasks, this might not be a good # idea if you are testing a URL directly. This process is not optimizied # for sources that are constantly updated (checksums). # # CLI Argument: --preload preload_file: no # Enable/Disable a chancy testing mode that unleashes and bypass the safety # workflow-s in place in hope of speed. # # DANGER / WARNING: # You have been warned. This mode is for the chancy and lucky one. # # You shouldn't use this unless you fele really, really, really lucky and # trust your machine. # # Enabling this mode makes thinks look 'fast', but it may produce some # rather ... unexpected behavior and results - IF N+1 process simultaneously # write the same output file. # # This mode also makes the CLI terminal output unparsable - either. # # **MAY THE FORCE BE WITH YOU!** # # CLI Argument: --chancy chancy_tester: no ci: # Provides everything related to the testing within a Continuous integration # engine. # Enable/Disable the CI/CD mode. # # When enabled, PyFunceble will assume that it works with a git repository. # Therefore, you have to declare the following environment variables to # configure git for pushing - which is normally not available withing a # CI engine. # # GIT_NAME - The `git.name` to setup and use. # GIT_EMAIL - The `git.email` to setup and use. # GIT_BRANCH - (optional) - The git branch to use to distribute results betwen sessions. # GIT_DISTRIBUTION_BRANCH - (optional) - The git branch to use to distribute the final results. # GITHUB_TOKEN - The token to use to authenticate ourselves against GitHub. Read when under a GitHub Action or Jenkins CI worker. # GL_TOKEN - The token to use to authenticate ourselves againt GitLab. Read when under a GitLab Runner. # GH_TOKEN - The token to ue to authenticate ourselves against GitHub. Read when under a Travis CI instance. # # CLI Argument: --ci active: no # Set the commit message to apply to all results commit except the final one. # # CLI Argument: --ci-commit-message commit_message: "PyFunceble - AutoSave" # Set the commit message to apply to the very last and final result commit. # # CLI Argument: --ci-end-commit-message end_commit_message: "PyFunceble - Results" # Set the number of minutes to wait before to start saving and stopping a session. # # This parameter can be understood as the running time of PyFunceble under a # CI Engine. # # CLI Argument: --ci-max-minutes max_exec_minutes: 15 # Set the branch to use to distribute results between multiple CI/CD sessions. # # Environment Variable: GIT_BRANCH # CLI Argument: --ci-branch branch: master # Set the branch to use to distribute the final results of multiple CI/CD session. # # Environment Variable: GIT_DISTRIBUTION_BRANCH # CLI Argument: --ci-distribution-branch distribution_branch: master # Set the command to execute before each (except last) result commit. # # CLI Argument: --ci-command command: null # Set the command to execute before the very last result commit. # # CLI Argument: --ci-end-command end_command: null display_mode: # Provides everything related to the display/OUTPUT of PyFunceble. # Enable/Disable the printing of dots. # # Dots !? Why Dots ? WTH ?! # Yes, you read correctly dots. Those dots are crutial under CI/CD engines # that assumes that no-output within a few minutes is an error. To avoid # such situation when the CI/CD engines just kill the job, we print dots, # when we perform some tasks that may not output anything for a few minutes. # # An example is when you are on the second session of testing and PyFunceble # is going through the list of subjects but it sees that the subject has been # already tested. # # NOTE: # This argument is automatically switched to `yes` when under a CI/CD engine # (aka cli_testing.ci set to yes). # # CLI Argument: --dots dots: no # Enable/Disable the printing of the execution time at the end of a test session. # # CLI Argument: -ex | --execution execution_time: no # Enable/Disable the printing of the percentage stats per status at the end # of a test session. # # CLI Argument: --percentage percentage: yes # Enable/Disable the printing of the registrar stats per subjects at the end # of a test session. # # CLI Argument: --registrar registrar: no # Enable/Disable the printing of any outputs. # # CLI Argument: -q | --quiet quiet: no # Enable/Disable the printing of minimal tabular information when testing. less: yes # Enable/Disable the printing of most tabular information when testing. # # CLI Argument: -a | --all all: no # Enable/Disable the printing of an extreme simple and minimalistic information # when testing. # # CLI Argument: -s | --simple simple: no # Enable/Disable the printing of colored tabular information. # # CLI Argument: --colour | --color colour: yes # Set the status to display to STDOUT. # # WARNING: # When this parameter is not set to `ALL`, only the subjects matching the # selected status will be printed to STDOUT. Howerver, this doesn't have # any effect on the generated files. # # CLI Argument: --display-status status: all # Set the maximal number of registrar to display when we have to print the # registrar stats per subject. # # NOTE: # This doesn't have any effect on the generated files. # # CLI Argument: --max-registrar max_registrar: 15 testing_mode: # Provides and select the testing mode. # # NOTE: # Only one can be active at a time. # Enable/Disable the availability test mode. availability: yes # Enable/Disable the syntax test mode. # # CLI Argument: --syntax syntax: no # Enable/Disable the reputation test mode. # # CLI Argument: --reputation reputation: no # BETA: Activates the platform contribution test. platform_contribution: no days_between: # Provides everything which is x days periodic. # NOT IMPLEMENTED (Anticipation for future usage). db_clean: 28 # Set the minimal number of days between the retest of subject which were # stored into the inactive datasets/database. # # CLI Argument: -dbr | --days-between-db-retest db_retest: 1 sorting_mode: # Provides everything related to the output sorting. # # NOTE: # Only one can be active at a time. # # WARNING: # The parameters below only applies to the generated files. NOT STDOUT. # Enable/Disable the hierarchical sorting. # # CLI Argument: --hierarchical hierarchical: no # Enable/Disable the standard sorting. standard: yes file_generation: # Provides everything related to the generation of files. # Enable/Disable the generation of files. # # CLI Argument: --no-files no_file: no # Enable/Disable the generation of hosts formatted files. # # CLI Argument: -h | --hosts hosts: no # Enable/Disable the generation of plain/raw formatted files. # # CLI Argument: --plain plain: yes # Enable/Disable the generation of analytic files. # # Analytic ?! WTH !? # Yes, analytic! While PyFunceble is really good for a lot of things, sometime # it takes some decision without being really sure about it or without # wanting to be biased. Therefore, it generates files inside the analytic folder. # The files inside the analytic folder are there for human to analyse or # to invite the community to influence PyFunceble. # # If you are sure that the behavior of PyFunceble should be adopted for sure, # fill an issue and let's evolve it together :-) # analytic: yes # Enable/Disable the generation of unified results files. # # WARNING: # This parameter simply generate a unified copy of the STDOUT instead of 1 # file per status. # # CLI Argument: --unified-results unified_results: no # Enable/Disable the merging of the results of all inputted files into one # single output directory. # # Normally, PyFunceble generated a dedicated output folder for each inputted # files. However, if you want the results to be merged inside a single # folder, just switch this parameter. # # CLI Argument: --merge-output merge_output_dirs: no lookup: # Provides everything related to the lookups. # Enable/Disable the usage of DNS records to lookup the status. # # CLI Argument: --dns-lookup # Exclusive CLI Argument: --dns-lookup-only dns: yes # Enable/Disable the usage of HTTP status codes to lookup the status. # # CLI Argument: --http | --http-status-code-lookup # Exclusive CLI Argument: --http-only | --http-status-code-lookup http_status_code: yes # Enable/Disable the usage of network (information) socket to lookup the status. # # CLI Argument: --netinfo-lookup # Exclusive CLI Argument: --netinfo-lookup-only netinfo: yes # Enable/Disable the usage of special rules to lookup or switch the status. # # CLI Argument: --special-lookup # Exclusive CLI Argument: --special-lookup-only special: yes # Enable/Disable the usage of WHOIS records to lookup the status. # # CLI Argument: --whois-lookup # Exclusive CLI Argument: --whois-lookup-only whois: yes # Enable/Disable the usage of the reputation data to lookup the status. # # NOTE: # The reputation lookup is actualy a lookup against the AlienVault IPv4 # reputation file.s # # CLI Argument: --reputation-lookup # Exclusive CLI Argument: --reputation-lookup reputation: no # Activate the usage of the platform to lookup status. platform: no # Set the timeout to apply to each of our lookup methods - when possible. # # WARNING: # This should be a value >= 0. # # CLI Argument: -t | --timeout timeout: 5 dns: # Provides everything related to the DNS resolver & lookup. # Enable/Disable the follow-up of the order of DNS server. # # NOTE: # When disabled, the order of the DNS servers is randomized. # # CLI Argument: --follow-server-order follow_server_order: yes # Enable/Disable the trust mode. # # When this parameter is enabled, we will trust the result of the first DNS # server and only switch to the next server in the list ONLY when it is # unreachable. # # However, when this parameter is disabled, we will ask the other server when # the previous DNS give us a negative response - until a positive on is given. # # CLI Argument: --trust-dns-server trust_server: no # Set the list of DNS server to communicate with. # # WARNING: # IPv6 should be given in this format if a port is explicitly given: # # [ip]:port # # If you omit the braket, the port will be set to the default one (53). # # Example: # - first.dns # - second.dns # # CLI Argument: --dns server: null # Set the protocol to use. # # Available Values: UDP | TCP | HTTPS | TLS # # CLI Argument: --dns-protocol protocol: UDP # Set the delay (in second) to apply between each queries. # # WARNING: # This should be a value >= 0.0. # # CLI Argument: --dns-delay delay: 0.0 # Not Implemented yet. Reserved for future usage and implementation. share_logs: no user_agent: # Provides everything related to choice of user agent. # Set the browser to pickup. # # WARNING: # This parameter will be deprecated (soon?). # # Available Values: chrome, edge, firefox, ie, opera, safari browser: chrome # Set the platform to pickup. # # Available Values: linux, macosx, win10 platform: linux # Set the User-Agent to use. # # WARNING: # If you choose to set this argument, the browser or platform arguments # won't be taken into consideration. # # CLI Argument: -ua | --user-agent custom: null proxy: # Provides everything related to the proxy usage and configuration. # # The idea: # We have two main keys, "global" and "rules". # The system will always follow the global keys unless you define an explit # TLD. # # Example: # # Let's say we want all HTTP requests to go through example.org but we want # all HTTP request for domains ending with `.com`, `.org` and `.dev` to go # through example.com. And, we want all domains ending with `.onion` to go # through example.dev. # # This is how it will look like. # # global: # http: http://example.org:8080 # https: http://example.org:8080 # # rules: # - http: http://example.com:8080 # https: http://example.org:8080 # tld: # - com # - org # - dev # - http: socks5h://example.dev:8080 # https: socks5h://example.dev:8080 # tld: # - onion # global: # Global HTTP proxy to use when no rule is given or matched. # # CLI Argument: --http-proxy http: null # Global HTTPS proxy to use when no rule is given or matched. # # CLI Argument: --https-proxy https: null # The rules to apply. # See example. rules: [] # Enable/Disable the verification of the certificate when making HTTPS requests. verify_ssl_certificate: no # Set the maximum number of retries to perform. # This should be an integer >= 0. max_http_retries: 3 http_codes: # Provides everything related to the HTTP code lookup interpolation. # Stops PyFunceble self management of the list. # # NOTE: # This parameter is deprecated. self_managed: no list: # Dictionary with the status codes and their interpolation. up: # A list of status codes to consider as ACTIVE. - 100 - 101 - 102 - 200 - 201 - 202 - 203 - 204 - 205 - 206 - 207 - 208 - 226 - 429 potentially_down: # A list of status codes to consider as potentially INACTIVE. - 400 - 402 - 404 - 409 - 410 - 412 - 414 - 415 - 416 - 451 potentially_up: # A list of status codes to consider as potentially ACTIVE. - 000 - 300 - 301 - 302 - 303 - 304 - 305 - 307 - 308 - 403 - 405 - 406 - 407 - 408 - 411 - 413 - 417 - 418 - 421 - 422 - 423 - 424 - 426 - 428 - 431 - 500 - 501 - 502 - 503 - 504 - 505 - 506 - 507 - 508 - 510 - 511 links: # Provides some of the non hard-coded URLs. # WARNING: # The parameters listed bellow are not implemented yet as the # underlaying infrastructure will be rewritten. api_date_format: "https://pyfunceble.funilrys.com/api/date-format" api_no_referrer: "https://pyfunceble.funilrys.com/api/no-referrer" platform: # Provides everything related to the platform. # PyFunceble alone is a great tool. What if we could just test the subject that # were not already tested by others ? # Enable or disable the push of datasets (cf: test results) into the collection # (API). # # NOTE: # This parameter is useless, unless you have a valid API Token defined # into the PYFUNCEBLE_PLATFORM_API_TOKEN environment variable. # # CLI Argument: --push-collection push: no # Set the preferred pull "method". # # The platform (API) does not only provides datasets but it also offer an # aggregation endpoint that let PyFunceble pull datasets. # When pulling information about a subject that is already known by the platform, # it returns 3 group of results: # # - `frequent`, which provides the status that was mostly been pushed. # - `latest`, which provides the status based on the latest submitted datasets. # - `recommended`, which provides the recommended status. # # CLI Argument: --platform-preferred-origin preferred_status_origin: recommended # Defines the checker type to prioritize when trying to fullfil platform # contracts. # # Notes: # 1. This is a list. The order matters. # 2. One can overwrite this value, by settings a comma separated list of # checker type to prioritize through the PYFUNCEBLE_PLATFORM_CHECKER_PRIORITY # environment variable. # 3. When set to `none`, the platform will throw a random contract at us. # # Example: # Prioritize availability checker until no contract is available, then # prioritize syntax checker until no contract is available, then prioritize # reputation checker until no contract is available. # # - availability # - syntax # - reputation # # Available Values: none | availability | reputation | syntax # # CLI Argument: none checker_priority: - none # Defines the checker type to exclude when trying to fullfil platform # contracts. # # Notes: # 1. This is a list. # 2. One can overwrite this value, by settings a comma separated list of # checker type to exclude through the PYFUNCEBLE_PLATFORM_CHECKER_EXCLUDE # environment variable. # 3. When set to `none`, no checker type will be excluded. # # Example: # Exclude the reputation checker from the list of checker to use to fullfil. # # - reputation # # Available Values: none | availability | reputation | syntax # # CLI Argument: none checker_exclude: - none PyFunceble-4.2.29.dev/PyFunceble/data/infrastructure/__init__.py000066400000000000000000000000001467462152100245550ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/data/infrastructure/dir_structure_production.json000066400000000000000000000131321467462152100305150ustar00rootroot00000000000000{ "Analytic": { ".gitignore": { "content": "*\n!.gitignore\n!/ACTIVE/\n!/POTENTIALLY_ACTIVE/\n!/POTENTIALLY_INACTIVE/\n!/SUSPICIOUS/\n", "hash": "27caf2edf9b0fbbd3cb1a2dde931ed6c8aa380f5b5aac83b9433ec11" } }, "Analytic/ACTIVE": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "Analytic/POTENTIALLY_ACTIVE": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "Analytic/POTENTIALLY_INACTIVE": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "Analytic/SUSPICIOUS": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "domains": { ".gitignore": { "content": "*\n!.gitignore\n!/ACTIVE/\n!/INACTIVE/\n!/INVALID/\n!/MALICIOUS/\n!/SANE/\n!/VALID/\n", "hash": "a273966a13322ad4da9fbad4bd7247ca046de503de543c6f909e5e2b" } }, "domains/ACTIVE": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "domains/INACTIVE": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "domains/INVALID": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "domains/MALICIOUS": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "domains/SANE": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "domains/VALID": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "hosts": { ".gitignore": { "content": "*\n!.gitignore\n!/ACTIVE/\n!/INACTIVE/\n!/INVALID/\n!/MALICIOUS/\n!/SANE/\n!/VALID/\n", "hash": "a273966a13322ad4da9fbad4bd7247ca046de503de543c6f909e5e2b" } }, "hosts/ACTIVE": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "hosts/INACTIVE": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "hosts/INVALID": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "hosts/MALICIOUS": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "hosts/SANE": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "hosts/VALID": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "ips": { ".gitignore": { "content": "*\n!.gitignore\n!/ACTIVE/\n!/INACTIVE/\n!/INVALID/\n!/MALICIOUS/\n!/SANE/\n!/VALID/\n", "hash": "a273966a13322ad4da9fbad4bd7247ca046de503de543c6f909e5e2b" } }, "ips/ACTIVE": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "ips/INACTIVE": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "ips/INVALID": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "ips/MALICIOUS": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "ips/SANE": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "ips/VALID": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "logs": { ".gitignore": { "content": "*\n!.gitignore\n!/date_format/\n!/no_referrer/\n!/percentage/\n!/whois/\n", "hash": "7e533b26a45b8712a1ed4895b52b2cc798a03a632074800af98a52e7" } }, "logs/percentage": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } }, "splitted": { ".gitignore": { "content": "*\n!.gitignore\n", "hash": "0bd551cb904befcee06b7a99ef7ac54dba91ee21b5944c78759c1e4b" } } }PyFunceble-4.2.29.dev/PyFunceble/database/000077500000000000000000000000001467462152100202315ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/database/__init__.py000066400000000000000000000046741467462152100223550ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the structure and connection with external databases. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/database/credential/000077500000000000000000000000001467462152100223435ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/database/credential/__init__.py000066400000000000000000000046361467462152100244650ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to our credential holders. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/database/credential/base.py000066400000000000000000000276061467462152100236420ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our credential holders. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools import os from typing import List, Optional import PyFunceble.storage from PyFunceble.helpers.file import FileHelper class CredentialBase: """ Provides the base of all our credential holder. """ STD_HOST: str = "localhost" STD_PORT: int = 3306 STD_NAME: str = PyFunceble.storage.PROJECT_NAME.lower() STD_USERNAME: str = PyFunceble.storage.PROJECT_NAME.lower() STD_PASSWORD: str = f"{PyFunceble.storage.PROJECT_NAME}:15_93le" STD_CHARSET: str = "utf8mb4" VAR2ENV: dict = { "host": "PYFUNCEBLE_DB_HOST", "port": "PYFUNCEBLE_DB_PORT", "name": "PYFUNCEBLE_DB_NAME", "username": "PYFUNCEBLE_DB_USERNAME", "password": "PYFUNCEBLE_DB_PASSWORD", "charset": "PYFUNCEBLE_DB_CHARSET", } """ Maps our credential variable with environment variable. """ dotenv_locations: List[str] = [] """ Provides the location of the dotenv to work with. .. warning:: The order is important. The last one in the list will be taken as default if everything else is not found in the filesystem. """ protocol: Optional[str] = None _host: Optional[str] = None _port: Optional[int] = None _name: Optional[str] = None _username: Optional[str] = None _password: Optional[str] = None _charset: Optional[str] = None def __init__( self, *, host: Optional[str] = None, port: Optional[int] = None, name: Optional[str] = None, username: Optional[str] = None, password: Optional[str] = None, charset: Optional[str] = None, ) -> None: if host is not None: self.host = host else: self.host = self.STD_HOST if port is not None: self.port = port else: self.port = self.STD_PORT if name is not None: self.name = name else: self.name = self.STD_NAME if username is not None: self.username = username else: self.username = self.STD_USERNAME if password is not None: self.password = password else: self.password = self.STD_PASSWORD if charset is not None: self.charset = charset else: self.charset = self.STD_CHARSET self.dotenv_locations = [ os.path.realpath(PyFunceble.storage.ENV_FILENAME), os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.ENV_FILENAME ), ] def ensure_protocol_is_given(func): # pylint: disable=no-self-argument """ Ensures that the protocol is given before launching the decorated method. :raise ValueError: When the :code:`protocol` is not given. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not self.protocol: raise ValueError(" is not given.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @property def host(self) -> Optional[str]: """ Provides the current state of the :code:`_host` attribute. """ return self._host @host.setter def host(self, value: str) -> None: """ Sets the hosts to interact with. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._host = value def set_host(self, value: str) -> "CredentialBase": """ Sets the hosts to interact with. :param value: The value to set. """ self.host = value return self @property def port(self) -> Optional[int]: """ Provides the current state of the :code:`_port` attribute. """ return self._port @port.setter def port(self, value: int) -> None: """ Sets the port to interact with. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`int`. """ if not isinstance(value, int): raise TypeError(f" should be {int}, {type(value)} given.") self._port = value def set_port(self, value: int) -> "CredentialBase": """ Sets the port to interact with. :param value: The value to set. """ self.port = value return self @property def name(self) -> Optional[str]: """ Provides the current state of the :code:`_name` attribute. """ return self._name @name.setter def name(self, value: str) -> None: """ Sets the name of the database to interact with. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._name = value def set_name(self, value: str) -> "CredentialBase": """ Sets the name of the database to interact with. :param value: The value to set. """ self.name = value return self @property def username(self) -> Optional[str]: """ Provides the current state of the :code:`_username` attribute. """ return self._username @username.setter def username(self, value: str) -> None: """ Sets the username to use to authenticate ourselves. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._username = value def set_username(self, value: str) -> "CredentialBase": """ Sets the username to use to authenticate ourselves. :param value: The value to set. """ self.username = value return self @property def password(self) -> Optional[str]: """ Provides the current state of the :code:`_password` attribute. """ return self._password @password.setter def password(self, value: str) -> None: """ Sets the password to use to authenticate ourselves. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") self._password = value def set_password(self, value: str) -> "CredentialBase": """ Sets the password to use to authenticate ourselves. :param value: The value to set. """ self.host = value return self @property def charset(self) -> Optional[str]: """ Provides the current state of the :code:`_charset` attribute. """ return self._charset @charset.setter def charset(self, value: str) -> None: """ Sets the charset to use. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._charset = value def set_charset(self, value: str) -> "CredentialBase": """ Sets the charset to use. :param value: The value to set. """ self.charset = value return self @ensure_protocol_is_given def get_uri(self) -> str: """ Provides the SQLAlchemy URI. """ if self.host.startswith("/"): return ( f"{self.protocol}://{self.username}:{self.password}" f"@localhost/{self.name}?unix_socket={self.host}" f"&charset={self.charset}" ) return ( f"{self.protocol}://{self.username}:{self.password}" f"@{self.host}/{self.name}" f"?charset={self.charset}" ) def get_dot_env_file(self) -> str: """ Provides the dotenv file to work with. """ file_helper = FileHelper() for file in self.dotenv_locations: if file_helper.set_path(file).exists(): return file_helper.path return self.dotenv_locations[-1] PyFunceble-4.2.29.dev/PyFunceble/database/credential/mariadb.py000066400000000000000000000051331467462152100243160ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our mariadb credential holder. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.database.credential.base import CredentialBase class MariaDBCredential(CredentialBase): """ Provides our MariaDB credential holder. """ protocol: str = "mysql+pymysql" PyFunceble-4.2.29.dev/PyFunceble/database/credential/mysql.py000066400000000000000000000051251467462152100240650ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our mysql credential holder. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.database.credential.base import CredentialBase class MySQLCredential(CredentialBase): """ Provides our MySQL credential holder. """ protocol: str = "mysql+pymysql" PyFunceble-4.2.29.dev/PyFunceble/database/credential/postgresql.py000066400000000000000000000057051467462152100251270ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our postgresql credential holder. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.database.credential.base import CredentialBase class PostgreSQLCredential(CredentialBase): """ Provides our PostgreSQL credential holder. """ STD_CHARSET: str = "utf8" protocol: str = "postgresql+psycopg2" @CredentialBase.ensure_protocol_is_given def get_uri(self) -> str: """ Provides the SQLAlchemy URI. """ return ( f"{self.protocol}://{self.username}:{self.password}" f"@{self.host}/{self.name}" f"?client_encoding={self.charset}" ) PyFunceble-4.2.29.dev/PyFunceble/database/schemas/000077500000000000000000000000001467462152100216545ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/database/schemas/__init__.py000066400000000000000000000046161467462152100237740ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides all our schemas in one place! Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/database/schemas/autocontinue.py000066400000000000000000000057421467462152100247530ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the schema of our "whois_record" table. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from datetime import datetime from sqlalchemy import Column, DateTime, String, Text from PyFunceble.database.sqlalchemy.base_schema import SchemaBase class Continue(SchemaBase): """ Provides the schema of our continue table. """ idna_subject = Column(Text, nullable=False) checker_type = Column(String(length=50), nullable=False) destination = Column(Text, nullable=False) source = Column(Text, nullable=False) tested_at = Column(DateTime(), default=datetime.utcnow, nullable=False) session_id = Column(Text, nullable=True, default=None) PyFunceble-4.2.29.dev/PyFunceble/database/schemas/inactive.py000066400000000000000000000055751467462152100240440ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the schema of our "whois_record" table. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from datetime import datetime from sqlalchemy import Column, DateTime, String, Text from PyFunceble.database.sqlalchemy.base_schema import SchemaBase class Inactive(SchemaBase): """ Provides the schema of our inactive table. """ idna_subject = Column(Text, nullable=False) checker_type = Column(String(length=50), nullable=False) destination = Column(Text, nullable=False) tested_at = Column(DateTime(), default=datetime.utcnow, nullable=False) PyFunceble-4.2.29.dev/PyFunceble/database/schemas/status.py000066400000000000000000000074541467462152100235630ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the schema of our "status" table. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from datetime import datetime from sqlalchemy import Boolean, Column, DateTime, Integer, Text from PyFunceble.database.sqlalchemy.base_schema import SchemaBase class Status(SchemaBase): """ Provides the schema our status table. """ file_id = Column( Integer, nullable=True, ) tested = Column(Text, nullable=False, index=True) _status = Column(Text, nullable=True) status = Column(Text, nullable=True) _status_source = Column(Text, nullable=True) status_source = Column(Text, nullable=True) domain_syntax_validation = Column(Boolean(), default=False, nullable=True) expiration_date = Column(Text, nullable=True) http_status_code = Column(Integer, nullable=True) ipv4_range_syntax_validation = Column(Boolean(), default=False, nullable=True) ipv4_syntax_validation = Column(Boolean(), default=False, nullable=True) ipv6_range_syntax_validation = Column(Boolean(), default=False, nullable=True) ipv6_syntax_validation = Column(Boolean(), default=False, nullable=True) subdomain_syntax_validation = Column(Boolean(), default=False, nullable=True) url_syntax_validation = Column(Boolean(), default=False, nullable=True) is_complement = Column(Boolean(), default=False, nullable=True) test_completed = Column(Boolean(), default=False, nullable=False) tested_at = Column(DateTime(), default=datetime.utcnow, nullable=False) PyFunceble-4.2.29.dev/PyFunceble/database/schemas/whois_record.py000066400000000000000000000055641467462152100247270ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the schema of our "whois_record" table. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from sqlalchemy import Column, Integer, Text from PyFunceble.database.sqlalchemy.base_schema import SchemaBase class WhoisRecord(SchemaBase): """ Provides the schema of our whois_record table. """ subject = Column(Text, nullable=False, unique=True) idna_subject = Column(Text, nullable=True, unique=False) expiration_date = Column(Text, nullable=False) epoch = Column(Integer, nullable=False) registrar = Column(Text, nullable=True) PyFunceble-4.2.29.dev/PyFunceble/database/session.py000066400000000000000000000165011467462152100222710ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our database session interface. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy import functools from typing import Any, Optional import sqlalchemy import sqlalchemy.orm import sqlalchemy.pool import PyFunceble.sessions from PyFunceble.database.credential.base import CredentialBase class DBSession: """ Provides our very own database session interface and handler. """ credential: Optional[CredentialBase] = None current_session: sqlalchemy.orm.Session = None def __enter__(self) -> sqlalchemy.orm.Session: if PyFunceble.sessions.DB_FACTORY is not None: self.current_session = PyFunceble.sessions.DB_FACTORY() else: self.current_session = self.get_new_session()() return self.current_session def __exit__(self, exc_type, exc_val, exc_tb) -> None: if exc_type or exc_val or exc_tb: try: self.current_session.rollback() except AttributeError: pass self.close() def ensure_credential_is_given(func): # pylint: disable=no-self-argument """ Ensures that a credential object is set before launching the decorated method. :raise TypeError: When :code:`credential` is not correct. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.credential, CredentialBase): raise TypeError( f" should be {CredentialBase}, " f"{type(self.credential)} given." ) return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def execute_if_authorized(default: Any = None): # pylint: disable=no-self-argument """ Executes the decorated method only if we are authorized to process. Otherwise, apply the given :code:`default`. """ def inner_metdhod(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.authorized: return func(self, *args, **kwargs) # pylint: disable=not-callable return self if default is None else default return wrapper return inner_metdhod @property def authorized(self) -> bool: """ Provides the authorization to operate. """ return self.credential is not None @execute_if_authorized(None) @ensure_credential_is_given def init_db_sessions(self) -> "DBSession": """ Initiate the global session to work with. """ if PyFunceble.sessions.DB_ENGINE is None: PyFunceble.sessions.DB_ENGINE = sqlalchemy.create_engine( self.credential.get_uri(), poolclass=sqlalchemy.pool.NullPool, pool_pre_ping=True, ) PyFunceble.sessions.DB_FACTORY = sqlalchemy.orm.sessionmaker( bind=PyFunceble.sessions.DB_ENGINE, autoflush=True, autocommit=False, expire_on_commit=False, ) return self @execute_if_authorized(None) def get_db_session(self) -> "DBSession": """ Provides a new session. """ session_object = DBSession() session_object.credential = copy.deepcopy(self.credential) return session_object @execute_if_authorized(None) @ensure_credential_is_given def get_new_session(self) -> sqlalchemy.orm.sessionmaker: """ Creates and returns a new session. .. warning:: This method generate a new session without any pool of connections. """ engine = sqlalchemy.create_engine( self.credential.get_uri(), poolclass=sqlalchemy.pool.NullPool, pool_pre_ping=True, ) return sqlalchemy.orm.sessionmaker( bind=engine, autoflush=True, autocommit=False, expire_on_commit=False, ) @execute_if_authorized(None) @ensure_credential_is_given def get_new_pool_session(self) -> sqlalchemy.orm.sessionmaker: """ Create and return a new session. """ engine = sqlalchemy.create_engine(self.credential.get_uri(), pool_pre_ping=True) return sqlalchemy.orm.sessionmaker( bind=engine, autoflush=True, autocommit=False, expire_on_commit=False, ) def close(self) -> "DBSession": """ Closes the session if exists. """ if self.current_session is not None: self.current_session.close() del self.current_session self.current_session = None return self @execute_if_authorized(None) def query(self, *args, **kwargs) -> Any: """ Makes a query. """ # pylint: disable=no-member with self as db_session: return db_session.query(*args, **kwargs) PyFunceble-4.2.29.dev/PyFunceble/database/sqlalchemy/000077500000000000000000000000001467462152100223735ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/database/sqlalchemy/__init__.py000066400000000000000000000046501467462152100245110ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to everything we do with SQLAlchemy. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/database/sqlalchemy/all_schemas.py000066400000000000000000000051371467462152100252260ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides all our schemas. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: skip-file # flake8: noqa from PyFunceble.database.schemas.autocontinue import Continue from PyFunceble.database.schemas.inactive import Inactive from PyFunceble.database.schemas.whois_record import WhoisRecord PyFunceble-4.2.29.dev/PyFunceble/database/sqlalchemy/base_schema.py000066400000000000000000000066261467462152100252110ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our schemas. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from datetime import datetime import inflection from sqlalchemy import BigInteger, Column, DateTime from sqlalchemy.ext.declarative import declarative_base, declared_attr import PyFunceble.storage class OurSchemaBase: """ Provides the base of all our schema. """ @declared_attr def __tablename__(self): """ Defines our table name. """ # pylint: disable=no-member return ( f"{PyFunceble.storage.PROJECT_NAME.lower()}_" f"{inflection.underscore(self.__name__).lower()}" ) id = Column(BigInteger, primary_key=True, nullable=False) created_at = Column(DateTime(), default=datetime.utcnow, nullable=False) modified_at = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow) def to_dict(self) -> dict: """ Converts the current object to dict. """ return {x: y for x, y in self.__dict__.items() if not x.startswith("_sa")} SchemaBase = declarative_base(cls=OurSchemaBase) PyFunceble-4.2.29.dev/PyFunceble/dataset/000077500000000000000000000000001467462152100201125ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/dataset/__init__.py000066400000000000000000000046271467462152100222340ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides all the dataset interaction submodules Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/dataset/autocontinue/000077500000000000000000000000001467462152100226275ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/dataset/autocontinue/__init__.py000066400000000000000000000046351467462152100247500ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the continue logic(s). Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/dataset/autocontinue/base.py000066400000000000000000000066531467462152100241250ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of everything related to the continue logic(s). Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Generator, List, Tuple from PyFunceble.dataset.db_base import DBDatasetBase class ContinueDatasetBase(DBDatasetBase): """ Provides the base of all continue related interface. """ FIELDS: List[str] = [ "idna_subject", "checker_type", "destination", "source", "tested_at", "session_id", ] COMPARISON_FIELDS: List[str] = [ "idna_subject", "checker_type", "session_id", ] @DBDatasetBase.execute_if_authorized(None) def get_to_test(self, session_id: str) -> Generator[Tuple[str], str, None]: """ Provides the next subject to test. This method provides the dataset directly from the autocontinue dataset. This method only compare the `tested_at` field. If it older than 20 years, that means that we still have to test the subject. :param session_id: The session ID to work with. """ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/dataset/autocontinue/csv.py000066400000000000000000000142031467462152100237740ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the interface for the CSV management. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools import os from datetime import datetime, timezone from typing import Any, Generator, Optional, Tuple import PyFunceble.cli.storage import PyFunceble.facility from PyFunceble.dataset.autocontinue.base import ContinueDatasetBase from PyFunceble.dataset.csv_base import CSVDatasetBase from PyFunceble.helpers.file import FileHelper class CSVContinueDataset(CSVDatasetBase, ContinueDatasetBase): """ Provides the interface for the management of the continue CSV file. """ source_file: Optional[str] = None _base_directory: Optional[str] = None def __init__( self, *, authorized: Optional[bool] = None, remove_unneeded_fields: Optional[bool] = None, base_directory: Optional[str] = None, ) -> None: if base_directory is not None: self.set_base_directory(base_directory) super().__init__( authorized=authorized, remove_unneeded_fields=remove_unneeded_fields ) def __contains__(self, value: str) -> bool: for row in self.get_content(): try: if value == row["idna_subject"]: return True except KeyError: break return False def __getattr__(self, value: Any) -> Any: raise AttributeError(value) def __getitem__(self, value: Any) -> Any: raise KeyError(value) def update_source_file_afterwards(func): # pylint: disable=no-self-argument """ Updates the source file before launching the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) # pylint: disable=not-callable self.source_file = os.path.join( self.base_directory, PyFunceble.cli.storage.AUTOCONTINUE_FILE ) return result return wrapper @property def base_directory(self) -> Optional[str]: """ Provides the current state of the :code:`_base_directory` attribute. """ return self._base_directory @base_directory.setter @update_source_file_afterwards def base_directory(self, value: str) -> None: """ Sets the given base directory. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._base_directory = value def set_base_directory(self, value: str) -> "CSVContinueDataset": """ Sets the given base directory. :param value: The value to set. """ self.base_directory = value return self @CSVDatasetBase.execute_if_authorized(None) def cleanup(self) -> "CSVContinueDataset": """ Deletes the source file (completely). """ if self.source_file: FileHelper(self.source_file).delete() PyFunceble.facility.Logger.debug("Deleted: %r", self.source_file) return self @CSVDatasetBase.execute_if_authorized(None) def get_to_test(self, session_id: str) -> Generator[Tuple[str], str, None]: min_days = 365.25 * 20 for data in self.get_filtered_content({"session_id": session_id}): if (datetime.now(timezone.utc) - data["tested_at"]).days < min_days: continue if not data["idna_subject"]: continue yield data["idna_subject"] PyFunceble-4.2.29.dev/PyFunceble/dataset/autocontinue/sql.py000066400000000000000000000102571467462152100240050ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the interface for the MariaDB management. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from datetime import datetime, timedelta, timezone from typing import Generator, Tuple import PyFunceble.cli.factory import PyFunceble.sessions from PyFunceble.database.sqlalchemy.all_schemas import Continue from PyFunceble.dataset.autocontinue.base import ContinueDatasetBase from PyFunceble.dataset.sql_base import SQLDBDatasetBase class SQLDBContinueDataset(SQLDBDatasetBase, ContinueDatasetBase): """ Provides the interface for the management and the Continue dataset unser mariadb. """ ORM_OBJ: Continue = Continue @SQLDBDatasetBase.execute_if_authorized(None) # pylint: disable=arguments-differ def cleanup(self, *, session_id: str) -> "SQLDBContinueDataset": """ Cleanups the dataset. Meaning that we delete every entries which are needed anymore. :param source: The source to delete. :param session_id: The session ID to cleanup. """ self.db_session.query(self.ORM_OBJ).filter( self.ORM_OBJ.session_id == session_id ).delete(synchronize_session=False) self.db_session.commit() PyFunceble.facility.Logger.debug( "Deleted data related to %s (session_id", session_id ) return self @SQLDBDatasetBase.execute_if_authorized(None) def get_to_test(self, session_id: str) -> Generator[Tuple[str], str, None]: twenty_years_ago = datetime.now(timezone.utc) - timedelta(days=365.25 * 20) result = ( self.db_session.query(self.ORM_OBJ) .filter(self.ORM_OBJ.session_id == session_id) .filter(self.ORM_OBJ.tested_at < twenty_years_ago) ) for row in result: if not row.idna_subject: continue yield row.idna_subject PyFunceble-4.2.29.dev/PyFunceble/dataset/base.py000066400000000000000000000122251467462152100214000ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all datasets classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from typing import Any, Optional import PyFunceble.storage from PyFunceble.downloader.base import DownloaderBase from PyFunceble.helpers.dict import DictHelper from PyFunceble.helpers.file import FileHelper class DatasetBase: """ Provides the base of all dataset. """ STORAGE_INDEX: Optional[str] = None DOWNLOADER: Optional[DownloaderBase] = None source_file: Optional[str] = None def __contains__(self, value: Any): # pragma: no cover raise NotImplementedError() def __getattr__(self, value: Any): # pragma: no cover raise AttributeError(value) def __getitem__(self, value: Any): # pragma: no cover raise KeyError(value) def __getstate__(self): # pragma: no cover return vars(self) def __setstate__(self, state): # pragma: no cover vars(self).update(state) def ensure_source_file_exists(func): # pylint: disable=no-self-argument """ Ensures that the source file exists before running the decorated method. :raise TypeError: When :code:`self.source_file` is not a :py:class:`str`. :raise ValueError: When :code:`self.source_file` is empty. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.source_file, str): raise TypeError( f" should be {str}, " f"{type(self.source_file)} given." ) if not self.source_file: raise ValueError(" should not be empty.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @ensure_source_file_exists def get_content(self) -> Optional[dict]: """ Provides the cached or the real contend of the dataset (after caching) :raise FileNotFoundError: When the declared file does not exists. """ if ( bool(self.STORAGE_INDEX) and hasattr(PyFunceble.storage, self.STORAGE_INDEX) and bool(getattr(PyFunceble.storage, self.STORAGE_INDEX)) ): return getattr(PyFunceble.storage, self.STORAGE_INDEX) file_helper = FileHelper(self.source_file) if not file_helper.exists() and bool( self.DOWNLOADER ): # pragma: no cover ## This is just a safety endpoint. self.DOWNLOADER.start() if not file_helper.exists(): raise FileNotFoundError(file_helper.path) content = DictHelper().from_json_file( self.source_file, return_dict_on_error=False ) setattr(PyFunceble.storage, self.STORAGE_INDEX, content) return content PyFunceble-4.2.29.dev/PyFunceble/dataset/csv_base.py000066400000000000000000000231421467462152100222530ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all CSV storeed datasets. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 csv import tempfile from datetime import datetime, timedelta, timezone from typing import Generator, Optional, Tuple import PyFunceble.facility from PyFunceble.dataset.db_base import DBDatasetBase from PyFunceble.helpers.file import FileHelper class CSVDatasetBase(DBDatasetBase): """ Provides the base of all CSV dataset. """ @DBDatasetBase.ensure_source_file_exists def get_csv_writer(self) -> Tuple[csv.DictWriter, open]: """ Provides the standard and initiated CSV Dict writer along with the file that was open with it. """ file_helper = FileHelper(self.source_file) add_header = not file_helper.exists() file_handler = file_helper.open("a+", newline="", encoding="utf-8") writer = csv.DictWriter(file_handler, fieldnames=self.FIELDS) if add_header: writer.writeheader() return writer, file_handler def update(self, row: dict, *, ignore_if_exist: bool = False) -> "DBDatasetBase": """ Adds the given dataset into the database if it does not exists. Update otherwise. :param row: The row or dataset to manipulate. :param ignore_if_exist: Ignore the insertion/update if the row already exists. :raise TypeError: When the given :code:`row` is not a :py:class`dict`. """ if not isinstance(row, dict): raise TypeError(f" should be {dict}, {type(row)} given.") PyFunceble.facility.Logger.info("Started to update row.") if self.exists(row): if not ignore_if_exist: self.remove(row) self.add(row) else: self.add(row) PyFunceble.facility.Logger.debug("Updated row:\n%r", row) PyFunceble.facility.Logger.info("Finished to update row.") return self @DBDatasetBase.ensure_source_file_exists @DBDatasetBase.execute_if_authorized(None) def add(self, row: dict) -> "CSVDatasetBase": """ Adds the given dataset into the CSV file. :param row: The row or dataset to add. :raise TypeError: When the given :code:`row` is not a :py:class`dict`. """ if not isinstance(row, dict): raise TypeError(f" should be {dict}, {type(row)} given.") PyFunceble.facility.Logger.info("Started to add row.") if self.remove_unneeded_fields: row = self.get_filtered_row(row) writer, file_handler = self.get_csv_writer() writer.writerow(row) file_handler.close() PyFunceble.facility.Logger.debug("Added row:\n%r", row) PyFunceble.facility.Logger.info("Finished to add row.") return self @DBDatasetBase.ensure_source_file_exists @DBDatasetBase.execute_if_authorized(None) def remove(self, row: dict) -> "CSVDatasetBase": """ Removes the given dataset from the CSV file. :param row: The row or dataset to add. :raise TypeError: When the given :code:`row` is not a :py:class`dict`. """ if not isinstance(row, dict): raise TypeError(f" should be {dict}, {type(row)} given.") PyFunceble.facility.Logger.info("Started to remove row.") if self.remove_unneeded_fields: row = self.get_filtered_row(row) our_temp_file = tempfile.NamedTemporaryFile("w", delete=False, encoding="utf-8") our_temp_filename = our_temp_file.name writer = csv.DictWriter(our_temp_file, fieldnames=self.FIELDS) writer.writeheader() for read_row in self.get_content(): if self.are_equal(read_row, row): continue writer.writerow(read_row) our_temp_file.close() FileHelper(our_temp_filename).move(self.source_file) PyFunceble.facility.Logger.debug("Removed row:\n%r", row) PyFunceble.facility.Logger.info("Finished to remove row.") return self @DBDatasetBase.ensure_source_file_exists @DBDatasetBase.execute_if_authorized(None) def get_content(self) -> Generator[Optional[dict], None, None]: """ Provides a generator which provides the next line to read. """ file_helper = FileHelper(self.source_file) if file_helper.exists(): file_handler = file_helper.open(newline="", encoding="utf-8") reader = csv.DictReader(file_handler) for row in reader: if "tested_at" in row: try: row["tested_at"] = datetime.fromisoformat( row["tested_at"] ).astimezone(timezone.utc) except (TypeError, ValueError): row["tested_at"] = datetime.now(timezone.utc) - timedelta( days=365 ) yield row file_handler.close() @DBDatasetBase.execute_if_authorized(None) def get_filtered_content( self, filter_map: dict ) -> Generator[Optional[dict], None, None]: """ Provides a generator which provides the next line to read. :param filter_map: A dictionary representing what we need to filter. :raise TypeError: When the given :code:`filter_map` is not a :py:class:`dict`. """ if not isinstance(filter_map, dict): raise TypeError(f" should be {dict}, {type(filter_map)} given.") for row in self.get_content(): if all(x in row and row[x] == y for x, y in filter_map.items()): yield row def get_filtered_comparision_row(self, row: dict): """ Makes the given row ready for comparison. """ if self.COMPARISON_FIELDS: row = {x: y for x, y in row.items() if x in self.COMPARISON_FIELDS} row.update({x: "" for x in self.COMPARISON_FIELDS if x not in row}) return row return row @DBDatasetBase.ensure_source_file_exists @DBDatasetBase.execute_if_authorized(False) def exists(self, row: dict) -> bool: """ Checks if the given dataset exists in our dataset. :param row: The row or dataset to check. """ if self.remove_unneeded_fields: row = self.get_filtered_row(row) row = self.get_filtered_comparision_row(row) for read_row in self.get_content(): if self.are_equal(read_row, row): return True return False @DBDatasetBase.execute_if_authorized(False) def are_equal(self, read_row: dict, row: dict) -> bool: """ Compares the given :code:`read_row` to the `row`. :param read_row: The row read from the dataset infrastructure. :param row: The row given by the testing infrastructure. """ if self.remove_unneeded_fields: read_row = self.get_filtered_row(read_row) row = self.get_filtered_row(row) read_row = self.get_filtered_comparision_row(read_row) row = self.get_filtered_comparision_row(row) return row.items() <= read_row.items() PyFunceble-4.2.29.dev/PyFunceble/dataset/db_base.py000066400000000000000000000222731467462152100220510ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all datasets which acts as database interface. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from typing import Any, Generator, List, Optional from PyFunceble.dataset.base import DatasetBase class DBDatasetBase(DatasetBase): """ Provides the base of all datasets which acts as database interface. """ STD_REMOVE_UNNEEDED_FIELDS: bool = True STD_AUTHORIZED: bool = False FIELDS: List[str] = [] COMPARISON_FIELDS: List[str] = [] source_file: Optional[str] = None _remove_unneeded_fields: Optional[bool] = True _authorized: Optional[bool] = False def __init__( self, *, authorized: Optional[bool] = None, remove_unneeded_fields: Optional[bool] = None, ) -> None: if authorized is not None: self.set_authorized(authorized) if remove_unneeded_fields is not None: self.set_remove_unneeded_fields(remove_unneeded_fields) self.__post_init__() def __post_init__(self) -> None: """ A method to be called (automatically) after __init__. """ def execute_if_authorized(default: Any = None): # pylint: disable=no-self-argument """ Executes the decorated method only if we are authorized to process. Otherwise, apply the given :code:`default`. """ def inner_metdhod(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.authorized: return func(self, *args, **kwargs) # pylint: disable=not-callable return default return wrapper return inner_metdhod @property def authorized(self) -> Optional[bool]: """ Provides the current state of the :code:`_authorized` attribute. """ return self._authorized @authorized.setter def authorized(self, value: bool) -> None: """ Sets the value of the :code:`_authorized` attribute. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool` """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._authorized = value def set_authorized(self, value: bool) -> "DBDatasetBase": """ Sets the value of the :code:`_authorized` attribute. :param value: The value to set. """ self.authorized = value return self @property def remove_unneeded_fields(self) -> Optional[bool]: """ Provides the current state of the :code:`_remove_unneeded_fields`. """ return self._remove_unneeded_fields @remove_unneeded_fields.setter def remove_unneeded_fields(self, value: bool) -> None: """ Sets the value of the :code:`_remove_unneeded_fields` attribute. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool` """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._remove_unneeded_fields = value def set_remove_unneeded_fields(self, value: bool) -> "DBDatasetBase": """ Sets the value of the :code:`_remove_unneeded_fields` attribute. :param value: The value to set. """ self.remove_unneeded_fields = value return self @execute_if_authorized(dict()) # pylint: disable=use-dict-literal def get_filtered_row(self, row: dict) -> dict: """ Removes all unkowns fields (not declared) from the given row. :param row: The row to work with. """ result = {} for key, value in row.items(): if value is None: value = "" if key in self.FIELDS: result[key] = value for field in self.COMPARISON_FIELDS: if field not in result: result[field] = "" return result def add(self, row: dict) -> "DBDatasetBase": """ Adds the given dataset into the database. :param row: The row or dataset to add. :raise TypeError: When the given :code:`row` is not a :py:class`dict`. """ raise NotImplementedError() def remove(self, row: dict) -> "DBDatasetBase": """ Removes the given dataset from the database. :param row: The row or dataset to remove. :raise TypeError: When the given :code:`row` is not a :py:class`dict`. """ raise NotImplementedError() def update(self, row: dict, *, ignore_if_exist: bool = False) -> "DBDatasetBase": """ Adds the given dataset into the database if it does not exists. Update otherwise. :param row: The row or dataset to manipulate. :param ignore_if_exist: Ignores the insertion/update if the row already exists. :raise TypeError: When the given :code:`row` is not a :py:class`dict`. """ raise NotImplementedError() def get_content(self) -> Generator[Optional[dict], None, None]: """ Provides a generator which provides the next line to read. """ raise NotImplementedError() def cleanup(self) -> "DBDatasetBase": """ Cleanups the dataset. """ raise NotImplementedError() @execute_if_authorized(None) def get_filtered_content( self, filter_map: dict ) -> Generator[Optional[dict], None, None]: """ Provides a generator which provides the next dataset. to read. :param filter_map: A dictionary representing what we need to filter. :raise TypeError: When the given :code:`filter_map` is not a :py:class:`dict`. """ if not isinstance(filter_map, dict): raise TypeError(f" should be {dict}, {type(filter_map)} given.") for row in self.get_content(): for key, value in filter_map.items(): if key not in row: continue if row[key] == value: yield row def exists(self, row: dict) -> bool: """ Checks if the given dataset exists in our dataset. :param row: The row or dataset to add. """ raise NotImplementedError() def are_equal(self, read_row: dict, row: dict) -> bool: """ Compares the given :code:`read_row` to the `row`. :param read_row: The row read from the dataset infrastructure. :param row: The row given by the testing infrastructure. """ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/dataset/iana.py000066400000000000000000000100031467462152100213660ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an interface which let us interact with the IANA database. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from typing import Any, Optional import PyFunceble.storage from PyFunceble.dataset.base import DatasetBase from PyFunceble.downloader.iana import IANADownloader class IanaDataset(DatasetBase): """ Provides the dataset handler for the IANA dataset. """ STORAGE_INDEX: str = "IANA" DOWNLOADER: IANADownloader = IANADownloader() def __init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.IANA_DUMP_FILENAME ) def __contains__(self, value: Any) -> bool: if value.startswith("."): value = value[1:] return value in self.get_content() def __getattr__(self, value: Any) -> Optional[str]: if value.startswith("."): value = value[1:] if value in self: return self.get_content()[value] return None def __getitem__(self, value: Any) -> Optional[str]: return self.__getattr__(value) def is_extension(self, extension: str) -> bool: """ Checks if the given extension is registered. :raise TypeError: When :code:`extension` is not a :py:class:`str`. """ if not isinstance(extension, str): raise TypeError(f" should be {str}, {type(extension)} given.") return extension in self def get_whois_server(self, extension: str) -> Optional[str]: """ Provides the WHOIS server of the given dataset. """ if self.is_extension(extension): return self[extension] return None PyFunceble-4.2.29.dev/PyFunceble/dataset/inactive/000077500000000000000000000000001467462152100217145ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/dataset/inactive/__init__.py000066400000000000000000000046461467462152100240370ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the inactive database logic(s). Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/dataset/inactive/base.py000066400000000000000000000062521467462152100232050ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all Inactive related dataset. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Generator, List, Optional, Tuple from PyFunceble.dataset.db_base import DBDatasetBase class InactiveDatasetBase(DBDatasetBase): """ Provides the base of all inactive related interface. """ FIELDS: List[str] = [ "idna_subject", "checker_type", "destination", "tested_at", ] COMPARISON_FIELDS: List[str] = [ "idna_subject", "checker_type", "destination", ] @DBDatasetBase.execute_if_authorized(None) def get_to_retest( self, destination: str, checker_type: str, *, min_days: Optional[int] = 1 ) -> Generator[Tuple[str, str, Optional[int]], dict, None]: """ Provides the next row to restest. """ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/dataset/inactive/csv.py000066400000000000000000000100011467462152100230510ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the interface for the inactive db CSV management. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from datetime import datetime, timedelta, timezone from typing import Generator, Optional, Tuple import PyFunceble.cli.storage import PyFunceble.storage from PyFunceble.dataset.csv_base import CSVDatasetBase from PyFunceble.dataset.inactive.base import InactiveDatasetBase class CSVInactiveDataset(CSVDatasetBase, InactiveDatasetBase): """ Provides the interface for the management of the inactive CSV file. """ def __post_init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.INACTIVE_DB_FILE ) return super().__post_init__() @CSVDatasetBase.execute_if_authorized(None) def get_to_retest( self, destination: str, checker_type: str, *, min_days: Optional[int] ) -> Generator[Tuple[str, str, Optional[int]], dict, None]: days_ago = datetime.now(timezone.utc) - timedelta(days=min_days) for dataset in self.get_filtered_content( {"destination": destination, "checker_type": checker_type} ): if not isinstance(dataset["tested_at"], datetime): try: date_of_inclusion = datetime.fromisoformat( dataset["tested_at"] ).astimezone(timezone.utc) except (TypeError, ValueError): date_of_inclusion = datetime.now(timezone.utc) - timedelta(days=365) else: date_of_inclusion = dataset["tested_at"] if date_of_inclusion > days_ago: continue yield dataset PyFunceble-4.2.29.dev/PyFunceble/dataset/inactive/sql.py000066400000000000000000000072201467462152100230660ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the interface for the inactive DB (mariadb) management. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from datetime import datetime, timedelta, timezone from typing import Generator, Optional, Tuple from PyFunceble.database.sqlalchemy.all_schemas import Inactive from PyFunceble.dataset.inactive.base import InactiveDatasetBase from PyFunceble.dataset.sql_base import SQLDBDatasetBase class SQLDBInactiveDataset(SQLDBDatasetBase, InactiveDatasetBase): """ Provides tht interface for the management and the WHOIS dataset under mariadb. """ ORM_OBJ: Inactive = Inactive @SQLDBDatasetBase.execute_if_authorized(None) @SQLDBDatasetBase.ensure_orm_obj_is_given def get_to_retest( self, destination: str, checker_type: str, *, min_days: Optional[int] ) -> Generator[Tuple[str, str, Optional[int]], dict, None]: days_ago = datetime.now(timezone.utc) - timedelta(days=min_days) result = ( self.db_session.query(self.ORM_OBJ) .filter(self.ORM_OBJ.destination == destination) .filter(self.ORM_OBJ.checker_type == checker_type) .filter(self.ORM_OBJ.tested_at < days_ago) ) for row in result: if not hasattr(row, "tested_at"): # This is just a safety. continue yield row.to_dict() PyFunceble-4.2.29.dev/PyFunceble/dataset/ipv4_reputation.py000066400000000000000000000077521467462152100236330ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an interface which let us interact with the IPv4 reputation database. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from typing import Any, Optional import PyFunceble.storage from PyFunceble.dataset.base import DatasetBase from PyFunceble.downloader.ipv4_reputation import IPV4ReputationDownloader from PyFunceble.helpers.file import FileHelper class IPV4ReputationDataset(DatasetBase): """ Provides the interface for the lookup of the IPv4 reputation. """ STORAGE_INDEX: Optional[str] = None DOWNLOADER: IPV4ReputationDownloader = IPV4ReputationDownloader() def __init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.IPV4_REPUTATION_FILENAME, ) def __contains__(self, value: Any) -> bool: with self.get_content() as file_stream: for line in file_stream: line = line.strip() if line.startswith(f"{value}#"): return True return False @DatasetBase.ensure_source_file_exists def get_content(self) -> open: """ Provides a file handler which does let you read the content line by line. :raise FileNotFoundError: When the declared file does not exists. """ file_helper = FileHelper(self.source_file) if not file_helper.exists() and bool(self.DOWNLOADER): # pragma: no cover ## pragma reason: Safety. self.DOWNLOADER.start() if not file_helper.exists(): raise FileNotFoundError(file_helper.path) return file_helper.open("r", encoding="utf-8") PyFunceble-4.2.29.dev/PyFunceble/dataset/public_suffix.py000066400000000000000000000101171467462152100233260ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an interface which let us interact with the Public Suffix List. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from typing import Any, List import PyFunceble.storage from PyFunceble.dataset.base import DatasetBase from PyFunceble.downloader.public_suffix import PublicSuffixDownloader class PublicSuffixDataset(DatasetBase): """ Provides the dataset handler for the Public Suffix List dataset. """ STORAGE_INDEX: str = "PUBLIC_SUFFIX" DOWNLOADER: PublicSuffixDownloader = PublicSuffixDownloader() def __init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.PUBLIC_SUFFIX_DUMP_FILENAME, ) def __contains__(self, value: Any) -> bool: if value.startswith("."): value = value[1:] return value in self.get_content() def __getattr__(self, value: Any) -> List[str]: if value.startswith("."): value = value[1:] if value in self: return self.get_content()[value] return [] def __getitem__(self, value: Any) -> List[str]: return self.__getattr__(value) def is_extension(self, extension: str) -> bool: """ Checks if the given extension is registered. :raise TypeError: When :code:`extension` is not a :py:class:`str`. """ if not isinstance(extension, str): raise TypeError(f" should be {str}, {type(extension)} given.") return extension in self def get_available_suffix(self, extension: str) -> List[str]: """ Provides the available suffix for the extension. """ if self.is_extension(extension): return self[extension] return [] PyFunceble-4.2.29.dev/PyFunceble/dataset/sql_base.py000066400000000000000000000244611467462152100222640ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all Mariadb stored datasets. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from datetime import datetime, timezone from typing import Any, Generator, Optional import sqlalchemy.exc from sqlalchemy.orm import Session import PyFunceble.cli.factory import PyFunceble.sessions from PyFunceble.dataset.db_base import DBDatasetBase class SQLDBDatasetBase(DBDatasetBase): """ Provides the base of all SQLDB stored dataset. """ STD_KEEP_SESSION_OPEN: bool = False ORM_OBJ = None db_session: Optional[Session] = None def __init__( self, *, authorized: Optional[bool] = None, remove_unneeded_fields: Optional[bool] = None, db_session: Optional[Session] = None, ) -> None: self.db_session = db_session super().__init__( authorized=authorized, remove_unneeded_fields=remove_unneeded_fields ) def __contains__(self, value: str) -> bool: raise NotImplementedError() def __getitem__(self, value: Any) -> Any: raise KeyError(value) def ensure_orm_obj_is_given(func): # pylint: disable=no-self-argument """ Ensures that the ORM object is given before launching the decorated method. :raise RuntimeError: When :code:`ORM_OBJ` is not declared. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.ORM_OBJ is None: raise RuntimeError(" not given.") return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @DBDatasetBase.execute_if_authorized(None) def get_content(self) -> Generator[dict, None, None]: """ Provides a generator which provides the next dataset to read. """ for row in self.db_session.query(self.ORM_OBJ): row = row.to_dict() yield row @DBDatasetBase.execute_if_authorized(None) def update(self, row, *, ignore_if_exist: bool = False) -> "SQLDBDatasetBase": """ Adds the given dataset into the database if it does not exists. Update otherwise. .. note:: This should be the preferred method for introduction of new dataset. :raise TypeError: When the given :code:`row` is not a :py:class:`dict` or sqlalchemy schema. """ if not isinstance(row, (dict, type(self.ORM_OBJ))): raise TypeError( f" should be {dict} or {self.ORM_OBJ}, {type(row)} given." ) PyFunceble.facility.Logger.info("Started to update row.") if isinstance(row, type(self.ORM_OBJ)): row = row.to_dict() if "id" in row: self.db_session.execute( self.ORM_OBJ.__table__.update().where(self.ORM_OBJ.id == row["id"]), row, ) self.db_session.commit() else: existing_row_id = self.get_existing_row_id(row) if existing_row_id is not None: if not ignore_if_exist: row["id"] = existing_row_id self.update(row, ignore_if_exist=ignore_if_exist) else: self.add(row) PyFunceble.facility.Logger.debug("Updated row:\n%r", row) PyFunceble.facility.Logger.info("Finished to update row.") return self @DBDatasetBase.execute_if_authorized(None) @ensure_orm_obj_is_given def remove(self, row) -> "SQLDBDatasetBase": """ Removes the given dataset from the database. :param row: The row or dataset to check. :raise TypeError: When the given :code:`row` is not a :py:class:`dict` or sqlalchemy schema. """ if not isinstance(row, (dict, type(self.ORM_OBJ))): raise TypeError( f" should be {dict} or {self.ORM_OBJ}, {type(row)} given." ) PyFunceble.facility.Logger.info("Started to remove row.") if not isinstance(row, type(self.ORM_OBJ)): row_id = self.get_existing_row_id(row) if row_id is not None: self.db_session.query(self.ORM_OBJ).filter( self.ORM_OBJ == row_id ).delete() self.db_session.commit() else: self.db_session.delete(row) self.db_session.commit() PyFunceble.facility.Logger.debug("Removed row:\n%r", row) PyFunceble.facility.Logger.info("Finished to remove row.") return self @DBDatasetBase.execute_if_authorized(False) @ensure_orm_obj_is_given def exists(self, row) -> bool: """ Checks if the given dataset exists in our dataset. :param row: The row or dataset to check. :raise TypeError: When the given :code:`row` is not a :py:class:`dict` or sqlalchemy schema. """ return self.get_existing_row_id(row) is not None @DBDatasetBase.execute_if_authorized(None) @ensure_orm_obj_is_given def get_existing_row_id(self, row): """ Returns the ID of the existing row. :param row: The row or dataset to check, """ if not isinstance(row, (dict, type(self.ORM_OBJ))): raise TypeError( f" should be {dict} or {self.ORM_OBJ}, {type(row)} given." ) if isinstance(row, type(self.ORM_OBJ)): row = row.to_dict() result = self.db_session.query(self.ORM_OBJ.id) for field in self.COMPARISON_FIELDS: result = result.filter(getattr(self.ORM_OBJ, field) == row[field]) result = result.first() if result is not None: return result.id return None @DBDatasetBase.execute_if_authorized(None) @ensure_orm_obj_is_given def get_existing_row(self, row): """ Returns the matching row. :param row: The row or dataset to check, """ if not isinstance(row, (dict, type(self.ORM_OBJ))): raise TypeError( f" should be {dict} or {self.ORM_OBJ}, {type(row)} given." ) if isinstance(row, type(self.ORM_OBJ)): row = row.to_dict() result = self.db_session.query(self.ORM_OBJ) for field in self.COMPARISON_FIELDS: result = result.filter(getattr(self.ORM_OBJ, field) == row[field]) return result.first() @DBDatasetBase.execute_if_authorized(None) @ensure_orm_obj_is_given def add(self, row) -> "SQLDBDatasetBase": """ Adds the given dataset into the database. :param row: The row or dataset to add. :raise TypeError: When the given :code:`row` is not a :py:class:`dict` or sqlalchemy schema. """ if not isinstance(row, (dict, type(self.ORM_OBJ))): raise TypeError( f" should be {dict} or {self.ORM_OBJ}, {type(row)} given." ) PyFunceble.facility.Logger.info("Started to add row.") if isinstance(row, type(self.ORM_OBJ)): row = row.to_dict() try: self.db_session.execute(self.ORM_OBJ.__table__.insert(), row) self.db_session.commit() except sqlalchemy.exc.DataError as exception: if "expiration_date" not in row and "epoch" not in row: raise exception y2k38_limit = datetime(2037, 12, 31, 0, 0) new_date = datetime.fromtimestamp(float(row["epoch"]), timezone.utc) new_date -= new_date - y2k38_limit row["epoch"] = new_date.timestamp() row["expiration_date"] = new_date.strftime("%d-%b-%Y") self.db_session.execute(self.ORM_OBJ.__table__.insert(), row) self.db_session.commit() PyFunceble.facility.Logger.debug("Added row:\n%r", row) PyFunceble.facility.Logger.info("Finished to add row.") return self PyFunceble-4.2.29.dev/PyFunceble/dataset/user_agent.py000066400000000000000000000175461467462152100226350ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an interface which let us interact with the Public Suffix List. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import secrets from typing import Any from warnings import warn import PyFunceble.storage from PyFunceble.dataset.base import DatasetBase from PyFunceble.downloader.user_agents import UserAgentsDownloader class UserAgentDataset(DatasetBase): """ Provides the dataset and infrastructure for the User Agent navigation """ STORAGE_INDEX: str = "USER_AGENTS" DOWNLOADER: UserAgentsDownloader = UserAgentsDownloader() preferred_browser: str = "chrome" preferred_platform: str = "linux" def __init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.USER_AGENT_FILENAME, ) def __contains__(self, value: Any) -> bool: content = self.get_content() if "@modern" in content: return value in self.get_content()["@modern"] return value in self.get_content() def __getattr__(self, value: Any) -> dict: if value in self: content = self.get_content() if "@modern" in content: return self.get_content()["@modern"][value] return self.get_content()[value] return dict() # pylint: disable=use-dict-literal def __getitem__(self, value: Any) -> dict: return self.__getattr__(value) def set_preferred( self, browser_short_name: str, platform: str ) -> "UserAgentDataset": """ Sets the preferred browser to work with. :param browser_short_name: The name of the browser to select. :pram platform: The name of the platform to select. :raise TypeError: When the given :code:`name` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is not supported. """ if not self.is_supported(browser_short_name, platform): raise ValueError( f"The given name ({browser_short_name!r}) or platform " f"({platform!r}) is not supported." ) self.preferred_browser = browser_short_name.lower() self.preferred_platform = platform.lower() return self # @deprecated("TODO: Soon we should be able to do this...") def set_prefered( self, browser_short_name: str, platform: str ) -> "UserAgentDataset": """ Sets the preferred browser to work with. :param browser_short_name: The name of the browser to select. :pram platform: The name of the platform to select. :raise TypeError: When the given :code:`name` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is not supported. """ warn( "The set_prefered() method is deprecated and will be removed in future " " releases. Please consider using the set_preferred() method instead.", DeprecationWarning, stacklevel=2, ) return self.set_preferred(browser_short_name, platform) def is_supported_browser(self, browser_short_name: str) -> bool: """ Checks if the given browser is supported. :raise TypeError: When :code:`browser_short_name` is not a :py:class:`str`. """ if not isinstance(browser_short_name, str): raise TypeError( f" should be {str}, " f"{type(browser_short_name)} given." ) return bool(browser_short_name.lower() in self) and bool( self[browser_short_name.lower()] ) def is_supported(self, browser_short_name: str, platform: str) -> bool: """ Checks if the given browser and platform is supported. :param browser_short_name: The short name of the browser. :param platform: The platform name. :raise TypeError: When :code:`browser_short_name` or :code:`platform` are not :py:class:`str`. """ if not isinstance(browser_short_name, str): raise TypeError( f" should be {str}, " f"{type(browser_short_name)} given." ) if not isinstance(platform, str): raise TypeError(f" should be {str}, {type(platform)} given.") return ( self.is_supported_browser(browser_short_name) and bool(platform.lower() in self[browser_short_name.lower()]) and bool(self[browser_short_name.lower()][platform.lower()]) ) def get_latest(self) -> str: """ Provides the latest user agent for the given platform. Side Effect: It tries to get the platform and browser from the configuration (if exists). """ if PyFunceble.storage.CONFIGURATION: if ( PyFunceble.storage.CONFIGURATION.user_agent and PyFunceble.storage.CONFIGURATION.user_agent.custom ): return PyFunceble.storage.CONFIGURATION.user_agent.custom self.set_preferred( PyFunceble.storage.CONFIGURATION.user_agent.browser, PyFunceble.storage.CONFIGURATION.user_agent.platform, ) result = self[self.preferred_browser][self.preferred_platform] if isinstance(result, (list, tuple)): return secrets.choice(result) return result PyFunceble-4.2.29.dev/PyFunceble/dataset/whois/000077500000000000000000000000001467462152100212435ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/dataset/whois/__init__.py000066400000000000000000000046431467462152100233630ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the whois database logic(s). Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/dataset/whois/base.py000066400000000000000000000077671467462152100225500ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all WHOIS related dataset. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from datetime import datetime, timezone from typing import List, Union from PyFunceble.database.sqlalchemy.all_schemas import WhoisRecord from PyFunceble.dataset.db_base import DBDatasetBase class WhoisDatasetBase(DBDatasetBase): """ Provides the base of all Whois related interface. """ FIELDS: List[str] = [ "subject", "idna_subject", "expiration_date", "epoch", "registrar", ] COMPARISON_FIELDS: List[str] = ["subject", "idna_subject"] @staticmethod def is_expired(row: Union[dict, WhoisRecord]) -> bool: """ Given a row, we look if the row is expired. """ if isinstance(row, WhoisRecord): to_check = row.epoch elif "epoch" in row: to_check = row["epoch"] else: return True return datetime.now(timezone.utc) > datetime.fromtimestamp( float(to_check), timezone.utc ) @DBDatasetBase.execute_if_authorized(None) def get_filtered_row(self, row: Union[dict, WhoisRecord]) -> dict: """ Removes all unkowns fields (not declared) from the given row. :param row: The row to work with. """ if isinstance(row, WhoisDatasetBase): row = row.to_dict() result = super().get_filtered_row(row) if "epoch" in result and isinstance(result["epoch"], float): # We do this here because we have to convert to a string in # order to be able to write into the CSV file. result["epoch"] = str(result["epoch"]) return result PyFunceble-4.2.29.dev/PyFunceble/dataset/whois/csv.py000066400000000000000000000137731467462152100224230ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the interface for the WHOIS DB CSV management. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from typing import Any, Generator, Optional import PyFunceble.cli.storage import PyFunceble.storage from PyFunceble.dataset.csv_base import CSVDatasetBase from PyFunceble.dataset.whois.base import WhoisDatasetBase class CSVWhoisDataset(CSVDatasetBase, WhoisDatasetBase): """ Provides the interface for the management of the WHOIS (db) CSV file. """ def __post_init__(self) -> None: self.source_file = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.WHOIS_DB_FILE ) return super().__post_init__() def __contains__(self, value: str) -> bool: for row in self.get_content(): try: if value in (row["subject"], row["idna_subject"]): return True except KeyError: break return False def __getitem__(self, value: Any) -> Optional[dict]: try: for row in self.get_content(): if value in (row["subject"], row["idna_subject"]): return row except TypeError: pass return None @CSVDatasetBase.execute_if_authorized(None) def get_content(self) -> Generator[Optional[dict], None, None]: """ Provides a generator which provides the next line to read. """ for row in super().get_content(): try: row["epoch"] = float(row["epoch"]) except (TypeError, ValueError): continue yield row @CSVDatasetBase.execute_if_authorized(None) def update(self, row: dict, *, ignore_if_exist: bool = False) -> "CSVWhoisDataset": """ Adds the given dataset into the database if it does not exists. Update otherwise. ..note:: This should be the prefered method for introduction of new dataset. ..warning:: This method do nothing if the row is expired. :param row: The row or dataset to manipulate. :param ignore_if_exist: Ignores the insertion/update if the row already exists. :raise TypeError: When the given :code:`row` is not a :py:class`dict`. """ if not isinstance(row, dict): raise TypeError(f" should be {dict}, {type(row)} given.") if not self.is_expired(row): if self.exists(row): if not ignore_if_exist and self[row["subject"]] != row: self.remove(row) self.add(row) else: self.add(row) return self @CSVDatasetBase.execute_if_authorized(None) def remove(self, row: dict) -> "CSVDatasetBase": """ Removes the given dataset from the CSV file. :param row: The row or dataset to add. :raise TypeError: When the given :code:`row` is not a :py:class`dict`. """ # If we don't do this, the comparison will fail. # # We don't want to overwrite the whole (remove) method just for what # we need. previous_remove_uneeded_fields = self.remove_unneeded_fields self.set_remove_unneeded_fields(False) super().remove(row) self.set_remove_unneeded_fields(previous_remove_uneeded_fields) return self def cleanup(self) -> "CSVWhoisDataset": """ Cleanups the dataset. Meaning that we delete every entries which are in the past. """ for row in self.get_content(): if self.is_expired(row): self.remove(row) return self PyFunceble-4.2.29.dev/PyFunceble/dataset/whois/sql.py000066400000000000000000000141721467462152100224210ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the interface for the WHOIS DB (sql) management. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from datetime import datetime, timezone from typing import Any, Generator, Optional, Union import sqlalchemy from sqlalchemy.exc import ProgrammingError import PyFunceble.cli.factory import PyFunceble.cli.storage import PyFunceble.facility import PyFunceble.sessions import PyFunceble.storage from PyFunceble.database.sqlalchemy.all_schemas import WhoisRecord from PyFunceble.dataset.sql_base import SQLDBDatasetBase from PyFunceble.dataset.whois.base import WhoisDatasetBase class SQLDBWhoisDataset(SQLDBDatasetBase, WhoisDatasetBase): """ Provides the interface for the management of the WHOIS database under (mariadb). """ ORM_OBJ: WhoisRecord = WhoisRecord @SQLDBDatasetBase.execute_if_authorized(None) def __contains__(self, value: str) -> bool: try: return ( self.db_session.query(self.ORM_OBJ) .filter( sqlalchemy.or_( self.ORM_OBJ.subject == value, self.ORM_OBJ.idna_subject == value, ) ) .first() is not None ) except ProgrammingError: return None @SQLDBDatasetBase.execute_if_authorized(None) def __getitem__(self, value: Any) -> Optional[WhoisRecord]: try: return ( self.db_session.query(self.ORM_OBJ) .filter( sqlalchemy.or_( self.ORM_OBJ.subject == value, self.ORM_OBJ.idna_subject == value, ) ) .first() ) except ProgrammingError: return None @SQLDBDatasetBase.execute_if_authorized(None) def get_content(self) -> Generator[dict, None, None]: """ Provides a generator which provides the next dataset to read. """ for row in super().get_content(): row["epoch"] = float(row["epoch"]) yield row @SQLDBDatasetBase.execute_if_authorized(None) def update( self, row: Union[dict, WhoisRecord], *, ignore_if_exist: bool = False ) -> "SQLDBWhoisDataset": """ Adds the given dataset into the database if it does not exists. Update otherwise. ..note:: This should be the prefered method for introduction of new dataset. ..warning:: This method do nothing if the row is expired. :param row: The row or dataset to manipulate. :raise TypeError: When the given :code:`row` is not a :py:class`dict`. """ if not isinstance(row, (dict, type(self.ORM_OBJ))): raise TypeError( f" should be {dict} or {self.ORM_OBJ}, {type(row)} given." ) if not self.is_expired(row): try: super().update(row, ignore_if_exist=ignore_if_exist) except ProgrammingError: pass else: PyFunceble.facility.Logger.debug("Expired dataset:\n%r", row) return self @SQLDBDatasetBase.execute_if_authorized(None) def cleanup(self) -> "SQLDBWhoisDataset": """ Cleanups the dataset. Meaning that we delete every entries which are in the past. """ current_timestamp = int(datetime.now(timezone.utc).timestamp()) try: self.db_session.query(self.ORM_OBJ).filter( self.ORM_OBJ.epoch < current_timestamp ).delete(synchronize_session=False) self.db_session.commit() except ProgrammingError: pass PyFunceble.facility.Logger.debug("Deleted all expired WHOIS records") return self PyFunceble-4.2.29.dev/PyFunceble/downloader/000077500000000000000000000000001467462152100206235ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/downloader/__init__.py000066400000000000000000000046011467462152100227350ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides all downloaders. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/downloader/base.py000066400000000000000000000213541467462152100221140ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our downloader. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 datetime import os from typing import Optional import PyFunceble.downloader.exceptions import PyFunceble.exceptions import PyFunceble.storage from PyFunceble.helpers.dict import DictHelper from PyFunceble.helpers.download import DownloadHelper from PyFunceble.helpers.file import FileHelper class DownloaderBase: """ Provides the base of all downloader classes. The interface is actually simple, but the part which may be hard to understand is the "downtime" part. What we do, is that we save the download time inside a JSON file, so this class provides the base around the download mechanism but also the generation or update of that JSON file. """ DOWNTIME_INDEX: Optional[str] = None """ Used to set/track the download time of the current file. """ DOWNLOAD_FREQUENCY: int = 1 """ The download frequency (in day). Example: if 1 is given, it's once every 24 hours. .. warning:: A frequency of :code:`0` or a negative number will force the download every hour. """ all_downtimes: Optional[dict] = {} """ Stores the download time of all files (self managed). """ _destination: Optional[str] = None _download_link: Optional[str] = None dict_helper: DictHelper = DictHelper() def __init__(self) -> None: self.downtimes_file = FileHelper( os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.DOWN_FILENAME ) ) self.all_downtimes.update(self.get_all_downtimes()) @property def authorized(self) -> bool: """ Provides the authorization to start the download. """ raise NotImplementedError() @property def destination(self) -> Optional[str]: """ Provides the current state of the :code:`_destination` attribute. """ return self._destination @destination.setter def destination(self, value: str) -> None: """ Sets the destination. :param value: The value to set. :raise TypeError: When value is not a :py:class:`str`. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") self._destination = value def set_destination(self, value: str) -> "DownloaderBase": """ Sets the destination. :param value: The value to set. """ self.destination = value return self @property def download_link(self) -> Optional[str]: """ Provides the current state of the :code:`_download_link` attribute. """ return self._download_link @download_link.setter def download_link(self, value: str) -> None: """ Sets the link to download. :param value: The value to set. :raise TypeError: When value is not a :py:class:`str`. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") self._download_link = value def set_download_link(self, value: str) -> "DownloaderBase": """ Sets the link to download. :param value: The value to set. """ self.download_link = value return self def get_all_downtimes(self) -> dict: """ Provides the downloadtime of all files. """ return self.dict_helper.from_json_file(self.downtimes_file.path) def is_downtime_set(self) -> bool: """ Checks if the download time of the current object exists. """ return ( self.DOWNTIME_INDEX in self.all_downtimes and self.all_downtimes[self.DOWNTIME_INDEX] and all( x in self.all_downtimes[self.DOWNTIME_INDEX] and self.all_downtimes[self.DOWNTIME_INDEX][x] for x in ["iso", "timestamp"] ) ) def get_current_downtime(self): """ Provides the download times of the current :code:`DOWN_TIME_INDEX`. """ if self.is_downtime_set(): return self.all_downtimes[self.DOWNTIME_INDEX] return None def set_current_downtime(self) -> "DownloaderBase": """ Sets the current datetime into our registry. """ current_datetime = datetime.datetime.now(datetime.timezone.utc) self.all_downtimes[self.DOWNTIME_INDEX] = { "iso": current_datetime.isoformat(), "timestamp": current_datetime.timestamp(), } return self def save_all_downtimes(self) -> None: """ Saves the current state of the all downtimes. """ self.dict_helper.set_subject(self.all_downtimes).to_json_file( self.downtimes_file.path ) def is_last_download_expired(self) -> bool: """ Checks if the last downloaded file is expired (if exists). """ if not FileHelper(self.destination).exists() or not self.is_downtime_set(): return True last_downloaded_time = datetime.datetime.fromtimestamp( self.get_current_downtime()["timestamp"], datetime.timezone.utc ) if ( self.DOWNLOAD_FREQUENCY <= 0 and ( datetime.datetime.now(datetime.timezone.utc) - last_downloaded_time ).seconds < 3600 ): return False if last_downloaded_time + datetime.timedelta( days=self.DOWNLOAD_FREQUENCY ) <= datetime.datetime.now(datetime.timezone.utc): return True return False def start(self) -> None: """ Starts the download process. """ if self.authorized and self.is_last_download_expired(): if not hasattr(self, "destination") or not self.destination: raise PyFunceble.downloader.exceptions.NoDownloadDestinationGiven() if not hasattr(self, "download_link") or not self.download_link: raise PyFunceble.downloader.exceptions.NoDownloadLinkGiven() if DownloadHelper(self.download_link).download_text( destination=self.destination ): self.set_current_downtime() self.save_all_downtimes() PyFunceble-4.2.29.dev/PyFunceble/downloader/exceptions.py000066400000000000000000000056151467462152100233650ustar00rootroot00000000000000# pylint:disable=line-too-long """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the exceptions related to the downloader. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.exceptions class PyFuncebleDownloaderException(PyFunceble.exceptions.PyFuncebleException): """ Describes the downloader (related) exceptions. """ class NoDownloadDestinationGiven(PyFuncebleDownloaderException): """ Describes the fact that the download destination was not declared. """ class NoDownloadLinkGiven(PyFuncebleDownloaderException): """ Describes the fact that no download link was declared. """ PyFunceble-4.2.29.dev/PyFunceble/downloader/iana.py000066400000000000000000000057751467462152100221230ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the downloader of the latest iana database file. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import PyFunceble.storage from PyFunceble.downloader.base import DownloaderBase class IANADownloader(DownloaderBase): """ Provides the downloader of our iana file. """ DOWNTIME_INDEX: str = "iana" DOWNLOAD_FREQUENCY: int = 1 def __init__(self) -> None: self.destination = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.IANA_DUMP_FILENAME, ) self.download_link = PyFunceble.storage.IANA_DUMP_LINK super().__init__() @property def authorized(self) -> bool: return True PyFunceble-4.2.29.dev/PyFunceble/downloader/ipv4_reputation.py000066400000000000000000000061241467462152100243340ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the downloader of the latest user agents database file. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import PyFunceble.storage from PyFunceble.downloader.base import DownloaderBase class IPV4ReputationDownloader(DownloaderBase): """ Provides the downloader of our user agent file. """ DOWNTIME_INDEX: str = "ipv4_reputation" DOWNLOAD_FREQUENCY: int = 1 def __init__(self) -> None: self.destination = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.IPV4_REPUTATION_FILENAME, ) self.download_link = PyFunceble.storage.IPV4_REPUTATION_DUMP_LINK super().__init__() @property def authorized(self) -> bool: # pragma: no cover ## Always True. return True PyFunceble-4.2.29.dev/PyFunceble/downloader/public_suffix.py000066400000000000000000000060371467462152100240450ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the downloader of the latest iana database file. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import PyFunceble.storage from PyFunceble.downloader.base import DownloaderBase class PublicSuffixDownloader(DownloaderBase): """ Provides the downloader of our public suffix file. """ DOWNTIME_INDEX: str = "psl" DOWNLOAD_FREQUENCY: int = 1 def __init__(self) -> None: self.destination = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.PUBLIC_SUFFIX_DUMP_FILENAME, ) self.download_link = PyFunceble.storage.PUBLIC_SUFFIX_DUMP_LINK super().__init__() @property def authorized(self) -> bool: return True PyFunceble-4.2.29.dev/PyFunceble/downloader/user_agents.py000066400000000000000000000060361467462152100235210ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the downloader of the latest user agents database file. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import PyFunceble.storage from PyFunceble.downloader.base import DownloaderBase class UserAgentsDownloader(DownloaderBase): """ Provides the downloader of our user agent file. """ DOWNTIME_INDEX: str = "user_agents" DOWNLOAD_FREQUENCY: int = 1 def __init__(self) -> None: self.destination = os.path.join( PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.USER_AGENT_FILENAME, ) self.download_link = PyFunceble.storage.USER_AGENT_DUMP_LINK super().__init__() @property def authorized(self) -> bool: return True PyFunceble-4.2.29.dev/PyFunceble/exceptions.py000066400000000000000000000053471467462152100212310ustar00rootroot00000000000000# pylint:disable=line-too-long """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our exceptions. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ class PyFuncebleException(Exception): """ Describes our own exceptions. """ class NoInternetConnection(PyFuncebleException): """ Describes a missing connection. """ class PleaseUpdatePyFunceble(PyFuncebleException): """ Describes the impossiblity to continue with an older version. """ PyFunceble-4.2.29.dev/PyFunceble/facility.py000066400000000000000000000051021467462152100206410ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything which we may need while running. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.config.loader import ConfigLoader as config_loader from PyFunceble.logger import Logger as logger ConfigLoader = config_loader() Logger = logger() PyFunceble-4.2.29.dev/PyFunceble/factory.py000066400000000000000000000050201467462152100205030ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything which doesn't get through the door of the facility. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from PyFunceble.query.requests.requester import Requester as requester Requester = requester() PyFunceble-4.2.29.dev/PyFunceble/helpers/000077500000000000000000000000001467462152100201275ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/helpers/__init__.py000066400000000000000000000045751467462152100222530ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/helpers/command.py000066400000000000000000000167161467462152100221320ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the command helpers. This helpers let us run Shell commands. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import subprocess import sys from typing import Generator, Optional, Union class CommandHelper: """ Shell command execution. :param str command: The command to execute. :param str encoding: The encoding to use to decode the shell output. """ _command: Optional[str] = None _encoding: str = "utf-8" def __init__( self, command: Optional[Union[str, list]] = None, *, encoding: Optional[str] = None, ) -> None: if command is not None: self.command = command if encoding is not None: self.encoding = encoding @property def command(self) -> Optional[str]: """ Provides the current state of the :code:`_command` attribute. """ return self._command @command.setter def command(self, value: Union[str, list]) -> None: """ Sets the command to use. :param value: The command to use/execute. :raise TypeError: When the value is not a :py:class:`list` or :py:class:`str` """ if not isinstance(value, (str, list)): raise TypeError( f" should be {str} or {list}, " f"{type(value)} given." ) if isinstance(value, list): self._command = " ".join(value) else: self._command = value def set_command(self, value: Union[str, list]) -> "CommandHelper": """ Sets the command to use. :param value: The command to use/execute. """ self.command = value return self @property def encoding(self) -> Optional[str]: """ Provides the current state of the :code:`_encoding` attribute. """ return self._encoding @encoding.setter def encoding(self, value: str) -> None: """ Sets the encoding to use. :param value: The value to set. :raise TypeError: When the value is not a :py:class:`str` """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") self._encoding = value def set_encoding(self, value: str) -> "CommandHelper": """ Sets the encoding to use. :param value: The value to set. """ self.encoding = value return self def _decode_output(self, to_decode: bytes) -> str: """ Decode the output of a shell command in order to be readable. :param bytes to_decode: Output of a command to decode. :return: The decoded output. :rtype: str """ if to_decode: return to_decode.decode(self.encoding) return "" def execute(self, *, raise_on_error: bool = False) -> str: """ Execute the given command. :parma raise_on_error: Raises on error if set to :py:class:`True`. :return: The output of the command. :raise RuntimeError: When the exit code is not equal to 0. """ # We initiate a process and parse the command to it. with subprocess.Popen( self.command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, env=os.environ, ) as process: stdout, stderr = process.communicate() if process.returncode != 0: if raise_on_error: raise RuntimeError(repr(self._decode_output(stderr))) return self._decode_output(stderr) return self._decode_output(stdout) def run(self, rstrip: bool = True) -> Generator[str, None, None]: """ Run the given command and yield each line(s) one by one. .. note:: The difference between this method and :func:`~PyFunceble.helpers.Command.execute` is that :func:`~PyFunceble.helpers.Command.execute` wait for the process to end in order to return its output while this method return each line one by one - as they are outputed. :param bool rstrip: Deactivates the rstrip of the output. """ with subprocess.Popen( self.command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, env=os.environ, ) as process: while True: # Note: we use rstrip() because we are paranoid :-) current_line = process.stdout.readline() if not current_line and process.poll() is not None: break if rstrip: yield self._decode_output(current_line.rstrip()) else: yield self._decode_output(current_line) def run_to_stdout(self) -> None: """ Run the given command and print each line(s) to stdout. """ for line in self.run(rstrip=False): sys.stdout.write(line) PyFunceble-4.2.29.dev/PyFunceble/helpers/dict.py000066400000000000000000000327111467462152100214300ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the dict helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy import json from json import decoder, dump, dumps, loads from typing import Any, List, Optional, Union from yaml import dump as yaml_dump from yaml import safe_load as yaml_load from PyFunceble.helpers.file import FileHelper class DictHelper: """ Simplify some :code:`dict` manipulation. :param dict main: The main :code:`dict` to work with. :raise TypeError: When :code:`main` is not a dict nor a list (tolarated). """ _subject: Optional[Union[Any, dict]] = None def __init__(self, subject: Optional[Union[Any, dict]] = None) -> None: if subject is not None: self.subject = subject @property def subject(self) -> Optional[Union[Any, dict]]: """ Provides the current state of the :code:`_subject` attribute. """ return self._subject @subject.setter def subject(self, value: Any) -> None: """ Sets the subject to work with. :param value: The value to set. """ self._subject = copy.deepcopy(value) def set_subject(self, value: Any) -> "DictHelper": """ Sets the subject to work with. :param value: The value to set. """ self.subject = value return self def has_same_keys_as(self, to_check: dict, loop: bool = False) -> bool: """ Checks if keys are presents in both given :py:class:`dict`. :param to_check: The dict to compare with. :param loop: DO NOT USE, only used to tell us wen to return the list of dataset or the final result. """ result = [] for key, value in to_check.items(): if key in self.subject: if isinstance(value, dict) and isinstance(self.subject[key], dict): result.extend( DictHelper(self.subject[key]).has_same_keys_as(value, loop=True) ) else: result.append(True) else: result.append(False) if loop: return result return False not in result def remove_key( self, key_to_remove: Union[str, List[str]] ) -> Optional[Union[Any, dict]]: """ Remove a given key from a given dictionary. :param key_to_remove: The key(s) to delete. :return: The dict without the given key(s). """ if isinstance(self.subject, dict): if isinstance(key_to_remove, list): for key in key_to_remove: self.remove_key(key) else: try: del self.subject[key_to_remove] except KeyError: pass return self.subject def rename_key(self, key_to_rename: dict, strict: bool = True) -> dict: """ Rename the given keys from the given dictionary. :param key_to_rename: The key(s) to rename. Expected format: :code:`{old:new}` :param strict: Tell us if we have to rename the exact index or the index which looks like the given key(s) :return: The well formatted dict. """ if isinstance(self.subject, dict) and isinstance(key_to_rename, dict): for old, new in key_to_rename.items(): if strict: if old in self.subject: self.subject[new] = self.subject.pop(old) else: to_rename = {} for index in self.subject: if old in index: to_rename.update({index: new[:-1] + index.split(old)[-1]}) self.subject = DictHelper(self.subject).rename_key(to_rename, True) return self.subject def to_json_file( self, file_path: str, ensure_ascii: bool = False, indent: int = 4, sort_keys: bool = True, encoding: str = "utf-8", own_class: Optional[json.JSONEncoder] = None, ) -> None: """ Converts the given :code:`dict` to JSON and save the result into a given file path. :param file_path: The file path. :param ensure_ascii: Avoids unicode. :param indent: The indentation to apply. :param sortkeys: Sorts the keys. :param encoding: The encoding to apply. :param own_class: A class to use for the conversion to json. """ with open(file_path, "w", encoding=encoding) as file_stream: dump( self.subject, file_stream, ensure_ascii=ensure_ascii, indent=indent, sort_keys=sort_keys, cls=own_class, ) @staticmethod def from_json_file( file_path: str, encoding: str = "utf-8", return_dict_on_error: bool = True ) -> Optional[Union[List[Any], dict]]: """ Reads the given file path and convert it's content to dict/list (tolarated). :param file_path: The file path. :param return_dict_on_error: Return a dict instead of a NoneType. :parma encoding: The encoding to use. """ try: return loads(FileHelper(path=file_path).read(encoding=encoding)) except (decoder.JSONDecodeError, TypeError): return None if not return_dict_on_error else {} def to_json( self, ensure_ascii: bool = False, indent: int = 4, sort_keys: bool = True, own_class: Optional[json.JSONEncoder] = None, ) -> str: """ Converts a given dict to JSON and return the json string. :param ensure_ascii: Avoids unicode. :param indent: The indentation to apply. :param sort_keys: Sort the keys. :param own_class: A class to use for the conversion to json. """ return dumps( self.subject, ensure_ascii=ensure_ascii, indent=indent, sort_keys=sort_keys, cls=own_class, ) @staticmethod def from_json( json_str: str, return_dict_on_error: bool = True ) -> Optional[Union[List[Any], dict]]: """ Converts a given JSON string to dict/list. :param json_str: The JSON string ot convert. :param return_dict_on_error: Returns a :py:class:`dict` instead of a :py:class:`None`. """ try: return loads(json_str) except (decoder.JSONDecodeError, TypeError): return None if not return_dict_on_error else {} @staticmethod def from_yaml_file( file_path: str, encoding: str = "utf-8" ) -> Union[List[Any], dict]: """ Converts a given YAML formatted file, into dict/list. :param file_path: The file path. :param encoding: The encoding to use. """ with open(file_path, "r", encoding=encoding) as file_stream: data = yaml_load(file_stream) return data def to_yaml_file( self, file_path: str, encoding: str = "utf-8", default_flow_style: bool = False, indent: int = 4, allow_unicode: bool = True, sort_keys: bool = True, ) -> None: """ Converts the given dict/list to YAML and save the result into a file. :param file_path: The file path. :param encoding: The encoding. :param default_flow_style: Uses the default flow style. :param indent: The indentation to apply. :param allow_unicode: Allows the decoding of unicode chars. :param sort_keys: Sorts the keys. """ with open(file_path, "w", encoding=encoding) as file_stream: yaml_dump( self.subject, stream=file_stream, default_flow_style=default_flow_style, indent=indent, allow_unicode=allow_unicode, encoding=encoding, sort_keys=sort_keys, ) @staticmethod def from_yaml(yaml_str) -> Union[List[Any], dict]: """ Converts the given YAML string to dict/list. :param str yaml_str: The YAML string to convert. """ return yaml_load(yaml_str) def to_yaml( self, encoding: str = "utf-8", default_flow_style: bool = False, indent: int = 4, allow_unicode: bool = True, sort_keys: bool = True, ) -> str: """ Converts the given dict/list to the YAML format and return the result. :param str encoding: The encoding to use. :param bool default_flow_style: Uses the default flow style. :param int indent: The indentation to apply. :param bool allow_unicode: Allows the decoding of unicode chars. :param bool sort_keys: Sors the keys. :rtype: dict|list """ return yaml_dump( self.subject, default_flow_style=default_flow_style, indent=indent, allow_unicode=allow_unicode, encoding=encoding, sort_keys=sort_keys, ).decode() def flatten( self, *, separator: str = ".", previous: Optional[str] = None, data: Optional[Any] = None, ) -> dict: """ Flatten the current dictionnary. :param separator: The separator to apply. :param previous: The previous key we are working with. :param data: The data to work with. If not given, we fallback to :code:`self.subject`. """ if data is None: data = self.subject result = {} if isinstance(data, dict): for key, value in data.items(): for yek, eulav in ( DictHelper(value).flatten(separator=separator, previous=key).items() ): if previous is not None: result[f"{previous}{separator}{yek}"] = eulav else: result[yek] = eulav else: if previous: result[previous] = data else: result[separator] = data return result def unflatten(self, *, separator: str = ".", data: Optional[Any] = None): """ Unflatten a previously flatten dictionnary. :param separator: The separator to split. """ if data is None: data = self.subject result = {} for key, value in data.items(): local_result = result if separator in key: splitted_sep = key.replace(separator + separator, separator).split( separator ) for yek in splitted_sep[:-1]: if yek not in local_result: local_result[yek] = {} local_result = local_result[yek] local_result[splitted_sep[-1]] = value else: local_result[key] = value return result PyFunceble-4.2.29.dev/PyFunceble/helpers/directory.py000066400000000000000000000135471467462152100225170ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the directory helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import shutil from typing import List, Optional from PyFunceble.helpers.list import ListHelper class DirectoryHelper: """ Simplify the directories manipulation. :param str dir_path the path to work with. """ _path: Optional[str] = None def __init__(self, path: Optional[str] = None) -> None: if path is not None: self.path = path @property def path(self) -> Optional[str]: """ Provides the current state of the :code:`_path` attribute. """ return self._path @path.setter def path(self, value: str) -> None: """ Sets the directory path to work with. :param value: The path to set. :raise TypeError: When :code:`value` is not a :py:class:`str`. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") self._path = value def set_path(self, value: str) -> "DirectoryHelper": """ Sets the directory path to work with. :param value: The path to set. """ self.path = value return self @staticmethod def get_current(*, with_end_sep: bool = False) -> str: """ Returns the current directory path. :param bool with_end_sep: Add a directory separator at the end. """ if with_end_sep: return os.getcwd() + os.sep return os.getcwd() @property def realpath(self) -> str: """ Returns the real path of the current path. """ return os.path.realpath(self.path) def join_path(self, *args) -> str: """ Joins the given arguments with the given path. """ return os.path.join(self.path, *args) def exists(self) -> bool: """ Checks if the given directory exists. """ return os.path.isdir(self.path) def create(self) -> "DirectoryHelper": """ Creates the given directory path. :return: The output of :code:`self.exists` after the directory creation. """ if self.path and not self.exists(): os.makedirs(self.path, exist_ok=True) return self def delete(self) -> "DirectoryHelper": """ Deletes the given directory path. :return: :code:`not self.exists` after the directory deletion. """ if self.exists(): shutil.rmtree(self.path) return self def list_all_subdirectories(self) -> List[str]: """ Provides the list of all subdirectories of the current path. """ result = [] if self.exists(): for root, directories, _ in os.walk(self.path): for directory in directories: result.append(os.path.join(root, directory)) return ListHelper(result).remove_duplicates().sort().subject def list_all_files(self) -> List[str]: """ Lists all files of the current path. """ result = [] if self.exists(): for directory in self.list_all_subdirectories(): for element in os.listdir(directory): possible_element = os.path.join(directory, element) if not os.path.isfile(possible_element): continue result.append(possible_element) return ListHelper(result).sort().subject PyFunceble-4.2.29.dev/PyFunceble/helpers/download.py000066400000000000000000000164651467462152100223240ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the download helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry import PyFunceble.helpers.exceptions from PyFunceble.helpers.file import FileHelper class DownloadHelper: """ Simplification of the downloads. :param str url: :param int retry: The number of time we have to retry before raising an exception. """ _url: Optional[str] = None _certificate_validation: bool = True _retries: int = 3 def __init__( self, url: Optional[str] = None, *, certificate_validation: bool = True, retries: int = 3, ) -> None: if url: self.url = url if certificate_validation: self.certificate_validation = certificate_validation if retries: self.retries = retries @property def url(self) -> Optional[str]: """ Provides the current state of the :code:`_url` attribute. """ return self._url @url.setter def url(self, value: str) -> None: """ Sets the url to work with. :param value: The URL to set. :raise TypeError: When :code:`value` is not a :py:class:`str`. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") self._url = value def set_url(self, value: str) -> "DownloadHelper": """ Sets the url to work with. :param value: The URL to set. """ self.url = value return self @property def certificate_validation(self) -> bool: """ Provides the current state of the :code:`certificate_validation` attribute. """ return self._certificate_validation @certificate_validation.setter def certificate_validation(self, value: bool) -> None: """ Sets the value of the certificate validation. :param value: The value to set. :raise TypeError: When :code:`value` is not a :py:class:`bool` """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._certificate_validation = value def set_certificate_validation(self, value: bool) -> "DownloadHelper": """ Sets the value of the certificate validation. :param value: The value to set. """ self.certificate_validation = value return self @property def retries(self) -> int: """ Provides the current state of the :code:`_retries` attributes. """ return self._retries @retries.setter def retries(self, value: int) -> None: """ Sets the number of retries we are allowed to perform before raising an exception. :param value: The number of retry to apply.i :raise TypeError: When :code:`value` is not a :py:class:`int`. :raise ValueError: When :code:`value` is lower than :code:`0`. """ if not isinstance(value, int): raise TypeError(f" should be {int}, {type(value)} given.") if value <= 0: raise ValueError(" should greater than zero.") self._retries = value def set_retries(self, value: int) -> "DownloadHelper": """ Sets the number of retries we are allowed to perform before raising an exception. :param value: The number of retry to apply.i """ self.retries = value return self def download_text(self, *, destination: Optional[str] = None) -> str: """ Download the body of the set url. .. note:: if :code:`destination` is set to :code:`None`, we only return the output. Otherwise, we save the output into the given destination, but we also return the output. :param destination: The download destination. :raise UnableToDownload: When could not unable to download the URL. """ session = requests.Session() retries = Retry(total=self.retries, backoff_factor=3) adapter = HTTPAdapter(max_retries=retries) session.mount("http://", adapter) session.mount("https://", adapter) req = session.get(self.url, verify=self.certificate_validation) if req.status_code == 200: response = req.text if destination and isinstance(destination, str): FileHelper(destination).write(req.text, overwrite=True) adapter.close() req.close() return response adapter.close() session.close() raise PyFunceble.helpers.exceptions.UnableToDownload( f"{req.url} (retries: {self.retries} | status code: {req.status_code})" ) PyFunceble-4.2.29.dev/PyFunceble/helpers/environment_variable.py000066400000000000000000000162211467462152100247140ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the environment variable helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 logging import os from typing import Any, Optional, Union import dotenv class EnvironmentVariableHelper: """ Simplify the way we work with environment variable. :param str name: The name of the environment variable to work with. """ _name: Optional[str] = None _env_file_path: Optional[str] = None def __init__(self, name: Optional[str] = None, env_file_path: Optional[str] = None): if name is not None: self.name = name if env_file_path is not None: self.env_file_path = env_file_path logging.getLogger("dotenv").setLevel(logging.CRITICAL) @property def name(self) -> Optional[str]: """ Provides the current state of the :code:`_name` attribute. """ return self._name @name.setter def name(self, value: str) -> None: """ Sets the name of the environment variable to work with. :param value: The name to set. :raise TypeError: When :code:`value` is not a :py:class:`str` """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") self._name = value def set_name(self, value: str) -> "EnvironmentVariableHelper": """ Sets the name of the environment variable to work with. :param value: The name to set. """ self.name = value return self @property def env_file_path(self) -> Optional[str]: """ Provides the current state of the :code:`_env_file_path` attribute. """ return self._env_file_path @env_file_path.setter def env_file_path(self, value: str) -> None: """ Sets the location of the environment file to work with. :param value: The name to set. :raise TypeError: When :code:`value` is not a :py:class:`str` """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") self._env_file_path = value def set_env_file_path(self, value: str) -> "EnvironmentVariableHelper": """ Sets the location of the environment file to work with. :param value: The name to set. """ self.env_file_path = value return self def exists(self) -> bool: """ Checks if the given environment variable name exists. """ return self.name in os.environ def get_value(self, *, default: Optional[Any] = None) -> Union[Any, str]: """ Returns the value of the given environment variable name (if exists.) :param default: The default value to return. """ if self.exists(): return os.environ[self.name] return default def get_value_from_env_file( self, *, default: Optional[Any] = None ) -> Union[Any, str]: """ Returns the value of the given environment variable if it exists in the given file path. """ read_value = dotenv.get_key(self.env_file_path, self.name) if read_value is not None: return read_value return default def set_value(self, value: str) -> "EnvironmentVariableHelper": """ Sets the given value into the given environment variable name. :param str value: The value to set. :raise TypeError: When :code:`value` is not a :py:class:`value`. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") os.environ[self.name] = value return self def set_value_in_env_file(self, value: str) -> "EnvironmentVariableHelper": """ Sets the given value and save it into the given dotenv file. .. warning:: This method also set the environment variable from the current environment. :param value: The value to set. """ self.set_value(value) dotenv.set_key(self.env_file_path, self.name, value) return self def delete(self) -> "EnvironmentVariableHelper": """ Deletes the given environment variable if exists. """ if self.exists(): del os.environ[self.name] return self def delete_from_env_file(self) -> "EnvironmentVariableHelper": """ Deletes the given environment file from the given dotenv file. .. warning:: This method also delete the environment variable from the current environment. """ self.delete() dotenv.unset_key(self.env_file_path, self.name) return self PyFunceble-4.2.29.dev/PyFunceble/helpers/exceptions.py000066400000000000000000000053101467462152100226610ustar00rootroot00000000000000# pylint:disable=line-too-long """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the exceptions related to the helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 PyFunceble.exceptions class PyFuncebleHelperException(PyFunceble.exceptions.PyFuncebleException): """ Describes the helper (related) exceptions. """ class UnableToDownload(PyFuncebleHelperException): """ Describes a failing download. """ PyFunceble-4.2.29.dev/PyFunceble/helpers/file.py000066400000000000000000000146571467462152100214350ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the file helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import shutil from typing import Any, Optional from PyFunceble.helpers.directory import DirectoryHelper class FileHelper: """ Simplify the file manipulations. :param str path: The file path to work with. """ _path: Optional[str] = None def __init__(self, path: Optional[str] = None): if path: self.path = path @property def path(self) -> Optional[str]: """ Provides the current state of the :code:`_path` attribute. """ return self._path @path.setter def path(self, value: str) -> None: """ Sets the path to work with. :param value: The path to work with. :raise TypeError: When :code:`value` is a :py:class:`value`. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} is given.") self._path = value def set_path(self, value: str) -> "FileHelper": """ Sets the path to work with. :param value: The path to work with. """ self.path = value return self def join_path(self, *args) -> str: """ Joins the given arguments with the given path. """ return os.path.join(self.path, *args) def exists(self) -> bool: """ Checks if the given file path exists. """ return os.path.isfile(self.path) def get_size(self) -> int: """ Provides the size (in bytes) of the given file path. """ return os.stat(self.path).st_size def is_empty(self) -> bool: """ Checks if the given file path is empty. """ return self.get_size() <= 0 def delete(self) -> "FileHelper": """ Deletes the given file path if it exists. """ if self.exists(): os.remove(self.path) return self def write( self, data: Any, *, overwrite: bool = False, encoding: str = "utf-8" ) -> "FileHelper": """ Write the given data into the given file path. :param data: The data to write. :param encoding: The encoding to use while opening the file. """ if overwrite or not self.exists(): DirectoryHelper(os.path.dirname(self.path)).create() with self.open("w", encoding=encoding) as file_stream: file_stream.write(data) else: with self.open("a", encoding=encoding) as file_stream: file_stream.write(data) return self def read(self, *, encoding: str = "utf-8") -> Optional[str]: """ Read the given file path and return it's content. :param str encoding: The encoding to use. """ data = None if self.exists(): with self.open("r", encoding=encoding) as file_stream: data = file_stream.read() return data def read_bytes(self) -> Optional[bytes]: """ Read the given file ath and returns it's bytes contetn. """ data = None if self.exists(): with self.open("rb") as file_stream: data = file_stream.read() return data def open(self, *args, **kwargs) -> "open": """ A wrapper for the built-in :py:class:`open` function. """ return open(self.path, *args, **kwargs) # pylint: disable=unspecified-encoding def copy(self, destination: str) -> "FileHelper": """ Copy the globaly given file path to the given destination. :param str destination: The destination of the copy. """ if self.exists(): shutil.copy(self.path, destination) return self def move(self, destination) -> "FileHelper": """ Move the globally given file path to the given destination. :param str destination: The destination of the file. """ if self.exists(): shutil.move(self.path, destination) return self PyFunceble-4.2.29.dev/PyFunceble/helpers/hash.py000066400000000000000000000122141467462152100214240ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the hashing helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional, Union from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from PyFunceble.helpers.file import FileHelper class HashHelper: """ Simplify the hashing of data or file content. :param str algo: The algorithm to use for hashing. :raise ValueError: When the given algo is not known. """ _algo: str = "SHA512_224" def __init__(self, algo: Optional[str] = None): if algo is not None: self.algo = algo @property def algo(self) -> str: """ Provides the current state fo the :code:`_algo` attribute. """ return self._algo @algo.setter def algo(self, value: str) -> None: """ Sets the algorithm to work with. :param value: The name of the hash to use. :raise TypeError: When :code:`value` is not a :py:class:`str`. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") value = value.upper() if not hasattr(hashes, value): raise ValueError( f" ({value!r}) in an unknown algorithm ({self.algo!r})." ) self._algo = value def set_algo(self, value: str) -> "HashHelper": """ Sets the algorithm to work with. :param value: The name of the hash to use. """ self.algo = value return self def __get_hash(self) -> hashes.Hash: """ Provides the Hash to use. """ return hashes.Hash(getattr(hashes, self.algo)(), backend=default_backend()) def hash_file(self, file_path: str) -> str: """ Hashes the content of the given file. :param file_path: The path of the file to read. """ block_size = 4096 digest = self.__get_hash() with FileHelper(file_path).open("rb") as file_stream: block = file_stream.read(block_size) while block: digest.update(block) block = file_stream.read(block_size) return digest.finalize().hex() def hash_data(self, data: Union[str, bytes]) -> str: """ Hashes the given data. :param data: The data to hash. :raise TypeError: When :code:`data` is not :py:class:`str` or :py:class:`bytes`. """ if not isinstance(data, (bytes, str)): raise TypeError(f" should be {bytes} or {str}, {type(data)}, given.") if isinstance(data, str): data = data.encode() digest = self.__get_hash() digest.update(data) return digest.finalize().hex() PyFunceble-4.2.29.dev/PyFunceble/helpers/list.py000066400000000000000000000116111467462152100214540ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the list helpers Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy from typing import Any, List, Optional class ListHelper: """ Simplify the list manipulation. :param subject: The list to work with. :param bool remove_empty: Process the deletion of empty strings. """ _subject: Optional[List[Any]] = None def __init__(self, subject: Optional[List[Any]] = None): if subject is not None: self.subject = subject @property def subject(self): """ Provides the current state of the :code:`_subject` attribute. """ return self._subject @subject.setter def subject(self, value: List[Any]) -> None: """ Sets the subject to work with. :param value: The subject to work with. :raise TypeError: When :code:`value` is not a :py:class:`list`. """ if not isinstance(value, list): raise TypeError(f" should be {list}, {type(value)} given.") self._subject = copy.deepcopy(value) def set_subject(self, value: List[Any]) -> "ListHelper": """ Sets the subject to work with. :param value: The subject to work with. """ self.subject = value return self def remove_empty(self) -> "ListHelper": """ Removes the empty entries of the given list. """ self.subject = [x for x in self.subject if x is None or x] return self def remove_duplicates(self) -> "ListHelper": """ Removes the duplicates of the current list. """ result = [] for element in self.subject: if element not in result: result.append(element) self.subject = result return self def sort(self, *, reverse: bool = False) -> "ListHelper": """ Sorts the given list (of string preferably). :param bool reverse: Tell us if we have to reverse the list. """ self.custom_sort(str.lower, reverse=reverse) return self def custom_sort(self, key_method: Any, *, reverse: bool = False) -> "ListHelper": """ Sorts the list with the given key method. :param key_method: A function or method to use to format the readed element before sorting. :type key_method: function|method :param bool reverse: Tell us if we have to reverse the list. """ self.subject = sorted(self.subject, key=key_method, reverse=reverse) return self PyFunceble-4.2.29.dev/PyFunceble/helpers/merge.py000066400000000000000000000136361467462152100216110ustar00rootroot00000000000000""" The tool to check the availability or syntax of dosubject, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the merging helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy from typing import Any, List, Optional class Merge: """ Simplify the merging of dict and list. :param subject: The subject to work with. """ _subject: Optional[Any] = None def __init__(self, subject: Optional[Any] = None): if subject is not None: self.subject = subject @property def subject(self) -> Optional[Any]: """ Provides the current state of the :code:`_subject` attribute. """ return self._subject @subject.setter def subject(self, value: Any) -> None: """ Sets the subject to work with. :param value: The subject to work with. :raise TypeError: When :code:`value` is not a :py:class:`list`. """ self._subject = copy.deepcopy(value) def set_subject(self, value: Any) -> "Merge": """ Sets the subject to work with. :param value: The subject to work with. :raise TypeError: When :code:`value` is not a :py:class:`list`. """ self.subject = value return self def __list(self, origin: Any, strict: bool = True) -> List[Any]: """ Process the list merging. :param strict: Activates the strict mode. """ result = [] if strict: for index, element in enumerate(self.subject): try: if isinstance(element, dict) and isinstance(origin[index], dict): result.append(Merge(element).into(origin[index], strict=strict)) elif isinstance(element, list) and isinstance(origin[index], list): result.append(Merge(element).into(origin[index], strict=strict)) else: result.append(element) except IndexError: # pragma: no cover ## Safety result.append(element) else: result = origin for element in self.subject: if element not in result: result.append(element) return result def __dict(self, origin: Any, strict: bool = True) -> dict: """ Process the dict merging. :param bool strict: Activates the strict mode. """ result = {} for index, data in self.subject.items(): if index in origin: if isinstance(data, dict) and isinstance(origin[index], dict): result[index] = Merge(data).into(origin[index], strict=strict) elif isinstance(data, list) and isinstance(origin[index], list): result[index] = Merge(data).into(origin[index], strict=strict) else: result[index] = data else: result[index] = data for index, data in origin.items(): if index not in result: result[index] = data return result def into(self, origin: Any, strict: bool = True) -> Any: """ Process the mergin. :param origin: The original data. :param strict: Activates the strict mode. """ origin = copy.deepcopy(origin) if isinstance(self.subject, list) and isinstance(origin, list): return self.__list(origin, strict=strict) if isinstance(self.subject, dict) and isinstance(origin, dict): return self.__dict(origin, strict=strict) return self.subject PyFunceble-4.2.29.dev/PyFunceble/helpers/regex.py000066400000000000000000000154131467462152100216170ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the regular expressions helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 from typing import List, Optional, Union class RegexHelper: """ Simplify the regex matching and usage. :param str regex: The regex to use. :param escape_regex: Escapes the given regex. """ _regex: Optional[str] = None escape_regex: bool = False def __init__(self, regex: Optional[str] = None, escape_regex: bool = False): self.escape_regex = escape_regex if regex is not None: self.regex = regex @property def regex(self) -> Optional[str]: """ Provides the current state of the :code:`_regex` attribute. """ return self._regex @regex.setter def regex(self, value: str) -> None: """ Sets the regex to work with. :param value: The regex to work with. :raise TypeError: When :code:`value` is not :py:class:`str`. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(str)} given.") if not self.escape_regex: self._regex = value else: self._regex = re.escape(value) def set_regex(self, value: str) -> "RegexHelper": """ Sets the regex to work with. :param value: The regex to work with. :raise TypeError: When :code:`value` is not :py:class:`str`. """ self.regex = value return self def get_not_matching_list(self, data: List[str]) -> List[str]: """ Returns the strings which does not the match the regex in the given data. """ pre_result = re.compile(self.regex) return [x for x in data if not pre_result.search(str(x))] def get_matching_list(self, data: List[str]) -> List[str]: """ Returns the strings which does the match the regex in the given data. """ pre_result = re.compile(self.regex) return [x for x in data if pre_result.search(str(x))] def match( self, data: str, *, rematch: bool = False, group: int = 0, return_match: bool = True, ) -> Union[bool, str, List[str]]: """ Checks if the given data match the given regex string. :param data: The data to work with. :param rematch: The equivalent of the $BASH_REMATCH but in Python. It's basically a list of all groups. :param group: The group to return when return_match is set to :code:`True`. :param return_match: Return the part that match the given regex string. """ result = [] to_match = re.compile(self.regex) if rematch: pre_result = to_match.findall(data) else: pre_result = to_match.search(data) if return_match and pre_result: if rematch: for res in pre_result: if isinstance(res, tuple): result.extend(list(res)) else: # pragma: no cover ## Safety result.append(res) if group != 0: return result[group] else: result = pre_result.group(group).strip() return result if not return_match and pre_result: return True return False def replace_match( self, data: str, replacement: str, *, occurences: int = 0, multiline: bool = False, ) -> str: """ Replaces the string which match the regex string with the given replacement. :param data: The data to work with. :param replacement: The replacement of the matched regex. :param occurences: The number of occurences to replace. .. note:: :code:`0` means all occurences. """ if isinstance(replacement, str): return re.sub( self.regex, replacement, data, occurences, flags=re.MULTILINE if multiline else 0, ) return data def split(self, data: str) -> List[str]: """ Split the reference of the given regex. :param str data: The data to work with. :rtype: list """ return re.split(self.regex, data) PyFunceble-4.2.29.dev/PyFunceble/logger.py000066400000000000000000000406571467462152100203320ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our logger. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools import logging import logging.handlers import os import traceback from typing import Generator, Optional, Tuple, Union import PyFunceble.cli.storage import PyFunceble.storage from PyFunceble.helpers.directory import DirectoryHelper from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper class Logger: """ Provides our logging logic. .. warning:: There is several way to activate the logging. 1. Through the :code:`PYFUNCEBLE_DEBUG_ON_SCREEN` environment variable. 2. Through the :code:`DEBUG_PYFUNCEBLE_ON_SCREEN` environment variable. 3. Through the :code:`PYFUNCEBLE_DEBUG` environment variable. 4. Through the :code:`DEBUG_PYFUNCEBLE` environment variable. 5. Through the :py:meth:`PyFunceble.logger.Logger.set_activated` method. """ # pylint: disable=too-many-public-methods # pylint: disable=line-too-long OWN_FORMAT: str = ( "[%(asctime)s | %(levelname)s | %(origin_path)s:" "%(origin_line)s@%(origin_func)s | PPID%(process)d:%(processName)s]:\n" "%(message)s\n" ) """ Our very own format. """ ROOT_FORMAT: str = ( "[%(asctime)s::%(levelname)s](PID%(process)s:%(processName)s): %(message)s" ) """ The format of the root loggy. """ STD_MIN_LEVEL: int = logging.INFO _activated: bool = False _min_level: int = logging.INFO _output_directory: Optional[str] = None own_formatter: logging.Formatter = logging.Formatter(OWN_FORMAT) root_formatter: logging.Formatter = logging.Formatter(ROOT_FORMAT) info_logger: Optional[logging.Logger] = None debug_logger: Optional[logging.Logger] = None warning_logger: Optional[logging.Logger] = None error_logger: Optional[logging.Logger] = None fatal_logger: Optional[logging.Logger] = None critical_logger: Optional[logging.Logger] = None sqlalchemy_logger: Optional[logging.Logger] = None env_var_helper: EnvironmentVariableHelper = EnvironmentVariableHelper() def __init__( self, *, activated: Optional[bool] = None, min_level: Optional[int] = None, output_dir: Optional[str] = None, ) -> None: if output_dir: self.output_directory = output_dir else: self.output_directory = os.path.join( PyFunceble.cli.storage.OUTPUT_DIRECTORY, PyFunceble.cli.storage.OUTPUTS.logs.directories.parent, ) if activated is not None: self.activated = activated if min_level is not None: self.min_level = min_level else: self.guess_and_set_min_level() @property def on_screen(self) -> bool: """ Provides the authorization to log on screen. """ return ( self.env_var_helper.set_name("PYFUNCEBLE_DEBUG_ON_SCREEN").exists() or self.env_var_helper.set_name("DEBUG_PYFUNCEBLE_ON_SCREEN").exists() ) @property def on_file(self) -> bool: """ Provides the authorization to log on file. """ return ( self.env_var_helper.set_name("PYFUNCEBLE_DEBUG").exists() or self.env_var_helper.set_name("DEBUG_PYFUNCEBLE").exists() ) @property def activated(self) -> bool: """ Provides the current state of the :code:`_activated` attribute. """ return self._activated @activated.setter def activated(self, value: bool) -> None: """ Sets the value of the activated attribute. :param value: The value to set. :raise TypeError: When the given value is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._activated = value def set_activated(self, value: bool) -> "Logger": """ Sets the value of the activated attribute. :param value: The value to set. """ self.activated = value return self @property def min_level(self) -> int: """ Provides the current state of the :code:`_min_level` attribute. """ return self._min_level @min_level.setter def min_level(self, value: Union[int, str]) -> None: """ Sets the minimum level to log. :param value: The value to set. :raise TypeError: When the given value is not a :py:class:`int` or :py:class:`str`. :raise ValueError: When the given value is not supported """ if not isinstance(value, (int, str)): raise TypeError(f" should be {int} or {str}, {type(value)} given.") # pylint: disable=protected-access if isinstance(value, int) and value not in logging._levelToName: raise ValueError(f" is not in {list(logging._nameToLevel.keys())}") if isinstance(value, str): if value.upper() not in logging._nameToLevel: raise ValueError( f" is not in {list(logging._nameToLevel.keys())}" ) value = logging._nameToLevel[value.upper()] self._min_level = value return self def set_min_level(self, value: Union[int, str]) -> "Logger": """ Sets the minimum level to log. :param value: The value to set. """ self.min_level = value return self @property def output_directory(self) -> Optional[str]: """ Provides the current state of the :code:`_output_directory` attribute. """ if self.authorized: DirectoryHelper(self._output_directory).create() return self._output_directory @output_directory.setter def output_directory(self, value: str) -> None: """ Sets the directory to write. Side Effect: Creation of the given value if it does not exists. :param value: The value to set. :raise TypeError: When the given value is not a :py:class:`str`. """ if not isinstance(value, str): raise TypeError(f" should be {int}, {type(value)} given.") self._output_directory = value def set_output_directory(self, value: str) -> "Logger": """ Sets the directory to write. :param value: The value to set. """ self.output_directory = value return self @property def authorized(self) -> bool: """ Provides the authorization to actually log. """ return ( self.activated or self.on_screen or self.on_file or ( bool(PyFunceble.storage.CONFIGURATION) and bool(PyFunceble.storage.CONFIGURATION.debug.active) ) ) @staticmethod def get_origin() -> dict: """ Provides the informatioon about where the logger was triggered. :return: A tuple, which is composed of the following. (trigger file path, trigger line, trigger function/method name) """ stackback = [ y for x in [x.split("\n") for x in traceback.format_stack()] for y in x if y ] interest = stackback[-6].split(",") complete_file = interest[0].strip()[6:-1].split(os.sep) try: if complete_file[-2] != PyFunceble.storage.PROJECT_NAME: file = "/".join(complete_file) else: file = "/".join(complete_file[-2:]) except IndexError: file = "/".join(complete_file) line = interest[1].strip().split()[-1].strip() func_name = interest[2].strip()[3:] if PyFunceble.storage.PROJECT_NAME in file: file = os.path.relpath(file) return {"origin_path": file, "origin_line": line, "origin_func": func_name} def single_logger_factory(level_name: str): # pylint: disable=no-self-argument """ Provides the general factory. :param level_name: The level to log. """ def single_logger(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): # pylint: disable=no-member, protected-access if ( self.authorized and logging._nameToLevel[level_name.upper()] >= self.min_level ): try: logger = getattr( getattr(self, f"{level_name.lower()}_logger"), level_name.lower(), ) if not logger: self.init_loggers() except AttributeError: self.init_loggers() logger = getattr( getattr(self, f"{level_name.lower()}_logger"), level_name.lower(), ) return logger(*args, **kwargs, extra=self.get_origin()) return func return wrapper return single_logger def guess_and_set_min_level(self) -> "Logger": """ Tries to guess the min level from the configuration. """ env_vars = ["PYFUNCEBLE_DEBUG_LVL", "PYFUNCEBLE_LOGGING_LVL"] env_var_helper = EnvironmentVariableHelper() env_var_found = False for env_var in env_vars: if env_var_helper.set_name(env_var).exists(): self.min_level = env_var_helper.get_value() env_var_found = True break if not env_var_found: if PyFunceble.storage.CONFIGURATION: # pylint: disable=protected-access self.min_level = logging._nameToLevel[ PyFunceble.storage.CONFIGURATION.debug.level.upper() ] else: self.min_level = self.STD_MIN_LEVEL def guess_all_settings(self) -> "Logger": """ Try to guess all settings. """ to_ignore = ["guess_all_settings"] for method in dir(self): if method in to_ignore or not method.startswith("guess_"): continue getattr(self, method)() return self def destroy_loggers(self) -> "Logger": """ Destroyes all existing loggers. """ for logger, level in self.get_next_logger(): logger.handlers.clear() delattr(self, f"{level}_logger") setattr(self, f"{level}_logger", None) def get_next_logger(self) -> Generator[None, Tuple[logging.Logger, str], None]: """ Provides the next logger. """ for logger_var_name in Logger.__dict__: if ( not logger_var_name.endswith("_logger") or logger_var_name == "get_next_logger" or "sqlalchemy" in logger_var_name ): continue level = logger_var_name.split("_", 1)[0] if not getattr(self, logger_var_name): setattr(self, logger_var_name, logging.getLogger(f"PyFunceble.{level}")) yield getattr(self, logger_var_name), level def init_loggers(self) -> "Logger": """ Init all our logger. """ if self.authorized: self.destroy_loggers() if not self.sqlalchemy_logger: self.sqlalchemy_logger = logging.getLogger("sqlalchemy") self.sqlalchemy_logger.setLevel(self.min_level) self.sqlalchemy_logger.propagate = False for logger, level in self.get_next_logger(): logger.propagate = False # pylint: disable=protected-access logger.setLevel(logging._nameToLevel[level.upper()]) logger.addHandler(self.get_handler(level)) return self def get_handler( self, level_name: str ) -> Optional[Union[logging.StreamHandler, logging.handlers.RotatingFileHandler]]: """ Given a level name, this method provides the right handler for it! """ level_name = level_name.upper() specials = ["SQLALCHEMY"] if hasattr(logging, level_name) or level_name in specials: if self.on_screen: handler = logging.StreamHandler() else: handler = logging.handlers.RotatingFileHandler( os.path.join(self.output_directory, f"{level_name.lower()}.log"), maxBytes=100_000_000, backupCount=5, ) if level_name in specials: handler.setLevel(self.min_level) handler.setFormatter(self.root_formatter) else: handler.setLevel(getattr(logging, level_name)) handler.setFormatter(self.own_formatter) return handler return None @single_logger_factory("info") def info(self, *args, **kwargs): """ Logs to the PyFunceble.info logger. """ @single_logger_factory("debug") def debug(self, *args, **kwargs): """ Logs to the PyFunceble.debug logger. """ @single_logger_factory("warning") def warning(self, *args, **kwargs): """ Logs to the PyFunceble.warning logger. """ @single_logger_factory("error") def error(self, *args, **kwargs): """ Logs to the PyFunceble.error logger. """ @single_logger_factory("fatal") def fatal(self, *args, **kwargs): """ Logs to the PyFunceble.fatal logger. """ @single_logger_factory("critical") def critical(self, *args, **kwargs): """ Logs to the PyFunceble.critical logger. """ @single_logger_factory("exception") def exception(self, *args, **kwargs): """ Logs to the PyFunceble.exception logger. """ PyFunceble-4.2.29.dev/PyFunceble/query/000077500000000000000000000000001467462152100176325ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/query/__init__.py000066400000000000000000000047041467462152100217500ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related queries and communication with target resources and information. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/query/dns/000077500000000000000000000000001467462152100204165ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/query/dns/__init__.py000066400000000000000000000046411467462152100225340ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to our very own dns resolver. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/query/dns/nameserver.py000066400000000000000000000230661467462152100231460ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides a way to get or guess the nameserver to use. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import List, Optional, Tuple import dns.exception import dns.resolver import PyFunceble.facility import PyFunceble.storage from PyFunceble.checker.syntax.domain import DomainSyntaxChecker from PyFunceble.checker.syntax.url import URLSyntaxChecker from PyFunceble.converter.url2netloc import Url2Netloc class Nameservers: """ Provides an interface to get the right nameserver to communicate with. """ DEFAULT_NAMESERVERS: List[str] = [ "9.9.9.10", "149.112.112.10", "2620:fe::10", "2620:fe::fe:10", ] nameservers: Optional[List[str]] = None nameserver_ports: Optional[dict] = None protocol: Optional[str] = None domain_syntax_checker: DomainSyntaxChecker = DomainSyntaxChecker() url_syntax_checker: URLSyntaxChecker = URLSyntaxChecker() url2netloc: Url2Netloc = Url2Netloc() def __init__( self, nameserver: Optional[List[str]] = None, protocol: str = "TCP" ) -> None: self.protocol = protocol if nameserver is not None: self.set_nameservers(nameserver) @staticmethod def split_nameserver_from_port( nameserver: str, *, default_port: int = 53, ) -> Tuple[str, int]: """ Splits the nameserver from its port.re :param nameserver: The nameserver to work with. :param default_port: The default port to apply, if none is found. """ if ":" in nameserver: if nameserver.count(":") > 1: if "]" not in nameserver: return nameserver, default_port nameserver, port = nameserver.split("]:", 1) if port.isdigit(): return nameserver[1:], int(port) return nameserver[1:], default_port splitted = nameserver.rsplit(":") if splitted[-1].isdigit(): return ":".join(splitted[:-1]), int(splitted[-1]) return ":".join(splitted[:-1]), default_port return nameserver, default_port @classmethod def get_ip_from_nameserver(cls, nameserver: str) -> List[str]: """ Given a nameserver, this method resolve it in order to get the IP to contact. :param nameserver: The name to resolve. """ PyFunceble.facility.Logger.info( "Started to get ip from nameserver (%r)", nameserver ) result = [] if cls.domain_syntax_checker.set_subject(nameserver).is_valid(): try: result.extend( [ x.address for x in dns.resolver.Resolver().resolve(nameserver, "A") ] ) except dns.exception.DNSException: pass try: result.extend( [ x.address for x in dns.resolver.Resolver().resolve(nameserver, "AAAA") ] ) except dns.exception.DNSException: pass else: result.append(nameserver) PyFunceble.facility.Logger.debug( "IP from nameserver (%r):\n%r", nameserver, result ) PyFunceble.facility.Logger.info( "Finished to get ip from nameserver (%r)", nameserver ) return result def set_nameservers(self, value: List[str]) -> "Nameservers": """ Sets the nameserver to use. Side Effect: Also updates the :code:`nameserver_ports` variable. :raise TypeError: When the given :code:`value` is not a :py:class:`list`. :raise ValueError: When the given :code:`value` is emtpy. """ if not isinstance(value, list): raise TypeError(f" should be {list}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self.nameserver_ports = {} self.nameservers = [] for nameserver in value: if self.protocol.lower() == "https": if not nameserver.startswith("https://"): netloc = self.url2netloc.set_data_to_convert( nameserver ).get_converted() if "/" in nameserver: path = nameserver[nameserver.find("/") :] else: path = "" self.nameservers.append( "https://" # pylint: disable=line-too-long f"{netloc}{path}" ) else: self.nameservers.append(nameserver) # 443 is because it's more likely to be for DOH. self.nameserver_ports.update({self.nameservers[-1]: 443}) continue server, port = self.split_nameserver_from_port(nameserver) for dns_ip in self.get_ip_from_nameserver(server): self.nameservers.append(dns_ip) self.nameserver_ports.update({dns_ip: port}) return self def get_nameservers(self) -> Optional[List[str]]: """ Provides the currently set nameservers. """ return self.nameservers def get_nameserver_ports(self) -> Optional[dict]: """ Provides the currently set nameserver_ports. """ return self.nameserver_ports def guess_and_set_nameservers(self) -> "Nameservers": """ Try to guess and set the nameserver to use. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if PyFunceble.storage.CONFIGURATION.dns.server: if isinstance(PyFunceble.storage.CONFIGURATION.dns.server, list): self.set_nameservers(PyFunceble.storage.CONFIGURATION.dns.server) else: self.set_nameservers([PyFunceble.storage.CONFIGURATION.dns.server]) else: # pragma: no cover try: ## Well, I don't like playing with the default resolver. self.set_nameservers( dns.resolver.get_default_resolver().nameservers ) except dns.resolver.NoResolverConfiguration: self.set_nameservers(self.DEFAULT_NAMESERVERS) else: # pragma: no cover try: ## Well, I don't like playing with the default resolver. self.set_nameservers(dns.resolver.get_default_resolver().nameservers) except dns.resolver.NoResolverConfiguration: self.set_nameservers(self.DEFAULT_NAMESERVERS) return self def guess_all_settings( self, ) -> "Nameservers": # pragma: no cover ## Method themselves are more important """ Try to guess all settings. """ to_ignore = ["guess_all_settings"] for method in dir(self): if method in to_ignore or not method.startswith("guess_"): continue getattr(self, method)() return self PyFunceble-4.2.29.dev/PyFunceble/query/dns/query_tool.py000066400000000000000000001000151467462152100231670ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an interface for the query. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: disable=too-many-lines import copy import functools import ipaddress import random import socket import time from typing import Dict, List, Optional, Union import dns.exception import dns.message import dns.name import dns.query import dns.rdataclass import dns.rdatatype import PyFunceble.facility import PyFunceble.storage from PyFunceble.helpers.list import ListHelper from PyFunceble.query.dns.nameserver import Nameservers from PyFunceble.query.record.dns import DNSQueryToolRecord class DNSQueryTool: """ Provides our query tool. """ # pylint: disable=too-many-public-methods STD_PROTOCOL: str = "UDP" STD_TIMEOUT: float = 5.0 STD_FOLLOW_NAMESERVER_ORDER: bool = True STD_TRUST_SERVER: bool = False STD_DELAY: float = 0.0 SUPPORTED_PROTOCOL: List[str] = ["TCP", "UDP", "HTTPS", "TLS"] value2rdata_type: Dict[int, str] = { x.value: x.name for x in dns.rdatatype.RdataType } rdata_type2value: Dict[str, int] = { x.name: x.value for x in dns.rdatatype.RdataType } nameservers: Nameservers = Nameservers() _query_record_type: int = dns.rdatatype.RdataType.ANY _subject: Optional[str] = None _follow_nameserver_order: bool = True _preferred_protocol: str = "UDP" _query_timeout: float = 5.0 _trust_server: bool = False _delay: float = 0.0 dns_name: Optional[str] = None query_message: Optional[dns.message.QueryMessage] = None lookup_record: Optional[DNSQueryToolRecord] = None def __init__( self, *, nameservers: Optional[List[str]] = None, follow_nameserver_order: Optional[bool] = None, preferred_protocol: Optional[str] = None, trust_server: Optional[bool] = None, delay: Optional[bool] = None, ) -> None: if nameservers is not None: self.nameservers.set_nameservers(nameservers) else: # pragma: no cover ## I'm not playing with system resolver. self.nameservers.guess_and_set_nameservers() if preferred_protocol is not None: self.preferred_protocol = preferred_protocol else: self.guess_and_set_preferred_protocol() if follow_nameserver_order is not None: self.follow_nameserver_order = follow_nameserver_order else: self.guess_and_set_follow_nameserver_order() if trust_server is not None: self.trust_server = trust_server else: self.guess_and_set_trust_server() if delay is not None: self.delay = delay else: self.guess_and_set_delay() def prepare_query(func): # pylint: disable=no-self-argument """ Prepare the query after running the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) # pylint: disable=not-callable if self.subject and self.query_record_type: self.dns_name = self.get_dns_name_from_subject_and_query_type() if self.dns_name: self.query_message = dns.message.make_query( self.dns_name, self.query_record_type ) else: self.query_message = None return result return wrapper def update_lookup_record(func): # pylint: disable=no-self-argument """ Ensures that a clean record is generated after the execution of the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) # pylint: disable=not-callable if self.lookup_record is None or self.subject != self.lookup_record.subject: self.lookup_record = DNSQueryToolRecord() self.lookup_record.subject = self.subject if self.dns_name != self.lookup_record.dns_name: self.lookup_record.dns_name = self.dns_name if ( self.get_human_query_record_type() != self.lookup_record.query_record_type ): self.lookup_record.query_record_type = ( self.get_human_query_record_type() ) if ( self.follow_nameserver_order != self.lookup_record.follow_nameserver_order ): self.lookup_record.follow_nameserver_order = ( self.follow_nameserver_order ) if self.query_timeout != self.lookup_record.query_timeout: self.lookup_record.query_timeout = self.query_timeout if self.preferred_protocol != self.lookup_record.preferred_protocol: self.lookup_record.preferred_protocol = self.preferred_protocol return result return wrapper def ensure_subject_is_given(func): # pylint: disable=no-self-argument """ Ensures that the subject to work with is given before running the decorated method. :raise TypeError: If :code:`self.subject` is not a :py:class:`str`. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.subject, str): raise TypeError( f" should be {str}, {type(self.subject)} given." ) return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def update_lookup_record_response(func): # pylint: disable=no-self-argument """ Ensures that the response of the decorated method is set as response in our record. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) # pylint: disable=not-callable if result != self.lookup_record.response: self.lookup_record.response = result return result return wrapper def ignore_if_query_message_is_missing(func): # pylint: disable=no-self-argument """ Ignores the call to the decorated method if the query message is missing. Otherwise, return an empty list. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.query_message: return func(self, *args, **kwargs) # pylint: disable=not-callable return [] # pragma: no cover ## Safety return wrapper @ensure_subject_is_given def get_dns_name_from_subject_and_query_type(self): """ Provides the dns name based on the current subject and query type. """ try: if self.get_human_query_record_type().lower() == "ptr": try: return dns.name.from_text( ipaddress.ip_address(self.subject).reverse_pointer ) except ValueError: return dns.name.from_text(self.subject) return dns.name.from_text(self.subject) except ( dns.name.LabelTooLong, dns.name.EmptyLabel, dns.name.BadEscape, dns.name.NameTooLong, ): return None @property def subject(self) -> Optional[str]: """ Provides the current state of the :code:`_subject` attribute. """ return self._subject @subject.setter @prepare_query @update_lookup_record def subject(self, value: str) -> None: """ Sets the subject to work with. :param value: The subject to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._subject = value def set_subject(self, value: str) -> "DNSQueryTool": """ Sets the subject to work with. :param value: The subject to set. """ self.subject = value return self def set_nameservers( self, value: List[str] ) -> "DNSQueryTool": # pragma: no cover ## Underlying already tested. """ Sets the nameservers to work with. :raise TypeError: When the given :code:`value` is not a list of :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ self.nameservers.set_nameservers(value) @property def follow_nameserver_order(self) -> bool: """ Provides the current state of the :code:`_follow_nameserver_order` attribute. """ return self._follow_nameserver_order @follow_nameserver_order.setter @update_lookup_record def follow_nameserver_order(self, value: bool) -> None: """ Updates the :code:`follow_nameserver_order` variable. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._follow_nameserver_order = value def set_follow_nameserver_order(self, value: bool) -> "DNSQueryTool": """ Updates the :code:`follow_nameserver_order` variable. :param value: The value to set. """ self.follow_nameserver_order = value return self @property def query_record_type(self) -> int: """ Provides the current state of the :code:`_query_record_type` attribute. """ return self._query_record_type @query_record_type.setter @prepare_query @update_lookup_record def query_record_type(self, value: Union[str, int]) -> None: """ Sets the DNS record type to query. :param value: The value to set. It can be the human version (e.g AAAA) or an integer as registered in the :code:`value2rdata_type` attribute. :raise TypeError: When the given :code:`value` is not a :py:class:`str` nor :py:class:`int`. :raise ValueError: When the given :code:`value` is unknown or unsupported. """ if not isinstance(value, (str, int)): raise TypeError(f" should be {int} or {str}, {type(value)} given.") if value in self.rdata_type2value: self._query_record_type = self.rdata_type2value[value] elif value in self.value2rdata_type: self._query_record_type = value else: raise ValueError(f" ({value!r}) is unknown or unsupported.") def set_query_record_type(self, value: Union[str, int]) -> "DNSQueryTool": """ Sets the DNS record type to query. :param value: The value to set. It can be the human version (e.g AAAA) or an integer as registered in the :code:`value2rdata_type` attribute. """ self.query_record_type = value return self def get_human_query_record_type(self) -> str: """ Provides the currently set record type. """ return self.value2rdata_type[self.query_record_type] @property def query_timeout(self) -> float: """ Provides the current state of the :code:`_query_timeout` attribute. """ return self._query_timeout @query_timeout.setter @update_lookup_record def query_timeout(self, value: Union[int, float]) -> None: """ Sets the timeout to apply. :param value: The timeout to apply. :raise TypeError: When the given :code:`value` is not a :py:class:`float` nor :py:class.`int`. """ if not isinstance(value, (float, int)): raise TypeError(f" should be {float} or {int}, {type(value)} given.") self._query_timeout = float(value) def set_timeout(self, value: Union[int, float]) -> "DNSQueryTool": """ Sets the timeout to apply. :param value: The timeout to apply. """ self.query_timeout = value return self @property def trust_server(self) -> Optional[bool]: """ Provides the current state of the :code:`trust_server` attribute. """ return self._trust_server @trust_server.setter def trust_server(self, value: bool) -> None: """ Sets the value to apply. :param value: The value to apply. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._trust_server = value def set_trust_server(self, value: bool) -> "DNSQueryTool": """ Sets the value to apply. :param value: The value to apply. """ self.trust_server = value return self def guess_and_set_timeout(self) -> "DNSQueryTool": """ Try to guess and set the timeout. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if PyFunceble.storage.CONFIGURATION.lookup.timeout: self.query_timeout = PyFunceble.storage.CONFIGURATION.lookup.timeout else: self.query_timeout = self.STD_TIMEOUT else: self.query_timeout = self.STD_TIMEOUT return self @property def preferred_protocol(self) -> Optional[str]: """ Provides the current state of the :code:`_preferred_protocol` attribute. """ return self._preferred_protocol @preferred_protocol.setter def preferred_protocol(self, value: str) -> None: """ Sets the preferred protocol. :param value: The protocol to use. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is unknown or unsupported. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") value = value.upper() if value not in self.SUPPORTED_PROTOCOL: raise ValueError( f" {value!r} is unknown or unsupported " f"(supported: {self.SUPPORTED_PROTOCOL!r})." ) self._preferred_protocol = self.nameservers.protocol = value def set_preferred_protocol(self, value: str) -> "DNSQueryTool": """ Sets the preferred protocol. :param value: The protocol to use. """ self.preferred_protocol = value return self @property def delay(self) -> float: """ Provides the current state of the :code:`_delay` attribute. """ return self._delay @delay.setter @update_lookup_record def delay(self, value: Union[int, float]) -> None: """ Sets the delay to apply. :param value: The delay to apply. :raise TypeError: When the given :code:`value` is not a :py:class:`float` nor :py:class.`int`. :raise ValueError: When the given :code:`value` is not a positive. """ if not isinstance(value, (float, int)): raise TypeError(f" should be {float} or {int}, {type(value)} given.") if value < 0: raise ValueError(f" should be positive, {value} given.") self._delay = float(value) def set_delay(self, value: Union[int, float]) -> "DNSQueryTool": """ Sets the delay to apply. :param value: The delay to apply. """ self.delay = value return self def guess_and_set_preferred_protocol(self) -> "DNSQueryTool": """ Try to guess and set the preferred procol. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if isinstance(PyFunceble.storage.CONFIGURATION.dns.protocol, str): self.preferred_protocol = PyFunceble.storage.CONFIGURATION.dns.protocol else: self.preferred_protocol = self.STD_PROTOCOL else: self.preferred_protocol = self.STD_PROTOCOL return self def guess_and_set_follow_nameserver_order(self) -> "DNSQueryTool": """ Try to guess and authorize the mix of the nameserver before each query. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if isinstance( PyFunceble.storage.CONFIGURATION.dns.follow_server_order, bool ): self.follow_nameserver_order = ( PyFunceble.storage.CONFIGURATION.dns.follow_server_order ) else: self.follow_nameserver_order = self.STD_FOLLOW_NAMESERVER_ORDER else: self.follow_nameserver_order = self.STD_FOLLOW_NAMESERVER_ORDER return self def guess_and_set_trust_server(self) -> "DNSQueryTool": """ Try to guess and set the trust flag. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if isinstance(PyFunceble.storage.CONFIGURATION.dns.trust_server, bool): self.trust_server = PyFunceble.storage.CONFIGURATION.dns.trust_server else: self.trust_server = self.STD_TRUST_SERVER else: self.trust_server = self.STD_TRUST_SERVER return self def guess_and_set_delay(self) -> "DNSQueryTool": """ Try to guess and set the delay to apply. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if PyFunceble.storage.CONFIGURATION.dns.delay: self.delay = PyFunceble.storage.CONFIGURATION.dns.delay else: self.delay = self.STD_DELAY else: self.delay = self.STD_DELAY def guess_all_settings( self, ) -> "DNSQueryTool": # pragma: no cover ## Method themselves are more important """ Try to guess all settings. """ to_ignore = ["guess_all_settings"] for method in dir(self): if method in to_ignore or not method.startswith("guess_"): continue getattr(self, method)() return self def get_lookup_record( self, ) -> Optional[DNSQueryToolRecord]: """ Provides the current query record. """ return self.lookup_record def _get_result_from_response( self, response: dns.message.Message ) -> List[str]: # pragma: no cover ## This just reads upstream result """ Given a response, we return the best possible result. """ result = [] rrset = response.get_rrset( response.answer, self.dns_name, dns.rdataclass.RdataClass.IN, self.query_record_type, ) if rrset: result.extend([x.to_text() for x in rrset]) PyFunceble.facility.Logger.debug("Result from response:\r%r", result) return result def _mix_order( self, data: Union[dict, List[str]] ) -> Union[dict, List[str]]: # pragma: no cover ## Just a shuffle :-) """ Given a dataset, we mix its order. """ dataset = copy.deepcopy(data) if not self.follow_nameserver_order: if isinstance(dataset, list): random.shuffle(dataset) return dataset if isinstance(dataset, dict): temp = list(dataset.items()) random.shuffle(temp) return dict(temp) PyFunceble.facility.Logger.debug("Mixed data:\n%r", dataset) return dataset @ensure_subject_is_given @ignore_if_query_message_is_missing @update_lookup_record_response def tcp( self, ) -> Optional[List[str]]: """ Request the chosen record through the TCP protocol. """ self.lookup_record.used_protocol = "TCP" result = [] for nameserver, port in self._mix_order( self.nameservers.get_nameserver_ports() ).items(): PyFunceble.facility.Logger.debug( "Started to query information of %r from %r", self.subject, nameserver ) try: response = dns.query.tcp( self.query_message, nameserver, port=port, timeout=self.query_timeout, ) local_result = self._get_result_from_response(response) if local_result: result.extend(local_result) self.lookup_record.nameserver = nameserver self.lookup_record.port = port PyFunceble.facility.Logger.debug( "Successfully queried information of %r from %r.", self.subject, nameserver, ) if not self.trust_server: # pragma: no cover: Per case. break if self.trust_server: # pragma: no cover: Per case. break except (dns.exception.Timeout, socket.error): # Example: Resource temporarily unavailable. pass except dns.query.UnexpectedSource: # Example: got a response from XXX instead of XXX. pass except dns.query.BadResponse: # Example: A DNS query response does not respond to the question # asked. pass except ValueError: # Example: Input is malformed. break PyFunceble.facility.Logger.debug( "Unsuccessfully queried information of %r from %r. Sleeping %fs.", self.subject, nameserver, self.delay, ) time.sleep(self.delay) return ListHelper(result).remove_duplicates().subject @ensure_subject_is_given @ignore_if_query_message_is_missing @update_lookup_record_response def udp( self, ) -> Optional[List[str]]: """ Request the chosen record through the UTP protocol. """ self.lookup_record.used_protocol = "UDP" result = [] for nameserver, port in self._mix_order( self.nameservers.get_nameserver_ports() ).items(): PyFunceble.facility.Logger.debug( "Started to query information of %r from %r", self.subject, nameserver ) try: response = dns.query.udp( self.query_message, nameserver, port=port, timeout=self.query_timeout, ) local_result = self._get_result_from_response(response) if local_result: result.extend(local_result) self.lookup_record.nameserver = nameserver self.lookup_record.port = port PyFunceble.facility.Logger.debug( "Successfully queried information of %r from %r.", self.subject, nameserver, ) if not self.trust_server: # pragma: no cover: Per case. break if self.trust_server: # pragma: no cover: Per case. break except (dns.exception.Timeout, socket.error): # Example: Resource temporarily unavailable. pass except dns.query.UnexpectedSource: # Example: got a response from XXX instead of XXX. pass except dns.query.BadResponse: # Example: A DNS query response does not respond to the question # asked. pass except ValueError: # Example: Input is malformed. break PyFunceble.facility.Logger.debug( "Unsuccessfully queried information of %r from %r. Sleeping %fs.", self.subject, nameserver, self.delay, ) time.sleep(self.delay) return ListHelper(result).remove_duplicates().subject @ensure_subject_is_given @ignore_if_query_message_is_missing @update_lookup_record_response def https( self, ) -> Optional[List[str]]: """ Request the chosen record through the https protocol. """ self.lookup_record.used_protocol = "HTTPS" result = [] for nameserver in self._mix_order(self.nameservers.get_nameservers()): PyFunceble.facility.Logger.debug( "Started to query information of %r from %r", self.subject, nameserver ) try: response = dns.query.https( self.query_message, nameserver, timeout=self.query_timeout ) local_result = self._get_result_from_response(response) if local_result: result.extend(local_result) self.lookup_record.nameserver = nameserver PyFunceble.facility.Logger.debug( "Successfully queried information of %r from %r.", self.subject, nameserver, ) if not self.trust_server: # pragma: no cover: Per case. break if self.trust_server: # pragma: no cover: Per case. break except (dns.exception.Timeout, socket.error): # Example: Resource temporarily unavailable. pass except dns.query.UnexpectedSource: # Example: got a response from XXX instead of XXX. pass except dns.query.BadResponse: # Example: A DNS query response does not respond to the question # asked. pass except ValueError: # Example: Input is malformed. break PyFunceble.facility.Logger.debug( "Unsuccessfully queried information of %r from %r. Sleeping %fs.", self.subject, nameserver, self.delay, ) time.sleep(self.delay) return ListHelper(result).remove_duplicates().subject @ensure_subject_is_given @ignore_if_query_message_is_missing @update_lookup_record_response def tls( self, ) -> Optional[List[str]]: """ Request the chosen record through the TLS protocol. """ self.lookup_record.used_protocol = "TLS" result = [] for nameserver, port in self._mix_order( self.nameservers.get_nameserver_ports() ).items(): PyFunceble.facility.Logger.debug( "Started to query information of %r from %r", self.subject, nameserver ) if port == 53: # Default port for nameserver class is 53. So we ensure we # overwrite with our own default. port = 853 try: response = dns.query.tls( self.query_message, nameserver, port=port, timeout=self.query_timeout, ) local_result = self._get_result_from_response(response) if local_result: result.extend(local_result) self.lookup_record.nameserver = nameserver self.lookup_record.port = port PyFunceble.facility.Logger.debug( "Successfully queried information of %r from %r.", self.subject, nameserver, ) if not self.trust_server: # pragma: no cover: Per case. break if self.trust_server: # pragma: no cover: Per case. break except (dns.exception.Timeout, socket.error): # Example: Resource temporarily unavailable. pass except dns.query.UnexpectedSource: # Example: got a response from XXX instead of XXX. pass except dns.query.BadResponse: # Example: A DNS query response does not respond to the question # asked. pass except ValueError: # Example: Input is malformed. break PyFunceble.facility.Logger.debug( "Unsuccessfully queried information of %r from %r. Sleeping %fs.", self.subject, nameserver, self.delay, ) time.sleep(self.delay) return ListHelper(result).remove_duplicates().subject def query( self, ) -> Optional[List[str]]: """ Process the query based on the preferred protocol. """ return getattr(self, self.preferred_protocol.lower())() PyFunceble-4.2.29.dev/PyFunceble/query/dns/resolver.py000066400000000000000000000144011467462152100226310ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides a way to provides the nameserver to use. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from typing import List, Optional, Union import dns.resolver import PyFunceble.facility import PyFunceble.storage from PyFunceble.query.dns.nameserver import Nameservers class Resolver: """ Provides the right resolver. :param nameservers: The list of nameservers to communicate with. """ STD_TIMEOUT: float = 5.0 timeout: float = 3.0 nameservers: Nameservers = Nameservers() internal_resolver: Optional[dns.resolver.Resolver] = None def __init__( self, nameservers: Optional[List[str]] = None, timeout: Optional[float] = None ) -> None: if nameservers is not None: self.set_nameservers(nameservers) else: self.nameservers.guess_and_set_nameservers() if timeout is not None: self.set_timeout(timeout) else: self.guess_and_set_timeout() def configure_resolver(func): # pylint: disable=no-self-argument """ Configures the resolvers after calling the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) # pylint: disable=not-callable self.internal_resolver.lifetime = self.timeout + 2.0 self.internal_resolver.timeout = self.timeout self.internal_resolver.nameservers = self.nameservers.get_nameservers() self.internal_resolver.nameserver_ports = ( self.nameservers.get_nameserver_ports() ) return result return wrapper def set_nameservers(self, value: List[str]) -> "Resolver": """ Sets the given nameserver. """ self.nameservers.set_nameservers(value) def set_timeout(self, value: Union[float, int]) -> "Resolver": """ Sets the timeout of a query. """ if not isinstance(value, (float, int)): raise TypeError(f" should be {float}, {type(value)} given.") self.timeout = float(value) return self def get_nameservers(self) -> Optional[List[str]]: """ Provides the currently set list of nameserver. """ return self.nameservers.get_nameservers() def get_nameserver_ports(self) -> Optional[dict]: """ Provides the currently set list of nameserver ports. """ return self.nameservers.get_nameserver_ports() def get_timeout(self) -> Optional[float]: """ Provides the currently set query timeout. """ return self.timeout def guess_and_set_timeout(self) -> "Resolver": """ Tries to guess the the timeout from the configuration. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.set_timeout(float(PyFunceble.storage.CONFIGURATION.lookup.timeout)) else: self.set_timeout(self.STD_TIMEOUT) return self def guess_all_settings( self, ) -> "Resolver": # pragma: no cover ## Method themselves are more important """ Try to guess all settings. """ to_ignore = ["guess_all_settings"] for method in dir(self): if method in to_ignore or not method.startswith("guess_"): continue getattr(self, method)() return self @configure_resolver def get_resolver(self) -> dns.resolver.Resolver: """ Provides the resolver to work with. """ if self.internal_resolver: return self.internal_resolver if self.nameservers.get_nameservers(): self.internal_resolver = dns.resolver.Resolver(configure=False) else: # pragma: no cover ## I don't want to play with the default resolver. self.internal_resolver = dns.resolver.Resolver() return self.internal_resolver PyFunceble-4.2.29.dev/PyFunceble/query/http_status_code.py000066400000000000000000000267631467462152100235760ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our interface for getting the status code of a given subject. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools import socket from typing import Optional, Union import PyFunceble.facility import PyFunceble.factory import PyFunceble.storage from PyFunceble.converter.url2netloc import Url2Netloc class HTTPStatusCode: """ Provides an interface for the extration of the HTTP status code. """ STD_UNKNOWN_STATUS_CODE: int = 99999999 STD_TIMEOUT: float = 5.0 STD_VERIFY_CERTIFICATE: bool = True STD_ALLOW_REDIRECTS: bool = False _subject: Optional[str] = None _timeout: float = 5.0 _verify_certificate: bool = True _allow_redirects: bool = False _url2netloc: Optional[Url2Netloc] = None def __init__( self, subject: Optional[str] = None, *, timeout: Optional[float] = None, verify_certificate: Optional[bool] = None, allow_redirects: Optional[bool] = None, ) -> None: if subject is not None: self.subject = subject if timeout is not None: self.timeout = timeout else: self.guess_and_set_timeout() if verify_certificate is not None: self.verify_certificate = verify_certificate else: self.guess_and_set_verify_certificate() if allow_redirects is not None: self.allow_redirects = allow_redirects else: self.allow_redirects = self.STD_ALLOW_REDIRECTS self._url2netloc = Url2Netloc() def ensure_subject_is_given(func): # pylint: disable=no-self-argument """ Ensures that the subject is given before running the decorated method. :raise TypeError: If the subject is not a string. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.subject, str): raise TypeError( f" should be {str}, {type(self.subject)} given." ) return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @property def subject(self) -> Optional[str]: """ Provides the current state of the :code:`_subject` attribute. """ return self._subject @subject.setter def subject(self, value: str) -> None: """ Sets the subject to work with. :param value: The subject to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._subject = value def set_subject(self, value: str) -> "HTTPStatusCode": """ Sets the subject to work with. :param value: The subject to set. """ self.subject = value return self @property def timeout(self) -> float: """ Provides the current state of the :code:`_timeout` attribute. """ return self._timeout @timeout.setter def timeout(self, value: Union[float, int]) -> None: """ Sets the timeout to apply. :param value: The timeout to apply. :raise TypeError: When the given :code:`value` is not a :py:class:`int` nor :py:class:`float`. :raise ValueError: When the given :code:`value` is less than `1`. """ if not isinstance(value, (int, float)): raise TypeError(f" should be {int} or {float}, {type(value)} given.") if value < 0: raise ValueError(f" ({value!r}) shouldn't be less than 0.") self._timeout = float(value) def set_timeout(self, value: Union[float, int]) -> "HTTPStatusCode": """ Sets the timeout to apply. :param value: The timeout to apply. """ self.timeout = value return self def guess_and_set_timeout(self) -> "HTTPStatusCode": """ Tries to guess and set the timeout from the configuration. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.timeout = PyFunceble.storage.CONFIGURATION.lookup.timeout else: self.timeout = self.STD_TIMEOUT return self @property def verify_certificate(self) -> bool: """ Provides the current state of the :code:`verify_certificate` attribute. """ return self._verify_certificate @verify_certificate.setter def verify_certificate(self, value: bool) -> None: """ Sets the value of the :code:`verify_certificate` variable. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._verify_certificate = value def set_verify_certificate(self, value: bool) -> "HTTPStatusCode": """ Sets the value of the :code:`verify_certificate` variable. :param value: The value to set. """ self.verify_certificate = value return self def guess_and_set_verify_certificate(self) -> "HTTPStatusCode": """ Tries to guess and set the :code:`verify_certificate` attribute. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.verify_certificate = bool( PyFunceble.storage.CONFIGURATION["verify_ssl_certificate"] ) else: self.verify_certificate = self.STD_VERIFY_CERTIFICATE return self @property def allow_redirects(self) -> bool: """ Provides the current state of the :code:`_allow_redirects` attribute. """ return self._allow_redirects @allow_redirects.setter def allow_redirects(self, value: bool) -> None: """ Sets the value of the :code:`verify_certificate` variable. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._allow_redirects = value def set_allow_redirects(self, value: bool) -> "HTTPStatusCode": """ Sets the value of the :code:`verify_certificate` variable. :param value: The value to set. """ self.allow_redirects = value return self @ensure_subject_is_given def get_status_code(self) -> int: """ Provides the status code. .. note:: The HTTP status code provided will differs regarding the following conditions. Assuming, that :code:`allow_redirects` is set to :py:class:`False`, you will be provided the following: - :code:`http://example.org (302) -> https://example.org (200) ===> 200` - :code:`http://example.org (302) -> https://test.example.rog (200) ===> 302` - :code:`http://example.org (302) -> https://test.example.org (301) -> https://example.org (200) ===> 302 On the other site if the :code:`allow_redirects` property is set to :py:class:`True`, this method will provide the status of the last one in the redirection order. In case of any error, this method will provide the default one. """ # pylint: disable=line-too-long try: req = PyFunceble.factory.Requester.get( self.subject, timeout=self.timeout, verify=self.verify_certificate, allow_redirects=True, ) first_origin = self._url2netloc.set_data_to_convert( self.subject ).get_converted() if len(req.history) > 1: final_origin = self._url2netloc.set_data_to_convert( req.history[1].url ).get_converted() else: final_origin = self._url2netloc.set_data_to_convert( req.url ).get_converted() if ( not self.allow_redirects and first_origin != final_origin and req.history ): return req.history[0].status_code return req.status_code except ( PyFunceble.factory.Requester.exceptions.RequestException, PyFunceble.factory.Requester.exceptions.InvalidSchema, PyFunceble.factory.Requester.exceptions.InvalidURL, PyFunceble.factory.Requester.exceptions.MissingSchema, socket.timeout, PyFunceble.factory.Requester.urllib3_exceptions.InvalidHeader, ): pass return self.STD_UNKNOWN_STATUS_CODE PyFunceble-4.2.29.dev/PyFunceble/query/netinfo/000077500000000000000000000000001467462152100212745ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/query/netinfo/__init__.py000066400000000000000000000046321467462152100234120ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides all our network info related subdmodules. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/query/netinfo/address.py000066400000000000000000000061721467462152100233010ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an interface to get the information of a given address. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 socket from typing import List, Optional from PyFunceble.query.netinfo.base import NetInfoBase class AddressInfo(NetInfoBase): """ Provides the information of a given address. """ @NetInfoBase.ensure_subject_is_given def get_info(self) -> Optional[List[str]]: """ Fetch and provides the information of the given hosts. :return: A list of of IP related to the given host. """ try: return [ x[-1][0] for x in socket.getaddrinfo(self.subject, 80, proto=socket.IPPROTO_TCP) ] except (socket.gaierror, socket.herror, UnicodeError, OSError): pass return [] PyFunceble-4.2.29.dev/PyFunceble/query/netinfo/base.py000066400000000000000000000107161467462152100225650ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from typing import Any, Optional class NetInfoBase: """ Provides the base of network information classes. """ _subject: Optional[str] = None base: Optional[str] = None def __init__(self, subject: Optional[str] = None) -> None: if subject is not None: self.subject = subject def ensure_subject_is_given(func): # pylint: disable=no-self-argument """ Ensures that the subject is given before running the decorated method. :raise TypeError: If the subject is not a string. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.subject, str): raise TypeError( f" should be {str}, {type(self.subject)} given." ) return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @property def subject(self) -> Optional[str]: """ Provides the current state of the :code:`_subject` attribute. """ return self._subject @subject.setter def subject(self, value: str) -> None: """ Sets the subject to work with. :param value: The subject to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._subject = value def set_subject(self, value: str) -> "NetInfoBase": """ Sets the subject to work with. :param value: The subject to set. """ self.subject = value return self @ensure_subject_is_given def get_info(self) -> Any: """ Provides the wanted network information. """ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/query/netinfo/hostbyaddr.py000066400000000000000000000065141467462152100240170ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an interface to get the information of a given host. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 socket from typing import Optional from PyFunceble.query.netinfo.base import NetInfoBase class HostByAddrInfo(NetInfoBase): """ Provides the information of a given address/IP. """ @NetInfoBase.ensure_subject_is_given def get_info(self) -> Optional[dict]: """ Fetch and provides the information of the given hosts. :return: A dictionnary with the following format or :py:class:`None` if nothing was found. :: { "hostname": "", "aliases": [], "ips": [] } """ try: request = socket.gethostbyaddr(self.subject) return {"hostname": request[0], "aliases": request[1], "ips": request[2]} except (socket.gaierror, socket.herror): pass return dict() # pylint: disable=use-dict-literal PyFunceble-4.2.29.dev/PyFunceble/query/platform.py000066400000000000000000000753341467462152100220440ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides ans interface which let us interact with the platform API. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: disable=too-many-lines import json import os from typing import Generator, List, Optional, Union import requests import requests.exceptions import PyFunceble.facility import PyFunceble.storage from PyFunceble.checker.availability.status import AvailabilityCheckerStatus from PyFunceble.checker.reputation.status import ReputationCheckerStatus from PyFunceble.checker.syntax.status import SyntaxCheckerStatus from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper class PlatformQueryTool: """ Provides the interface to interact with the platform. :param token: The token to use to communicate with the API. .. warning:: If :code:`None` is given, the class constructor will try to load the :code:`PYFUNCEBLE_COLLECTION_API_TOKEN` or :code:`PYFUNCEBLE_PLATFORM_API_TOKEN` environment variable. :param url_base: The base of the URL to communicate with. :param preferred_status_origin: The preferred data origin. It can be :code:`frequent`, :code:`latest` or :code:`recommended`. """ SUPPORTED_CHECKERS: List[str] = ["syntax", "reputation", "availability"] SUPPORTED_STATUS_ORIGIN: List[str] = ["frequent", "latest", "recommended"] SUBJECT: str = ( "10927294711127294799272947462729471152729471162729471152729471112729" "4710427294745272947100272947972729471012729471002729474627294797272947" "116272947101272947982729474627294710527294711227294797272947472729474" "727294758272947115272947112272947116272947116272947104" ) STD_PREFERRED_STATUS_ORIGIN: str = "frequent" STD_CHECKER_PRIORITY: str = ["none"] STD_CHECKER_EXCLUDE: str = ["none"] STD_TIMEOUT: float = 5.0 _token: Optional[str] = None """ The token to use while communicating with the platform API. """ _url_base: Optional[str] = None """ The base of the URL to communicate with. """ _preferred_status_origin: Optional[str] = None """ The preferred data origin """ _checker_priority: Optional[List[str]] = [] """ The checker to prioritize. """ _checker_exclude: Optional[List[str]] = [] """ The checker to exclude. """ _is_modern_api: Optional[bool] = None """ Whether we are working with the modern or legacy API. """ _timeout: float = 5.0 """ The timeout to use while communicating with the API. """ session: Optional[requests.Session] = None def __init__( self, *, token: Optional[str] = None, preferred_status_origin: Optional[str] = None, timeout: Optional[float] = None, checker_priority: Optional[List[str]] = None, checker_exclude: Optional[List[str]] = None, ) -> None: if token is not None: self.token = token else: self.token = EnvironmentVariableHelper( "PYFUNCEBLE_COLLECTION_API_TOKEN" ).get_value(default="") or EnvironmentVariableHelper( "PYFUNCEBLE_PLATFORM_API_TOKEN" ).get_value( default="" ) if preferred_status_origin is not None: self.preferred_status_origin = preferred_status_origin else: self.guess_and_set_preferred_status_origin() if checker_priority is not None: self.checker_priority = checker_priority else: self.guess_and_set_checker_priority() if checker_exclude is not None: self.checker_exclude = checker_exclude else: self.guess_and_set_checker_exclude() if timeout is not None: self.timeout = timeout else: self.guess_and_set_timeout() self._url_base = EnvironmentVariableHelper( "PYFUNCEBLE_COLLECTION_API_URL" ).get_value(default=None) or EnvironmentVariableHelper( "PYFUNCEBLE_PLATFORM_API_URL" ).get_value( default=None ) self.session = requests.Session() self.session.headers.update( { "Authorization": f"Bearer {self.token}" if self.token else None, "X-Pyfunceble-Version": PyFunceble.storage.PROJECT_VERSION, "Content-Type": "application/json", } ) def __contains__(self, value: str) -> bool: """ Checks if the given value is in the platform. :param value: The value to check. """ return self.pull(value) is not None def __getitem__(self, value: str) -> Optional[dict]: """ Gets the information about the given value. :param value: The value to get the information about. """ return self.pull(value) @property def token(self) -> Optional[str]: """ Provides the currently set token. """ return self._token @token.setter def token(self, value: str) -> None: """ Sets the value of the :code:`_token` attribute. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str` """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") self._token = value def set_token(self, value: str) -> "PlatformQueryTool": """ Sets the value of the :code:`_token` attribute. :param value: The value to set. """ self.token = value return self @property def url_base(self) -> Optional[str]: """ Provides the value of the :code:`_url_base` attribute. """ return self._url_base or "".join( reversed([chr(int(x)) for x in self.SUBJECT.split("272947")]) ) @url_base.setter def url_base(self, value: str) -> None: """ Sets the base of the URL to work with. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value.startswith(("http", "https")): raise ValueError( f" is missing the scheme (http/https), {value} given." ) self._url_base = value.rstrip("/") def set_url_base(self, value: str) -> "PlatformQueryTool": """ Sets the base of the URL to work with. :parma value: The value to set. """ self.url_base = value return self @property def is_modern_api(self) -> bool: """ Provides the value of the :code:`_is_modern_api` attribute. """ return self._is_modern_api @is_modern_api.setter def is_modern_api(self, value: bool) -> None: """ Sets the value of the :code:`_is_modern_api` attribute. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`bool`. """ if not isinstance(value, bool): raise TypeError(f" should be {bool}, {type(value)} given.") self._is_modern_api = value def set_is_modern_api(self, value: bool) -> "PlatformQueryTool": """ Sets the value of the :code:`_is_modern_api` attribute. :param value: The value to set. """ self.is_modern_api = value return self @property def timeout(self) -> float: """ Provides the value of the :code:`_timeout` attribute. """ return self._timeout @timeout.setter def timeout(self, value: float) -> None: """ Sets the value of the :code:`_timeout` attribute. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`float`. """ if not isinstance(value, (int, float)): raise TypeError(f" should be {float}, {type(value)} given.") self._timeout = value def set_timeout(self, value: float) -> "PlatformQueryTool": """ Sets the value of the :code:`_timeout` attribute. :param value: The value to set. """ self.timeout = value return self def guess_and_set_is_modern_api(self) -> "PlatformQueryTool": """ Try to guess if we are working with a legacy version. """ if self.token: try: response = self.session.get( f"{self.url_base}/v1/stats/subject", timeout=self.timeout, ) response.raise_for_status() self.is_modern_api = False except (requests.RequestException, json.decoder.JSONDecodeError): self.is_modern_api = True else: self.is_modern_api = False return self @property def preferred_status_origin(self) -> Optional[str]: """ Provides the value of the :code:`_preferred_status_origin` attribute. """ return self._preferred_status_origin @preferred_status_origin.setter def preferred_status_origin(self, value: str) -> None: """ Sets the preferred status origin. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is not supported. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if value not in self.SUPPORTED_STATUS_ORIGIN: raise ValueError(f" ({value}) is not supported.") self._preferred_status_origin = value def set_preferred_status_origin(self, value: str) -> "PlatformQueryTool": """ Sets the preferred status origin. :parma value: The value to set. """ self.preferred_status_origin = value return self def guess_and_set_preferred_status_origin(self) -> "PlatformQueryTool": """ Try to guess the preferred status origin. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): if isinstance( PyFunceble.storage.CONFIGURATION.platform.preferred_status_origin, str ): self.preferred_status_origin = ( PyFunceble.storage.CONFIGURATION.platform.preferred_status_origin ) else: self.preferred_status_origin = self.STD_PREFERRED_STATUS_ORIGIN else: self.preferred_status_origin = self.STD_PREFERRED_STATUS_ORIGIN return self @property def checker_priority(self) -> Optional[List[str]]: """ Provides the value of the :code:`_checker_priority` attribute. """ return self._checker_priority @checker_priority.setter def checker_priority(self, value: List[str]) -> None: """ Sets the checker priority to set - order matters. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is not supported. """ accepted = [] for checker_type in value: if not isinstance(checker_type, str): raise TypeError( f" ({checker_type}) should be {str}, " "{type(checker_type)} given." ) if checker_type.lower() not in self.SUPPORTED_CHECKERS + ["none"]: raise ValueError(f" ({checker_type}) is not supported.") accepted.append(checker_type.lower()) self._checker_priority = accepted def set_checker_priority(self, value: List[str]) -> "PlatformQueryTool": """ Sets the checker priority. :parma value: The value to set. """ self.checker_priority = value return self def guess_and_set_checker_priority(self) -> "PlatformQueryTool": """ Try to guess the checker priority to use. """ if "PYFUNCEBLE_PLATFORM_CHECKER_PRIORITY" in os.environ: self.checker_priority = os.environ[ "PYFUNCEBLE_PLATFORM_CHECKER_PRIORITY" ].split(",") elif PyFunceble.facility.ConfigLoader.is_already_loaded(): if isinstance(PyFunceble.storage.PLATFORM.checker_priority, list): self.checker_priority = PyFunceble.storage.PLATFORM.checker_priority else: self.checker_priority = self.STD_CHECKER_PRIORITY else: self.checker_priority = self.STD_CHECKER_PRIORITY return self @property def checker_exclude(self) -> Optional[List[str]]: """ Provides the value of the :code:`_checker_exclude` attribute. """ return self._checker_exclude @checker_exclude.setter def checker_exclude(self, value: List[str]) -> None: """ Sets the checker exclude. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is not supported. """ accepted = [] for checker_type in value: if not isinstance(checker_type, str): raise TypeError( f" ({checker_type}) should be {str}, " "{type(checker_type)} given." ) if checker_type.lower() not in self.SUPPORTED_CHECKERS + ["none"]: raise ValueError(f" ({checker_type}) is not supported.") accepted.append(checker_type.lower()) self._checker_exclude = accepted def set_checker_exclude(self, value: List[str]) -> "PlatformQueryTool": """ Sets the checker to exclude. :parma value: The value to set. """ self.checker_exclude = value return self def guess_and_set_checker_exclude(self) -> "PlatformQueryTool": """ Try to guess the checker to exclude. """ if "PYFUNCEBLE_PLATFORM_CHECKER_EXCLUDE" in os.environ: self.checker_exclude = os.environ[ "PYFUNCEBLE_PLATFORM_CHECKER_EXCLUDE" ].split(",") elif PyFunceble.facility.ConfigLoader.is_already_loaded(): if isinstance(PyFunceble.storage.PLATFORM.checker_exclude, list): self.checker_exclude = PyFunceble.storage.PLATFORM.checker_exclude else: self.checker_exclude = self.STD_CHECKER_EXCLUDE else: self.checker_exclude = self.STD_CHECKER_EXCLUDE return self def guess_and_set_timeout(self) -> "PlatformQueryTool": """ Try to guess the timeout to use. """ if PyFunceble.facility.ConfigLoader.is_already_loaded(): self.timeout = PyFunceble.storage.CONFIGURATION.lookup.timeout else: self.timeout = self.STD_TIMEOUT return self def ensure_modern_api(func): # pylint: disable=no-self-argument """ Ensures that the :code:`is_modern_api` attribute is set before running the decorated method. """ def wrapper(self, *args, **kwargs): if self.is_modern_api is None: self.guess_and_set_is_modern_api() return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @ensure_modern_api def pull(self, subject: str) -> Optional[dict]: """ Pulls all data related to the subject or :py:class:`None` :param subject: The subject to search for. :raise TypeError: When the given :code:`subject` is not a :py:class:`str`. :return: The response of the search. """ PyFunceble.facility.Logger.info("Starting to search subject: %r", subject) if not isinstance(subject, str): raise TypeError(f" should be {str}, {type(subject)} given.") if self.is_modern_api: if self.token: url = f"{self.url_base}/v1/aggregation/subject/search" else: url = f"{self.url_base}/v1/hub/aggregation/subject/search" else: url = f"{self.url_base}/v1/subject/search" try: response = self.session.post( url, json={"subject": subject}, timeout=self.timeout, ) response_json = response.json() if response.status_code == 200: PyFunceble.facility.Logger.debug( "Successfully search subject: %r. Response: %r", subject, response_json, ) PyFunceble.facility.Logger.info( "Finished to search subject: %r", subject ) return response_json except (requests.RequestException, json.decoder.JSONDecodeError): response_json = {} PyFunceble.facility.Logger.debug( "Failed to search subject: %r. Response: %r", subject, response_json ) PyFunceble.facility.Logger.info("Finished to search subject: %r", subject) return None @ensure_modern_api def pull_contract(self, amount: int = 1) -> Generator[dict, None, None]: """ Pulls the next amount of contracts. :param int amount: The amount of data to pull. :return: The response of the query. """ PyFunceble.facility.Logger.info("Starting to pull next contract") if not isinstance(amount, int) or amount < 1: amount = 1 url = f"{self.url_base}/v1/contracts/next" params = { "limit": amount, "shuffle": True, } if "none" in self.checker_priority: params["shuffle"] = True else: params["checker_type_priority"] = ",".join(self.checker_priority) if "none" not in self.checker_exclude: params["checker_type_exclude"] = ",".join(self.checker_exclude) try: response = self.session.get( url, params=params, timeout=self.timeout * 10, ) response_json = response.json() if response.status_code == 200: PyFunceble.facility.Logger.debug( "Successfully pulled next %r contracts. Response: %r", response_json ) PyFunceble.facility.Logger.info("Finished to pull next contract") yield response_json else: response_json = [] except (requests.RequestException, json.decoder.JSONDecodeError): response_json = [] PyFunceble.facility.Logger.debug( "Failed to pull next contract. Response: %r", response_json ) PyFunceble.facility.Logger.info("Finished to pull next contracts") yield response_json @ensure_modern_api def deliver_contract(self, contract: dict, contract_data: dict) -> Optional[dict]: """ Delivers the given contract data. :param contract: The contract to deliver. :param contract_data: The data to deliver. :return: The response of the query. """ PyFunceble.facility.Logger.info( "Starting to deliver contract data: %r", contract ) contract_id = contract["id"] contract_data = ( contract_data.to_json() if not isinstance(contract_data, dict) else contract_data ) url = f"{self.url_base}/v1/contracts/{contract_id}/delivery" try: response = self.session.post( url, data=contract_data.encode("utf-8"), timeout=self.timeout * 10, ) response_json = response.json() if response.status_code == 200: PyFunceble.facility.Logger.debug( "Successfully delivered contract: %r. Response: %r", contract_data, response_json, ) PyFunceble.facility.Logger.info( "Finished to deliver contract: %r", contract_data ) return response_json except (requests.RequestException, json.decoder.JSONDecodeError): response_json = {} PyFunceble.facility.Logger.debug( "Failed to deliver contract: %r. Response: %r", contract_data, response_json ) PyFunceble.facility.Logger.info( "Finished to deliver contract: %r", contract_data ) return None @ensure_modern_api def push( self, checker_status: Union[ AvailabilityCheckerStatus, SyntaxCheckerStatus, ReputationCheckerStatus ], ) -> Optional[dict]: """ Push the given status to the platform. :param checker_status: The status to push. :raise TypeError: - When the given :code:`checker_status` is not a :py:class:`AvailabilityCheckerStatus`, :py:class:`SyntaxCheckerStatus` or :py:class:`ReputationCheckerStatus`. - When the given :code:`checker_status.subject` is not a :py:class:`str`. :raise ValueError: When the given :code:`checker_status.subject` is empty. """ if not isinstance( checker_status, (AvailabilityCheckerStatus, SyntaxCheckerStatus, ReputationCheckerStatus), ): raise TypeError( f" should be {AvailabilityCheckerStatus}, " f"{SyntaxCheckerStatus} or {ReputationCheckerStatus}, " f"{type(checker_status)} given." ) if not isinstance(checker_status.subject, str): raise TypeError( f" should be {str}, " f"{type(checker_status.subject)} given." ) if not isinstance(checker_status.checker_type, str): raise TypeError( f" should be {str}, " f"{type(checker_status.subject)} given." ) if checker_status.subject == "": raise ValueError(" cannot be empty.") if ( not self.is_modern_api and hasattr(checker_status, "expiration_date") and checker_status.expiration_date ): self.__push_whois(checker_status) data = self.__push_status( checker_status.checker_type.lower(), checker_status.to_json() ) return data def guess_all_settings( self, ) -> "PlatformQueryTool": # pragma: no cover ## Underlying tested """ Try to guess all settings. """ to_ignore = ["guess_all_settings"] for method in dir(self): if method in to_ignore or not method.startswith("guess_"): continue getattr(self, method)() return self def __push_status( self, checker_type: str, data: Union[dict, str] ) -> Optional[dict]: """ Submits the given status to the platform. :param checker_type: The type of the checker. :param data: The data to submit. :raise TypeError: - When :code:`checker_type` is not a :py:class:`str`. - When :code:`data` is not a :py:class:`dict`. :raise ValueError: When the given :code:`checker_type` is not a subject checker type. """ if not self.token: return None if checker_type not in self.SUPPORTED_CHECKERS: raise ValueError(f" ({checker_type}) is not supported.") PyFunceble.facility.Logger.info("Starting to submit status: %r", data) if self.is_modern_api: if not self.token: url = f"{self.url_base}/v1/hub/status/{checker_type}" else: url = f"{self.url_base}/v1/contracts/self-delivery" else: url = f"{self.url_base}/v1/status/{checker_type}" try: if isinstance(data, dict): response = self.session.post( url, json=data, timeout=self.timeout * 10, ) elif isinstance( data, ( AvailabilityCheckerStatus, SyntaxCheckerStatus, ReputationCheckerStatus, ), ): response = self.session.post( url, json=data.to_dict(), timeout=self.timeout * 10, ) else: response = self.session.post( url, data=data, timeout=self.timeout * 10, ) response_json = response.json() if response.status_code == 200: PyFunceble.facility.Logger.debug( "Successfully submitted data: %r to %s", data, url ) PyFunceble.facility.Logger.info("Finished to submit status: %r", data) return response_json except (requests.RequestException, json.decoder.JSONDecodeError): response_json = {} PyFunceble.facility.Logger.debug( "Failed to submit data: %r to %s. Response: %r", data, url, response_json ) PyFunceble.facility.Logger.info("Finished to submit status: %r", data) return None def __push_whois(self, data: dict) -> Optional[dict]: """ Submits the given WHOIS data into the given subject. :param checker_type: The type of the checker. :param data: The data to submit. :raise TypeError: - When :code:`checker_type` is not a :py:class:`str`. - When :code:`data` is not a :py:class:`dict`. :raise ValueError: When the given :code:`checker_type` is not a subject checker type. """ if not self.token: return None PyFunceble.facility.Logger.info("Starting to submit WHOIS: %r", data) url = f"{self.url_base}/v1/status/whois" try: if isinstance(data, dict): response = self.session.post( url, json=data, timeout=self.timeout * 10, ) elif isinstance( data, ( AvailabilityCheckerStatus, SyntaxCheckerStatus, ReputationCheckerStatus, ), ): response = self.session.post( url, data=data.to_json(), timeout=self.timeout * 10, ) else: response = self.session.post( url, data=data, timeout=self.timeout * 10, ) response_json = response.json() if response.status_code == 200: PyFunceble.facility.Logger.debug( "Successfully submitted WHOIS data: %r to %s", data, url ) PyFunceble.facility.Logger.info("Finished to submit WHOIS: %r", data) return response_json except (requests.RequestException, json.decoder.JSONDecodeError): response_json = {} PyFunceble.facility.Logger.debug( "Failed to WHOIS data: %r to %s. Response: %r", data, url, response_json ) PyFunceble.facility.Logger.info("Finished to submit WHOIS: %r", data) return None PyFunceble-4.2.29.dev/PyFunceble/query/record/000077500000000000000000000000001467462152100211105ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/query/record/__init__.py000066400000000000000000000046051467462152100232260ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides all records classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/query/record/base.py000066400000000000000000000065341467462152100224040ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our record classes. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 dataclasses import json from typing import Any @dataclasses.dataclass class RecordBase: """ Provides the base of all query record classes. """ def __getitem__(self, key: str) -> Any: return getattr(self, key) def to_dict(self) -> dict: """ Provides the dict representation of the current object. """ return { x: y if not hasattr(y, "to_dict") else y.to_dict() for x, y in self.__dict__.items() if not x.startswith("__") } def to_json(self, *, pretty_print: bool = False) -> str: """ Provides the JSON representation of the current object. :param pretty_print: If True, the JSON will be formatted. """ return json.dumps( self.to_dict(), indent=4 if pretty_print else None, ensure_ascii=False, sort_keys=True if pretty_print else None, ) PyFunceble-4.2.29.dev/PyFunceble/query/record/dns.py000066400000000000000000000061101467462152100222440ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the record class of the dns query tool. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 dataclasses from typing import List, Optional from PyFunceble.query.record.base import RecordBase @dataclasses.dataclass class DNSQueryToolRecord(RecordBase): """ Provides a record of an executed request. """ # pylint: disable=too-many-instance-attributes nameserver: Optional[str] = None port: Optional[int] = None follow_nameserver_order: Optional[bool] = None preferred_protocol: Optional[str] = None used_protocol: Optional[str] = None query_record_type: Optional[str] = None query_timeout: Optional[float] = None subject: Optional[str] = None dns_name: Optional[str] = None response: Optional[List[str]] = None PyFunceble-4.2.29.dev/PyFunceble/query/record/whois.py000066400000000000000000000055751467462152100226270ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the record class of the whois query tool. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 dataclasses from typing import Optional from PyFunceble.query.record.base import RecordBase @dataclasses.dataclass class WhoisQueryToolRecord(RecordBase): """ Provides a record of an executed request. """ server: Optional[str] = None port: Optional[str] = None query_timeout: Optional[float] = None subject: Optional[str] = None record: Optional[str] = None expiration_date: Optional[str] = None registrar: Optional[str] = None PyFunceble-4.2.29.dev/PyFunceble/query/requests/000077500000000000000000000000001467462152100215055ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/query/requests/__init__.py000066400000000000000000000046441467462152100236260ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to our very own request handler. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/query/requests/adapter/000077500000000000000000000000001467462152100231255ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/query/requests/adapter/__init__.py000066400000000000000000000046341467462152100252450ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to our request adapters. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/query/requests/adapter/base.py000066400000000000000000000225371467462152100244220ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all our adapter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Optional import requests.adapters import requests.models import PyFunceble.storage from PyFunceble.checker.syntax.ip import IPSyntaxChecker from PyFunceble.query.dns.query_tool import DNSQueryTool class RequestAdapterBase(requests.adapters.HTTPAdapter): """ Extends the built-in HTTP adapater and acts as a base for all our own adapter. """ resolving_cache: dict = {} resolving_use_cache: bool = False timeout: float = 5.0 proxy_pattern: dict = {} def __init__(self, *args, **kwargs): if "timeout" in kwargs: self.timeout = float(kwargs["timeout"]) del kwargs["timeout"] if "max_retries" in kwargs: kwargs["max_retries"] = requests.adapters.Retry( total=kwargs["max_retries"], respect_retry_after_header=False ) if "dns_query_tool" in kwargs: self.dns_query_tool = kwargs["dns_query_tool"] del kwargs["dns_query_tool"] else: self.dns_query_tool = DNSQueryTool() if "proxy_pattern" in kwargs: self.proxy_pattern = kwargs["proxy_pattern"] del kwargs["proxy_pattern"] else: self.proxy_pattern = {} super().__init__(*args, **kwargs) @staticmethod def fake_response() -> requests.models.Response: """ Provides the fake response that is provided when we couldn't resolve the given domain. """ raise PyFunceble.factory.Requester.exceptions.ConnectionError( "Could not resolve." ) @staticmethod def extract_extension(subject: str) -> Optional[str]: """ Provides the extension of the given subject. .. versionchanged:: 4.1.1.dev Handle the case that the given subject does not have a `.` (point). :param str subject: The subject to get extract the extension from. :raise TypeError: When the given :code:`subject` is not a :py:class:`str`. :raise ValueError: When the given :code:`subject` is an empty :py:class:`str`. """ if not subject or "." not in subject: return None if subject.endswith("."): # Absolute needs a little correction. last_point = subject[:-1].rfind(".") else: last_point = subject.rindex(".") extension = subject[last_point + 1 :] if extension.endswith("."): return extension[:-1] return extension def fetch_proxy_from_pattern(self, subject: str) -> dict: """ Provides the proxy settings to use for the given subject. .. versionchanged:: 4.1.1.dev Handle the case that the given subject has no extension/TLD. :param str subject: The subject to work with. :raise TypeError: When the given :code:`subject` is not a :py:class:`str`. :raise ValueError: When the given :code:`subject` is an empty :py:class:`str`. """ def correct_input(pattern_input: dict) -> dict: result = {} if "http" in pattern_input and pattern_input["http"]: result["http"] = pattern_input["http"] if "https" in pattern_input and pattern_input["https"]: result["https"] = pattern_input["https"] if "http" in result and "https" not in result: result["https"] = result["http"] if "https" in result and "http" not in result: result["http"] = result["https"] return result extension = self.extract_extension(subject) proxies = {} if extension and "rules" in self.proxy_pattern: for rule in self.proxy_pattern["rules"]: local_proxy = {} if "http" in rule and rule["http"]: local_proxy["http"] = rule["http"] if "https" in rule and rule["https"]: local_proxy["https"] = rule["https"] if not local_proxy: continue if "tld" in rule and extension in rule["tld"]: proxies = correct_input(local_proxy) break if not proxies and "global" in self.proxy_pattern: proxies = correct_input(self.proxy_pattern["global"]) return proxies def resolve_with_cache(self, hostname: str) -> Optional[str]: """ Try to resolve using an internal cache. """ if hostname not in self.resolving_cache: self.resolving_cache[hostname] = self.resolve_without_cache(hostname) return self.resolving_cache[hostname] def resolve_without_cache(self, hostname: str) -> Optional[str]: """ Resolves the IP of the given hostname. :param hostname: The hostname to get resolve. """ def get_last_cname(subject: str, recursion_depth: int = 60) -> Optional[str]: """ Given a subject, this function tries to query the CNAME until there is none. :param subject: The first subject. """ last_cname_result = [] last_cname_new_subject = subject depth = 0 while depth < recursion_depth: local_last_cname_result = ( self.dns_query_tool.set_query_record_type("CNAME") .set_subject(last_cname_new_subject) .query() ) depth += 1 if any(x in last_cname_result for x in local_last_cname_result): break last_cname_result.extend(local_last_cname_result) if local_last_cname_result: last_cname_new_subject = local_last_cname_result[0] else: break try: return last_cname_result[-1] except IndexError: return None result = set() if not IPSyntaxChecker(hostname).is_valid(): last_cname = get_last_cname(hostname) if last_cname: result.update( self.dns_query_tool.set_query_record_type("A") .set_subject(last_cname) .query() ) else: result.update( self.dns_query_tool.set_query_record_type("A") .set_subject(hostname) .query() ) else: result.add(hostname) if result: return result.pop() return None def resolve(self, hostname: str) -> Optional[str]: """ Resolves with the prefered method. """ if hostname: if self.resolving_use_cache: return self.resolve_with_cache(hostname) return self.resolve_without_cache(hostname) return None PyFunceble-4.2.29.dev/PyFunceble/query/requests/adapter/http.py000066400000000000000000000130251467462152100244570ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the our HTTP adapter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 urllib.parse import requests import PyFunceble.facility import PyFunceble.storage from PyFunceble.query.requests.adapter.base import RequestAdapterBase class RequestHTTPAdapter(RequestAdapterBase): """ Provides our HTTP adapter. """ # pylint: disable=arguments-differ def send(self, request, **kwargs) -> requests.Response: """ Overwrite the upstream :code:`send` method. We basically do the same. We only ensure that we request the IP from the chosen DNS record. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response .. versionchanged:: 4.1.0b16 When a proxy is given, it is acceptable to have an unresolvable subject. The proxy should handle the situation and give us back a proper status or error. """ kwargs["timeout"] = self.timeout parsed_url = urllib.parse.urlparse(request.url) hostname_ip = self.resolve(parsed_url.hostname) kwargs["proxies"] = self.fetch_proxy_from_pattern(parsed_url.hostname) PyFunceble.facility.Logger.debug("Parsed URL: %r", parsed_url) PyFunceble.facility.Logger.debug("Resolved IP: %r", hostname_ip) PyFunceble.facility.Logger.debug("KWARGS: %r", kwargs) PyFunceble.facility.Logger.debug( "Pool Manager: %r", self.poolmanager.connection_pool_kw ) if hostname_ip or kwargs["proxies"]: if hostname_ip: request.url = request.url.replace( f"{parsed_url.scheme}://{parsed_url.hostname}", f"{parsed_url.scheme}://{hostname_ip}", ) # Ensure that the Hosts header is present. Otherwise, connection might # not work. request.headers["Host"] = parsed_url.hostname else: self.poolmanager.connection_pool_kw.pop( "server_hostname", PyFunceble.storage.NOT_RESOLVED_STD_HOSTNAME ) self.poolmanager.connection_pool_kw.pop( "assert_hostname", PyFunceble.storage.NOT_RESOLVED_STD_HOSTNAME ) return self.fake_response() # raise Exception(hostname_ip, parsed_url, parsed_url.hostname, kwargs) response = super().send(request, **kwargs) if hostname_ip: response.url = response.url.replace(hostname_ip, parsed_url.hostname) return response PyFunceble-4.2.29.dev/PyFunceble/query/requests/adapter/https.py000066400000000000000000000137641467462152100246540ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the our HTTPS adapter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 urllib.parse import requests import PyFunceble.facility import PyFunceble.storage from PyFunceble.query.requests.adapter.base import RequestAdapterBase class RequestHTTPSAdapter(RequestAdapterBase): """ Provides our HTTP adapter. """ # pylint: disable=arguments-differ def send(self, request, **kwargs) -> requests.Response: """ Overwrite the upstream :code:`send` method. We basically do the same. We only ensure that we request the IP from the chosen DNS record. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response .. versionchanged:: 4.1.0b16 When a proxy is given, it is acceptable to have an unresolvable subject. The proxy should handle the situation and give us back a proper status or error. """ kwargs["timeout"] = self.timeout parsed_url = urllib.parse.urlparse(request.url) hostname_ip = self.resolve(parsed_url.hostname) kwargs["proxies"] = self.fetch_proxy_from_pattern(parsed_url.hostname) PyFunceble.facility.Logger.debug("Parsed URL: %r", parsed_url) PyFunceble.facility.Logger.debug("Resolved IP: %r", hostname_ip) PyFunceble.facility.Logger.debug("KWARGS: %r", kwargs) PyFunceble.facility.Logger.debug( "Pool Manager: %r", self.poolmanager.connection_pool_kw ) if hostname_ip or kwargs["proxies"]: if hostname_ip: request.url = request.url.replace( f"{parsed_url.scheme}://{parsed_url.hostname}", f"{parsed_url.scheme}://{hostname_ip}", ) if parsed_url.scheme == "https": self.poolmanager.connection_pool_kw["server_hostname"] = ( parsed_url.hostname ) self.poolmanager.connection_pool_kw["assert_hostname"] = ( parsed_url.hostname ) # Ensure that the Hosts header is present. Otherwise, connection might # not work. request.headers["Host"] = parsed_url.hostname else: self.poolmanager.connection_pool_kw.pop( "server_hostname", PyFunceble.storage.NOT_RESOLVED_STD_HOSTNAME ) self.poolmanager.connection_pool_kw.pop( "assert_hostname", PyFunceble.storage.NOT_RESOLVED_STD_HOSTNAME ) self.poolmanager.connection_pool_kw.pop( "server_hostname", parsed_url.hostname ) self.poolmanager.connection_pool_kw.pop( "assert_hostname", parsed_url.hostname ) return self.fake_response() response = super().send(request, **kwargs) if hostname_ip: response.url = response.url.replace(hostname_ip, parsed_url.hostname) return response PyFunceble-4.2.29.dev/PyFunceble/query/requests/requester.py000066400000000000000000000431541467462152100241050ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our own requests handler Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools import logging import warnings from typing import Optional, Union import requests import requests.exceptions import urllib3.exceptions import PyFunceble.facility import PyFunceble.storage from PyFunceble.dataset.user_agent import UserAgentDataset from PyFunceble.query.dns.query_tool import DNSQueryTool from PyFunceble.query.requests.adapter.http import RequestHTTPAdapter from PyFunceble.query.requests.adapter.https import RequestHTTPSAdapter class Requester: """ Provides our very own requests handler. :param int max_retries: Optional, The maximum number of retries to perform. :param bool verify_certificate: Optional, Should we verify and validate the SSL/TLS certificate ? :param float timeout: Optional, The timeout to apply to the query. :param int max_redirects: Optional, The maximum number of redirects to allow. :param dns_query_tool: Optional, The DNS Query tool to use. :param proxy_pattern: Optional, The proxy pattern to apply to each query. Expected format: :: { "global": { # Everything under global will be used as default if no # rule matched. "http": "str" ## HTTP_PROXY "https": "str" ## HTTPS_PROXY }, "rules":[ # A set/list of rules to work with. { "http": "str" ## HTTP_PROXY when TLD is matched. "https": "str" ## HTTPS_PROXY when TLD is matched. "tld": [ "str", "str", str ] }, { "http": "str" ## HTTP_PROXY when TLD is matched. "https": "str" ## HTTPS_PROXY when TLD is matched. "tld": [ "str", "str" ] }, ] } """ STD_VERIFY_CERTIFICATE: bool = False STD_TIMEOUT: float = 3.0 STD_MAX_RETRIES: int = 3 urllib3_exceptions = urllib3.exceptions exceptions = requests.exceptions _timeout: float = 5.0 _max_retries: int = 3 _verify_certificate: bool = True _max_redirects: int = 60 _proxy_pattern: dict = {} session: Optional[requests.Session] = None dns_query_tool: Optional[DNSQueryTool] = None def __init__( self, *, max_retries: Optional[int] = None, verify_certificate: Optional[bool] = None, timeout: Optional[float] = None, max_redirects: Optional[int] = None, dns_query_tool: Optional[DNSQueryTool] = None, proxy_pattern: Optional[dict] = None, ) -> None: if max_retries is not None: self.max_retries = max_retries else: self.guess_and_set_max_retries() if verify_certificate is not None: self.verify_certificate = verify_certificate else: self.guess_and_set_verify_certificate() if timeout is not None: self.timeout = timeout else: self.guess_and_set_timeout() if max_redirects is not None: self.max_redirects = max_redirects if dns_query_tool is not None: self.dns_query_tool = dns_query_tool else: self.dns_query_tool = DNSQueryTool() if proxy_pattern is not None: self.proxy_pattern = proxy_pattern else: self.guess_and_set_proxy_pattern() self.session = self.get_session() warnings.simplefilter("ignore", urllib3.exceptions.InsecureRequestWarning) logging.getLogger("requests.packages.urllib3").setLevel(logging.CRITICAL) logging.getLogger("urllib3").setLevel(logging.CRITICAL) def recreate_session(func): # pylint: disable=no-self-argument """ Recreate a new session after executing the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) # pylint: disable=not-callable if hasattr(self, "session") and isinstance(self.session, requests.Session): self.session = self.get_session() return result return wrapper def request_factory(verb: str): # pylint: disable=no-self-argument """ Provides a universal request factory. :param verb: The HTTP Verb to apply. """ def request_method(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): # pylint: disable=no-member PyFunceble.facility.Logger.debug( "Started %r request to %r with %r", verb.upper(), args[0], kwargs, ) req = getattr(self.session, verb.lower())(*args, **kwargs) PyFunceble.facility.Logger.debug( "Finished %r request to %r with %r", verb.upper(), args[0], kwargs, ) return req return wrapper return request_method @property def max_retries(self) -> int: """ Provides the current state of the :code:`_max_retries` attribute. """ return self._max_retries @max_retries.setter @recreate_session def max_retries(self, value: int) -> None: """ Sets the max retries value to apply to all subsequent requests. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`int`. :raise ValueError: When the given :code:`value` is less than :code:`1`. """ if not isinstance(value, int): raise TypeError(f" should be {int}, {type(value)} given.") if value < 0: raise ValueError(f" ({value!r}) should be positive.") self._max_retries = value def set_max_retries(self, value: int) -> "Requester": """ Sets the max retries value to apply to all subsequent requests. :param value: The value to set. """ self.max_retries = value return self def guess_and_set_max_retries(self) -> "Requester": """ Try to guess the value from the configuration and set it. """ if PyFunceble.facility.ConfigLoader.is_already_loaded() and bool( PyFunceble.storage.CONFIGURATION.max_http_retries ): self.set_max_retries( bool(PyFunceble.storage.CONFIGURATION.max_http_retries) ) else: self.set_max_retries(self.STD_MAX_RETRIES) return self @property def max_redirects(self) -> int: """ Provides the current state of the :code:`_max_redirects` attribute. """ return self._max_redirects @max_redirects.setter @recreate_session def max_redirects(self, value: int) -> None: """ Sets the max redirects value to apply to all subsequent requests. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class:`int`. :raise ValueError: When the given :code:`value` is less than :code:`1`. """ if not isinstance(value, int): raise TypeError(f" should be {int}, {type(value)} given.") if value < 1: raise ValueError(f" ({value!r}) should not be less than 1.") self._max_redirects = value def set_max_redirects(self, value: int) -> "Requester": """ Sets the max redirects value to apply to all subsequent requests. :param value: The value to set. """ self.max_redirects = value return self @property def verify_certificate(self) -> bool: """ Provides the current state of the :code:`_verify_certificate` attribute. """ return self._verify_certificate @verify_certificate.setter @recreate_session def verify_certificate(self, value: bool) -> None: """ Enable or disables the certificate validation. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class`bool`. """ if not isinstance(value, bool): raise TypeError(f" shoule be {bool}, {type(value)} given.") self._verify_certificate = value def set_verify_certificate(self, value: bool) -> "Requester": """ Enable or disables the certificate validation. :param value: The value to set. """ self.verify_certificate = value return self def guess_and_set_verify_certificate(self) -> "Requester": """ Try to guess the value from the configuration and set it. """ if PyFunceble.facility.ConfigLoader.is_already_loaded() and bool( PyFunceble.storage.CONFIGURATION.verify_ssl_certificate ): self.set_verify_certificate( bool(PyFunceble.storage.CONFIGURATION.verify_ssl_certificate) ) else: self.set_verify_certificate(self.STD_VERIFY_CERTIFICATE) return self @property def timeout(self) -> float: """ Provides the current state of the :code:`_timeout` attribute. """ return self._timeout @timeout.setter @recreate_session def timeout(self, value: Union[int, float]) -> None: """ Enable or disables the certificate validation. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class`int` nor :py:class:`float`. :raise ValueError: Whent the given :code:`value` is less than `1`. """ if not isinstance(value, (int, float)): raise TypeError(f" shoule be {int} or {float}, {type(value)} given.") if value < 0: raise ValueError(" should not be less than 0.") self._timeout = float(value) def set_timeout(self, value: Union[int, float]) -> "Requester": """ Enable or disables the certificate validation. :param value: The value to set. """ self.timeout = value return self def guess_and_set_timeout(self) -> "Requester": """ Try to guess the value from the configuration and set it. """ if PyFunceble.facility.ConfigLoader.is_already_loaded() and bool( PyFunceble.storage.CONFIGURATION.lookup.timeout ): self.set_timeout(PyFunceble.storage.CONFIGURATION.lookup.timeout) else: self.set_timeout(self.STD_TIMEOUT) return self @property def proxy_pattern(self) -> Optional[dict]: """ Provides the current state of the :code:`_proxy_pattern` attribute. """ return self._proxy_pattern @proxy_pattern.setter @recreate_session def proxy_pattern(self, value: dict) -> None: """ Overwrite the proxy pattern to use. :param value: The value to set. :raise TypeError: When the given :code:`value` is not a :py:class`dict`. """ if not isinstance(value, dict): raise TypeError(f" shoule be {dict}, {type(value)} given.") self._proxy_pattern = value def set_proxy_pattern(self, value: dict) -> "Requester": """ Overwrite the proxy pattern. :param value: The value to set. """ self.proxy_pattern = value return self def guess_and_set_proxy_pattern(self) -> "Requester": """ Try to guess the value from the configuration and set it. """ if PyFunceble.facility.ConfigLoader.is_already_loaded() and bool( PyFunceble.storage.CONFIGURATION.proxy ): self.set_proxy_pattern(PyFunceble.storage.CONFIGURATION.proxy) else: self.set_proxy_pattern({}) return self def guess_all_settings(self) -> "Requester": """ Try to guess all settings. """ to_ignore = ["guess_all_settings"] for method in dir(self): if method in to_ignore or not method.startswith("guess_"): continue getattr(self, method)() return self def get_verify_certificate(self) -> bool: """ Provides the current value of the certificate validation. """ return self.verify_certificate def get_timeout(self) -> float: """ Provides the currently set timetout. """ return self.timeout def get_session(self) -> requests.Session: """ Provides a new session. """ session = requests.Session() session.verify = self.verify_certificate session.max_redirects = self.max_redirects session.mount( "https://", RequestHTTPSAdapter( max_retries=self.max_retries, timeout=self.timeout, dns_query_tool=self.dns_query_tool, proxy_pattern=self.proxy_pattern, ), ) session.mount( "http://", RequestHTTPAdapter( max_retries=self.max_retries, timeout=self.timeout, dns_query_tool=self.dns_query_tool, proxy_pattern=self.proxy_pattern, ), ) custom_headers = {"User-Agent": UserAgentDataset().get_latest()} session.headers.update(custom_headers) return session @request_factory("GET") def get(self, *args, **kwargs) -> requests.Response: """ Sends a GET request and get its response. """ @request_factory("OPTIONS") def options(self, *args, **kwargs) -> requests.Response: """ Sends am OPTIONS request and get its response. """ @request_factory("HEAD") def head(self, *args, **kwargs) -> requests.Response: """ Sends a HEAD request and get its response. """ @request_factory("POST") def post(self, *args, **kwargs) -> requests.Response: """ Sends a POST request and get its response. """ @request_factory("PUT") def put(self, *args, **kwargs) -> requests.Response: """ Sends a PUT request and get its response. """ @request_factory("PATCH") def patch(self, *args, **kwargs) -> requests.Response: """ Sends a PATCH request and get its response. """ @request_factory("DELETE") def delete(self, *args, **kwargs) -> requests.Response: """ Sends a DELETE request and get its response. """ PyFunceble-4.2.29.dev/PyFunceble/query/whois/000077500000000000000000000000001467462152100207635ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/query/whois/__init__.py000066400000000000000000000046611467462152100231030ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides everything related to the way we get or manipulate WHOIS record. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/query/whois/converter/000077500000000000000000000000001467462152100227725ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/query/whois/converter/__init__.py000066400000000000000000000046511467462152100251110ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the converter or extractor around the WHOIS query logic. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/query/whois/converter/base.py000066400000000000000000000104131467462152100242550ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base of all WHOIS converter/extracter class. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools from typing import Any, Optional class ConverterBase: """ Provides the base of all converter class. """ _data_to_convert: Optional[Any] = None def __init__(self, data_to_convert: Optional[Any] = None) -> None: if data_to_convert is not None: self.data_to_convert = data_to_convert def ensure_data_to_convert_is_given(func): # pylint: disable=no-self-argument """ Ensures that the data to convert is given before running the decorated method. :raise TypeError: If the subject is not a string. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self.data_to_convert, str): raise TypeError( f" should be {str}, " f"{type(self.data_to_convert)} given." ) return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @property def data_to_convert(self) -> Optional[Any]: """ Provides the current state of the :code:`_data_to_convert` attribute. """ return self._data_to_convert @data_to_convert.setter def data_to_convert(self, value: Any) -> Any: """ Sets the data to convert / to work with. :param value: The data to convert """ self._data_to_convert = value def set_data_to_convert(self, value: Any) -> "ConverterBase": """ Sets the data to convert / to work with. :param value: The data to convert """ self.data_to_convert = value return self @ensure_data_to_convert_is_given def get_converted(self) -> Optional[Any]: """ Provides the converted data. """ raise NotImplementedError() PyFunceble-4.2.29.dev/PyFunceble/query/whois/converter/digit2digits.py000066400000000000000000000065671467462152100257500ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an easy way to convert a digit string to 2 digits. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: enable=line-too-long from typing import Any from PyFunceble.query.whois.converter.base import ConverterBase class Digit2Digits(ConverterBase): """ Converts a given digit to a 2 digits string. """ @ConverterBase.data_to_convert.setter def data_to_convert(self, value: Any) -> Any: """ Overrites the default behavior. :param value: The data to convert. :raise TypeError: When the given data to convert is not :py:class:`str` """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") # pylint: disable=no-member super(Digit2Digits, self.__class__).data_to_convert.fset(self, value) @ConverterBase.ensure_data_to_convert_is_given def get_converted(self) -> str: """ Provides the converted data (after conversion) """ return str(self.data_to_convert).zfill(2) PyFunceble-4.2.29.dev/PyFunceble/query/whois/converter/expiration_date.py000066400000000000000000000321441467462152100265270ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our expiration date extracter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import List, Optional, Tuple from PyFunceble.helpers.regex import RegexHelper from PyFunceble.query.whois.converter.base import ConverterBase from PyFunceble.query.whois.converter.digit2digits import Digit2Digits from PyFunceble.query.whois.converter.month2unified import Month2Unified class ExpirationDateExtractor(ConverterBase): """ Provides an interface for the extraction of the expiration date. """ PATTERNS: List[str] = [ r"\[expires\s+on\](.*)", r"data\s+de\s+expiraรงรฃo\s+\/\s+Expiration\s+Date\s+\(dd\/mm\/yyyy\):(.*)", r"date\s+d'expiration:(.*)", r"domain_datebilleduntil:(.*)", r"Exp\s+date:(.*)", r"expiration:\.+(.*)", r"expiration\s+date:(.*)", r"expiration\s+date\s+:(.*)", r"expiration\s+time:(.*)", r"expire-date:(.*)", r"expire:(.*)", r"expire\s+date:(.*)", r"expire\s+on:(.*)", r"expired:(.*)", r"expires:(.*)", r"expires\.+:(.*)", r"expires\s+at:(.*)", r"expires\s+on:(.*)", r"expires\s+on\.+:(.*)", r"expiry\s+:(.*)", r"expiry\s+date:(.*)", r"fecha\s+de\s+expiraciรณn\s+\(expiration\s+date\):(.*)", r"fecha\s+de\s+vencimiento:(.*)", r"free-date(.*)", r"record\s+expires\s+on(.*)(\(YYYY-MM-DD\))", r"registry\s+expiry\s+date:(.*)", r"renewal:(.*)", r"renewal\s+date:(.*)", r"status:\s+OK-UNTIL(.*)", r"valid-date(.*)", r"validity:(.*)", ] """ Provides all our known patterns. """ REGEX_DIGITS: str = r"[0-9]" """ Provides the regex to match in order to extract the digits. """ MARKER2DATE_REGEX: dict = { # Date in format: 02-jan-2017 "1": r"([0-9]{2})-([a-z]{3})-([0-9]{4})", # Date in format: 02.01.2017 // Month: jan "2": r"([0-9]{2})\.([0-9]{2})\.([0-9]{4})$", # Date in format: 02/01/2017 // Month: jan "3": r"([0-3][0-9])\/(0[1-9]|1[012])\/([0-9]{4})", # Date in format: 2017-01-02 // Month: jan "4": r"([0-9]{4})-([0-9]{2})-([0-9]{2})$", # Date in format: 2017.01.02 // Month: jan "5": r"([0-9]{4})\.([0-9]{2})\.([0-9]{2})$", # Date in format: 2017/01/02 // Month: jan "6": r"([0-9]{4})\/([0-9]{2})\/([0-9]{2})$", # Date in format: 2017.01.02 15:00:00 "7": r"([0-9]{4})\.([0-9]{2})\.([0-9]{2})\s[0-9]{2}:[0-9]{2}:[0-9]{2}", # Date in format: 20170102 15:00:00 // Month: jan "8": r"([0-9]{4})([0-9]{2})([0-9]{2})\s[0-9]{2}:[0-9]{2}:[0-9]{2}", # Date in format: 2017-01-02 15:00:00 // Month: jan "9": r"([0-9]{4})-([0-9]{2})-([0-9]{2})\s[0-9]{2}:[0-9]{2}:[0-9]{2}", # Date in format: 02.01.2017 15:00:00 // Month: jan "10": r"([0-9]{2})\.([0-9]{2})\.([0-9]{4})\s[0-9]{2}:[0-9]{2}:[0-9]{2}", # Date in format: 02-Jan-2017 15:00:00 UTC "11": r"([0-9]{2})-([A-Z]{1}[a-z]{2})-([0-9]{4})\s[0-9]{2}:[0-9]{2}:[0-9]{2}\s[A-Z]{1}.*", # pylint: disable=line-too-long # noqa: E501 # Date in format: 2017/01/02 01:00:00 (+0900) // Month: jan "12": r"([0-9]{4})\/([0-9]{2})\/([0-9]{2})\s[0-9]{2}:[0-9]{2}:[0-9]{2}\s\(.*\)", # Date in format: 2017/01/02 01:00:00 // Month: jan "13": r"([0-9]{4})\/([0-9]{2})\/([0-9]{2})\s[0-9]{2}:[0-9]{2}:[0-9]{2}$", # Date in format: Mon Jan 02 15:00:00 GMT 2017 "14": r"[a-zA-Z]{3}\s([a-zA-Z]{3})\s([0-9]{2})\s[0-9]{2}:[0-9]{2}:[0-9]{2}\s[A-Z]{3}\s([0-9]{4})", # pylint: disable=line-too-long # noqa: E501 # Date in format: Mon Jan 02 2017 "15": r"[a-zA-Z]{3}\s([a-zA-Z]{3})\s([0-9]{2})\s([0-9]{4})", # Date in format: 2017-01-02T15:00:00 // Month: jan "16": r"([0-9]{4})-([0-9]{2})-([0-9]{2})T[0-9]{2}:[0-9]{2}:[0-9]{2}$", # Date in format: 2017-01-02T15:00:00Z // Month: jan${'7} "17": r"([0-9]{4})-([0-9]{2})-([0-9]{2})T[0-9]{2}:[0-9]{2}:[0-9]{2}[A-Z].*", # Date in format: 2017-01-02T15:00:00+0200 // Month: jan "18": r"([0-9]{4})-([0-9]{2})-([0-9]{2})T[0-9]{2}:[0-9]{2}:[0-9]{2}[+-][0-9]{4}", # pylint: disable=line-too-long # noqa: E501 # Date in format: 2017-01-02T15:00:00+0200.622265+03:00 // # Month: jan "19": r"([0-9]{4})-([0-9]{2})-([0-9]{2})T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9].*[+-][0-9]{2}:[0-9]{2}", # pylint: disable=line-too-long # noqa: E501 # Date in format: 2017-01-02T15:00:00+0200.622265 // Month: jan "20": r"([0-9]{4})-([0-9]{2})-([0-9]{2})T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}$", # Date in format: 2017-01-02T23:59:59.0Z // Month: jan "21": r"([0-9]{4})-([0-9]{2})-([0-9]{2})T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9].*[A-Z]", # pylint: disable=line-too-long # noqa: E501 # Date in format: 02-01-2017 // Month: jan "22": r"([0-9]{2})-([0-9]{2})-([0-9]{4})", # Date in format: 2017. 01. 02. // Month: jan "23": r"([0-9]{4})\.\s([0-9]{2})\.\s([0-9]{2})\.", # Date in format: 2017-01-02T00:00:00+13:00 // Month: jan "24": r"([0-9]{4})-([0-9]{2})-([0-9]{2})T[0-9]{2}:[0-9]{2}:[0-9]{2}[+-][0-9]{2}:[0-9]{2}", # pylint: disable=line-too-long # noqa: E501 # Date in format: 20170102 // Month: jan "25": r"(?=[0-9]{8})(?=([0-9]{4})([0-9]{2})([0-9]{2}))", # Date in format: 02-Jan-2017 "26": r"([0-9]{2})-([A-Z]{1}[a-z]{2})-([0-9]{4})$", # Date in format: 02.1.2017 // Month: jan "27": r"([0-9]{2})\.([0-9]{1})\.([0-9]{4})", # Date in format: 02 Jan 2017 "28": r"([0-9]{1,2})\s([A-Z]{1}[a-z]{2})\s([0-9]{4})", # Date in format: 02-January-2017 "29": r"([0-9]{2})-([A-Z]{1}[a-z]*)-([0-9]{4})", # Date in format: 2017-Jan-02. "30": r"([0-9]{4})-([A-Z]{1}[a-z]{2})-([0-9]{2})\.", # Date in format: Mon Jan 02 15:00:00 2017 "31": r"[a-zA-Z]{3}\s([a-zA-Z]{3})\s([0-9]{1,2})\s[0-9]{2}:[0-9]{2}:[0-9]{2}\s([0-9]{4})", # pylint: disable=line-too-long # noqa: E501 # Date in format: Mon Jan 2017 15:00:00 "32": r"()[a-zA-Z]{3}\s([a-zA-Z]{3})\s([0-9]{4})\s[0-9]{2}:[0-9]{2}:[0-9]{2}", # Date in format: January 02 2017-Jan-02 "33": r"([A-Z]{1}[a-z]*)\s([0-9]{1,2})\s([0-9]{4})", # Date in format: 2.1.2017 // Month: jan "34": r"([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{4})", # Date in format: 20170102000000 // Month: jan "35": r"([0-9]{4})([0-9]{2})([0-9]{2})[0-9]+", # Date in format: 01/02/2017 // Month: jan "36": r"(0[1-9]|1[012])\/([0-3][0-9])\/([0-9]{4})", # Date in format: January 2 2017 "37": r"([A-Z]{1}[a-z].*)\s\s([0-9]{1,2})\s([0-9]{4})", # Date in format: 2nd January 2017 "38": r"([0-9]{1,})[a-z]{1,}\s([A-Z].*)\s(2[0-9]{3})", } """ Provides all the known regex to extract the date. .. note:: The index (or key) will be used to map or group some of them later. """ REGEX_PARSE_MAP: List[dict] = [ { "regex_keys": [1, 2, 3, 10, 11, 22, 26, 27, 28, 29, 32, 34, 38], "positions": {"day": 0, "month": 1, "year": 2}, }, { "regex_keys": [14, 15, 31, 33, 36, 37], "positions": {"day": 1, "month": 0, "year": 2}, }, { "regex_keys": [ 4, 5, 6, 7, 8, 9, 12, 13, 16, 17, 18, 19, 20, 21, 23, 24, 25, 30, 35, ], "positions": {"day": 2, "month": 1, "year": 0}, }, ] """ Our parsing map. Indeed, we hava a list of regex, but no way to know how to parse them. Especially when the order (month, day, year) are different from a format to another. This variable solve that problem by interpreting all regex we previously created. """ @ConverterBase.data_to_convert.setter def data_to_convert(self, value: str) -> None: """ Sets the data to convert or work with. :param value: The record to work with. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} is given.") if not value: raise ValueError(" should not be empty.") # pylint: disable=no-member super(ExpirationDateExtractor, self.__class__).data_to_convert.fset(self, value) def __get_line(self) -> Optional[str]: """ Tries to get the expiration date line from the given record. """ for regex in self.PATTERNS: expiration_date_line = RegexHelper(r"(?i)" + regex).match( self.data_to_convert, return_match=True, rematch=True, group=0 ) if not expiration_date_line: continue return expiration_date_line return None def __get_actual_expiration_date( self, extracted: str ) -> Optional[Tuple[str, str, str]]: """ Tries to extract the actual expiration date. """ for index, date_regex in self.MARKER2DATE_REGEX.items(): matched = RegexHelper(date_regex).match( extracted, return_match=True, rematch=True ) date_parts = tuple() if not matched: continue for parse_case in self.REGEX_PARSE_MAP: if int(index) not in parse_case["regex_keys"]: continue date_parts = ( Digit2Digits( matched[parse_case["positions"]["day"]], ).get_converted(), Month2Unified( matched[parse_case["positions"]["month"]] ).get_converted(), str(matched[parse_case["positions"]["year"]]), ) if date_parts: return "-".join(date_parts) return None @ConverterBase.ensure_data_to_convert_is_given def get_converted(self) -> Optional[str]: """ Provides the expiration date of the record (if found). """ expiration_date_line = self.__get_line() if expiration_date_line: expiration_date = expiration_date_line[0].strip() if RegexHelper(self.REGEX_DIGITS).match( expiration_date, return_match=False ): return self.__get_actual_expiration_date(expiration_date) return None PyFunceble-4.2.29.dev/PyFunceble/query/whois/converter/month2unified.py000066400000000000000000000103351467462152100261210ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides a way to convert a given month to our unified format. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Any, Dict, List from PyFunceble.query.whois.converter.base import ConverterBase class Month2Unified(ConverterBase): """ Converts the given month into our unified format. """ MAP: Dict[str, List[str]] = { "jan": [str(1), "01", "jan", "january", "jan."], "feb": [str(2), "02", "feb", "february", "feb."], "mar": [str(3), "03", "mar", "march", "mar."], "apr": [str(4), "04", "apr", "april", "apr."], "may": [str(5), "05", "may"], "jun": [str(6), "06", "jun", "june", "jun."], "jul": [str(7), "07", "jul", "july", "jul."], "aug": [str(8), "08", "aug", "august", "aug."], "sep": [str(9), "09", "sep", "september", "sep.", "sept", "sept."], "oct": [str(10), "oct", "october", "oct."], "nov": [str(11), "nov", "november", "nov."], "dec": [str(12), "dec", "december", "dec."], } @ConverterBase.data_to_convert.setter def data_to_convert(self, value: Any) -> None: """ Overrites the default behavior. :raise TypeError: When the given data to convert is not :py:class:`str` """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") # pylint: disable=no-member super(Month2Unified, self.__class__).data_to_convert.fset(self, value) @ConverterBase.ensure_data_to_convert_is_given def get_converted(self) -> str: """ Provides the converted data (after conversion) .. warning:: If no month is found, the given data is given as response. """ for to_return, possibilities in self.MAP.items(): if self.data_to_convert.lower() in possibilities: return to_return return self.data_to_convert PyFunceble-4.2.29.dev/PyFunceble/query/whois/converter/registrar.py000066400000000000000000000111611467462152100253460ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our registrar extrator. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import Any, List, Optional from PyFunceble.helpers.regex import RegexHelper from PyFunceble.query.whois.converter.base import ConverterBase class RegistarExtractor(ConverterBase): """ Provides an interface for the extration of the registrar. """ PATTERNS: List[str] = [ r"authorized\s+agency(\s+|):(.*)", r"domain\s+support(\s+|):(.*)", r"registrar\s+name(\s+|):(.*)", r"registrar_name(\s+|):(.*)", r"registrar(\s+|):(.*)", r"registrar\.+(\s+|):(.*)", r"registration\s+service\s+provider(\s+|):(.*)", r"sponsoring\s+registrar(\s+|):(.*)", r"sponsoring\s+registrar\s+organization(\s+|):(.*)", ] @ConverterBase.data_to_convert.setter def data_to_convert(self, value: Any) -> None: """ Sets the data to convert and work with. :param value: The record to work with. :raise TypeError: When the given data to convert is not :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") # pylint: disable=no-member super(RegistarExtractor, self.__class__).data_to_convert.fset(self, value) def __get_line(self) -> Optional[str]: """ Tries to get the registrar line from the given record. """ for regex in self.PATTERNS: registrar_line = RegexHelper(r"(?i)" + regex).match( self.data_to_convert, return_match=True, rematch=True, group=0 ) if not registrar_line: continue return registrar_line return None @ConverterBase.ensure_data_to_convert_is_given def get_converted(self) -> Optional[str]: """ Provides the registrar of the record (if found). """ registrar_line = self.__get_line() if registrar_line: try: return [x.strip() for x in registrar_line if x.strip()][0] except IndexError: pass return None PyFunceble-4.2.29.dev/PyFunceble/query/whois/query_tool.py000066400000000000000000000344641467462152100235520ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our interface for quering the WHOIS Record of a given subject. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 functools import socket from typing import Optional, Union from PyFunceble.dataset.iana import IanaDataset from PyFunceble.query.record.whois import WhoisQueryToolRecord from PyFunceble.query.whois.converter.expiration_date import ExpirationDateExtractor from PyFunceble.query.whois.converter.registrar import RegistarExtractor # pylint: disable=protected-access class WhoisQueryTool: """ Provides the interface to get the WHOIS record of a given subject. """ BUFFER_SIZE: int = 4096 STD_PORT: int = 43 expiration_date_extractor: Optional[ExpirationDateExtractor] = None registrar_extractor: Optional[RegistarExtractor] = None iana_dataset: Optional[IanaDataset] = None _subject: Optional[str] = None _server: Optional[str] = None _query_timeout: float = 5.0 _expiration_date: Optional[str] = None _record: Optional[str] = None _registrar: Optional[str] = None lookup_record: Optional[WhoisQueryToolRecord] = None def __init__( self, subject: Optional[str] = None, *, server: Optional[str] = None, query_timeout: Optional[float] = None, ) -> None: self.registrar_extractor = RegistarExtractor() self.expiration_date_extractor = ExpirationDateExtractor() self.iana_dataset = IanaDataset() if subject is not None: self.subject = subject if server is not None: self.server = server if query_timeout is not None: self.set_query_timeout(query_timeout) def ensure_subject_is_given(func): # pylint: disable=no-self-argument """ Ensures that the subject is given before running the decorated method. :raise TypeError: If the subject is not a string. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): # pragma: no cover ## Just safety. if not isinstance(self.subject, str): raise TypeError( f" should be {str}, {type(self.subject)} given." ) return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def update_lookup_record(func): # pylint: disable=no-self-argument """ Ensures that a clean record is generated after the execution of the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) # pylint: disable=not-callable if self.lookup_record is None or self.subject != self.lookup_record.subject: self.lookup_record = WhoisQueryToolRecord(port=self.STD_PORT) self.lookup_record.subject = self.subject if self.query_timeout != self.lookup_record.query_timeout: self.lookup_record.query_timeout = self.query_timeout if self.server != self.lookup_record.server: self.lookup_record.server = self.server if self._expiration_date != self.lookup_record.expiration_date: self.lookup_record.expiration_date = self._expiration_date if self._registrar != self.lookup_record.registrar: self.lookup_record.registrar = self._registrar return result return wrapper def reset_record(func): # pylint: disable=no-self-argument """ Resets the record before executing the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): if self.lookup_record: self.lookup_record.record = self._record = None self.lookup_record.expiration_date = self._expiration_date = None self.lookup_record.registrar = self._registrar = None return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper def query_record(func): # pylint: disable=no-self-argument """ Queries the record before executing the decorated method. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): # pragma: no cover ## It just works. if not self.lookup_record or self.lookup_record.record is None: self.query() return func(self, *args, **kwargs) # pylint: disable=not-callable return wrapper @property def subject(self) -> Optional[str]: """ Provides the current state of the :code:`_subject` attribute. """ return self._subject @subject.setter @reset_record @update_lookup_record def subject(self, value: str) -> None: """ Sets the subject to work with. :param value: The subject to set. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._subject = value def set_subject(self, value: str) -> "WhoisQueryTool": """ Sets the subject to work with. :param value: The subject to set. """ self.subject = value return self @property def server(self) -> Optional[str]: """ Provides the current state of the :code:`_server` attribute. """ return self._server @server.setter @reset_record @update_lookup_record def server(self, value: str) -> None: """ Sets the server to communicate with. :param value: The server to work with. :raise TypeError: When the given :code:`value` is not a :py:class:`str`. :raise ValueError: When the given :code:`value` is empty. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") if not value: raise ValueError(" should not be empty.") self._server = value def set_server(self, value: str) -> "WhoisQueryTool": """ Sets the server to communicate with. :param value: The server to work with. """ self.server = value return self @property def query_timeout(self) -> float: """ Provides the current state of the :code:`_query_timeout` attribute. """ return self._query_timeout @query_timeout.setter def query_timeout(self, value: Union[float, int]) -> None: """ Sets the query_timeout to apply. :param value: The query_timeout to apply. :raise TypeError: When the given :code:`value` is not a :py:class:`int` nor :py:class:`float`. :raise ValueError: When the given :code:`value` is less than `1`. """ if not isinstance(value, (int, float)): raise TypeError(f" should be {int} or {float}, {type(value)} given.") if value < 0: raise ValueError(f" ({value!r}) should be less than 0.") self._query_timeout = float(value) def set_query_timeout(self, value: Union[float, int]) -> "WhoisQueryTool": """ Sets the query_timeout to apply. :param value: The query_timeout to apply. """ self.query_timeout = value return self @property @query_record @update_lookup_record def expiration_date(self) -> Optional[str]: """ Provides the current state of the :code:`_expiration_date` attribute. """ if self.lookup_record.record: self._expiration_date = self.expiration_date_extractor.set_data_to_convert( self.lookup_record.record ).get_converted() return self._expiration_date @property @query_record def record(self) -> Optional[str]: """ Provides the current state of the :code:`_record` attribute. """ return self.lookup_record.record @property @query_record @update_lookup_record def registrar(self) -> Optional[str]: """ Provides the current state of the :code:`_registrar` attribute. """ if self.lookup_record.record: self._registrar = self.registrar_extractor.set_data_to_convert( self.lookup_record.record ).get_converted() return self._registrar @ensure_subject_is_given def get_whois_server( self, ) -> Optional[str]: # pragma: no cover ## Test the underlying method instead. """ Provides the whois server to work with. """ if self.subject.endswith("."): extension = self.subject[:-1] else: extension = self.subject extension = extension[extension.rfind(".") + 1 :] return self.iana_dataset.get_whois_server(extension) def get_lookup_record( self, ) -> Optional[WhoisQueryToolRecord]: """ Provides the current query record. """ return self.lookup_record @ensure_subject_is_given @update_lookup_record def query( self, ) -> str: # pragma: no cover ## The effect of the response of this method ## are more important. """ Queries the WHOIS record and return the current object. """ if self.lookup_record.record is None: if not self.server: whois_server = self.get_whois_server() else: whois_server = self.server if whois_server: self.lookup_record.server = whois_server self.lookup_record.query_timeout = self.query_timeout req = socket.socket(socket.AF_INET, socket.SOCK_STREAM) req.settimeout(self.query_timeout) try: req.connect((whois_server, self.STD_PORT)) req.send(f"{self.subject}\r\n".encode()) response = "".encode() while True: try: data = req.recv(self.BUFFER_SIZE) except (ConnectionResetError, socket.timeout): break response += data if not data: break req.close() try: self.lookup_record.record = self._record = response.decode() except UnicodeDecodeError: # Note: Because we don't want to deal with other issue, we # decided to use `replace` in order to automatically replace # all non utf-8 encoded characters. self.lookup_record.record = self._record = response.decode( "utf-8", "replace" ) except socket.error: pass if self.lookup_record.record is None or not self.lookup_record.record: self.lookup_record.record = self._record = "" self.lookup_record.expiration_date = self._expiration_date = "" self.lookup_record.registrar = self._record = "" else: self.lookup_record.expiration_date = self.expiration_date self.lookup_record.registrar = self.registrar return self.lookup_record.record @query_record def get_record( self, ) -> Optional[str]: # pragma: no cover ## Just a dataclass attribute. """ Provides the current record. Side Effect: The record will be queried if it is non existent. """ return self.lookup_record.record PyFunceble-4.2.29.dev/PyFunceble/sessions.py000066400000000000000000000050101467462152100207010ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the location of all our sessions Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # Should be initiated by the PyFunceble.database.session module. DB_ENGINE = None DB_FACTORY = None DB_SESSION = None PyFunceble-4.2.29.dev/PyFunceble/storage.py000066400000000000000000000142131467462152100205040ustar00rootroot00000000000000# pylint:disable=invalid-name, cyclic-import """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides a central storage place. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import secrets from typing import Optional from box import Box from dotenv import load_dotenv from PyFunceble.storage_facility import get_config_directory PROJECT_NAME: str = "PyFunceble" PROJECT_VERSION: str = "4.2.29.dev (Blue Duckling: Tulip)" DISTRIBUTED_CONFIGURATION_FILENAME: str = ".PyFunceble_production.yaml" DISTRIBUTED_DIR_STRUCTURE_FILENAME: str = "dir_structure_production.json" IANA_DUMP_FILENAME: str = "iana-domains-db.json" PUBLIC_SUFFIX_DUMP_FILENAME: str = "public-suffix.json" CONFIGURATION_FILENAME: str = ".PyFunceble.yaml" CONFIGURATION_OVERWRITE_FILENAME: str = ".PyFunceble.overwrite.yaml" ENV_FILENAME: str = ".pyfunceble-env" DOWN_FILENAME: str = ".pyfunceble_intern_downtime.json" USER_AGENT_FILENAME: str = "user_agents.json" IPV4_REPUTATION_FILENAME: str = "ipv4_reputation.data" # pylint: disable=line-too-long IANA_DUMP_LINK: str = ( "https://raw.githubusercontent.com/PyFunceble/iana/master/iana-domains-db.json" ) PUBLIC_SUFFIX_DUMP_LINK: str = ( "https://raw.githubusercontent.com/PyFunceble/public-suffix/master/public-suffix.json" ) USER_AGENT_DUMP_LINK: str = ( "https://raw.githubusercontent.com/PyFunceble/user_agents/master/user_agents.json" ) IPV4_REPUTATION_DUMP_LINK: str = "https://reputation.alienvault.com/reputation.data" SHORT_REPO_LINK: str = "https://pyfunceble.github.io" REPO_LINK: str = "https://github.com/funilrys/PyFunceble" NOT_RESOLVED_STD_HOSTNAME: str = f"pyfunceble-{secrets.token_hex(12)}.com" IANA: Optional[dict] = {} PUBLIC_SUFFIX: Optional[dict] = {} USER_AGENTS: Optional[dict] = {} load_dotenv(".env") load_dotenv(ENV_FILENAME) CONFIG_DIRECTORY: str = get_config_directory( project_name=PROJECT_NAME, project_version=PROJECT_VERSION ) load_dotenv(os.path.join(CONFIG_DIRECTORY, ".env")) load_dotenv(os.path.join(CONFIG_DIRECTORY, ENV_FILENAME)) # This is for the case that the environment variable are telling us something # else. CONFIG_DIRECTORY: str = get_config_directory( project_name=PROJECT_NAME, project_version=PROJECT_VERSION ) CONFIGURATION: Optional[Box] = Box({}) FLATTEN_CONFIGURATION: Optional[dict] = {} STATUS: Optional[Box] = Box( { "up": "ACTIVE", "down": "INACTIVE", "valid": "VALID", "invalid": "INVALID", "malicious": "MALICIOUS", "sane": "SANE", }, frozen_box=True, ) HTTP_CODES: Optional[Box] = Box({}) PLATFORM: Optional[Box] = Box({}) LINKS: Optional[Box] = Box({}) PROXY: Optional[Box] = Box({}) STD_HTTP_CODES: Optional[Box] = Box( { "list": { "up": [ 100, 101, 102, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 429, ], "potentially_up": [ 300, 301, 302, 303, 304, 305, 307, 308, 403, 405, 406, 407, 408, 411, 413, 417, 418, 421, 422, 423, 424, 426, 428, 431, 500, 501, 502, 503, 504, 505, 506, 507, 508, 510, 511, ], "potentially_down": [400, 402, 404, 409, 410, 412, 414, 415, 416, 451], }, }, frozen_box=True, ) PyFunceble-4.2.29.dev/PyFunceble/storage_facility.py000066400000000000000000000113231467462152100223670ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some facilities for the storage module. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os from PyFunceble.helpers.directory import DirectoryHelper from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper from PyFunceble.utils.platform import PlatformUtility from PyFunceble.utils.version import VersionUtility def get_config_directory( *, project_name: str, project_version: str ) -> str: # pragma: no cover ## Not relevant """ Provides the location of the configuration directory. """ # pylint: disable=too-many-branches env_var_helper = EnvironmentVariableHelper() directory_helper = DirectoryHelper() if env_var_helper.set_name("PYFUNCEBLE_CONFIG_DIR").exists(): config_directory = env_var_helper.get_value() elif env_var_helper.set_name("PYFUNCEBLE_OUTPUT_DIR").exists(): config_directory = env_var_helper.get_value() elif ( VersionUtility(project_version).is_cloned() or env_var_helper.set_name("TRAVIS_BUILD_DIR").exists() or env_var_helper.set_name("CI_PROJECT_DIR").exists() and env_var_helper.set_name("GITLAB_CI").exists() ): config_directory = directory_helper.get_current(with_end_sep=True) else: if PlatformUtility.is_unix(): config_dir_path = os.path.expanduser(os.path.join("~", ".config")) if directory_helper.set_path(config_dir_path).exists(): config_directory = config_dir_path elif directory_helper.set_path(os.path.expanduser("~")).exists(): config_directory = directory_helper.join_path(".") else: config_directory = directory_helper.get_current(with_end_sep=True) elif PlatformUtility.is_windows(): if env_var_helper.set_name("APPDATA").exists(): config_directory = env_var_helper.get_value() else: config_directory = directory_helper.get_current(with_end_sep=True) else: config_directory = directory_helper.get_current(with_end_sep=True) if not config_directory.endswith(os.sep): config_directory += os.sep config_directory += project_name + os.sep if not directory_helper.set_path(config_directory).exists(): directory_helper.create() if not config_directory.endswith(os.sep): config_directory += os.sep return config_directory PyFunceble-4.2.29.dev/PyFunceble/utils/000077500000000000000000000000001467462152100176255ustar00rootroot00000000000000PyFunceble-4.2.29.dev/PyFunceble/utils/__init__.py000066400000000000000000000046461467462152100217500ustar00rootroot00000000000000# pylint: disable=invalid-name """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some global utilities. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/PyFunceble/utils/platform.py000066400000000000000000000075021467462152100220270ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides a simple way to get the current platform. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 platform class PlatformUtility: """ Provides an easy way to get the current platform. """ WINDOWS: list = ["windows"] """ Provides the list of supported windows platform. """ CYGWIN: list = ["cygwin", "cygwin_nt-10.0"] """ Provides the list of supporter cygwin platform. """ UNIX: list = ["linux", "darwin"] """ Provides the list of supported unix platform. """ MAC: list = ["darwin"] """ Provides the list of supported MAC platform. """ @staticmethod def get() -> str: """ Returns the current platform. """ return platform.system().lower() @classmethod def is_cygwin(cls) -> bool: """ Checks if the current platform is in our cygwin list. """ current_platform = cls.get() return any(x in current_platform for x in cls.CYGWIN) @classmethod def is_windows(cls) -> bool: """ Checks if the current platform is in our windows list. """ return cls.get() in cls.WINDOWS or cls.is_cygwin() @classmethod def is_unix(cls) -> bool: """ Checks if the current platform is in our unix list. """ return cls.get() in cls.UNIX @classmethod def is_mac_os(cls) -> bool: """ Checks if the current platform is in our OSX list. """ return cls.get() in cls.MAC PyFunceble-4.2.29.dev/PyFunceble/utils/profile.py000066400000000000000000000107101467462152100216360ustar00rootroot00000000000000# pylint: disable=invalid-name """ The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some global utilities. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 contextlib import cProfile import io import linecache import pstats import tracemalloc @contextlib.contextmanager def profile_it(*, sort_stats: str = "cumulative", show_callers: bool = False): """ Provides a context manager which will activates the profiling of our source code. :param sort_starts: The column to sort. :param show_callers: Authorizes the output of the callers. """ profiler = cProfile.Profile() profiler.enable() yield profiler.disable() our_stream = io.StringIO() profiler_starts = pstats.Stats(profiler, stream=our_stream) if sort_stats: profiler_starts.sort_stats(sort_stats) profiler_starts.print_stats() if show_callers: profiler_starts.print_callees() print(our_stream.getvalue()) @contextlib.contextmanager def profile_memory(stats_mode: str = "lineno", top_limit: int = 10): """ Provides a context manager which will activates memory profiling of our source code. """ tracemalloc.start() yield snapshot = tracemalloc.take_snapshot() snapshot = snapshot.filter_traces( ( tracemalloc.Filter(False, ""), tracemalloc.Filter(False, ""), tracemalloc.Filter(False, ""), ) ) top_stats = snapshot.statistics(stats_mode) print("Top %s lines" % top_limit) for index, stat in enumerate(top_stats[:top_limit], 1): frame = stat.traceback[0] print( "#%s: %s:%s: %.1f KiB" % (index, frame.filename, frame.lineno, stat.size / 1024) ) line = linecache.getline(frame.filename, frame.lineno).strip() if line: print(" %s" % line) other = top_stats[top_limit:] if other: size = sum(stat.size for stat in other) print("%s other: %.1f KiB" % (len(other), size / 1024)) total = sum(stat.size for stat in top_stats) print("Total allocated size: %.1f KiB" % (total / 1024)) PyFunceble-4.2.29.dev/PyFunceble/utils/version.py000066400000000000000000000202631467462152100216670ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides an interface for version comparison or manipulation. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import List, Optional, Tuple import packaging.version from PyFunceble.helpers.directory import DirectoryHelper from PyFunceble.helpers.file import FileHelper class VersionUtility: """ Provides an interface to compare or manipulate a version. :param local_version: The local version to work with. :ivar local_version: The version we are currently working with. """ _local_version: Optional[str] = None def __init__(self, local_version: Optional[str] = None) -> None: if local_version: self.local_version = local_version @property def local_version(self) -> Optional[str]: """ Provides the current state of the :code:`_local_version` attribute. """ return self._local_version @local_version.setter def local_version(self, value: str) -> None: """ Sets the local version to work with. :param value: The local version to work with. :raise TypeError: When :code:`value` is not :py:class:`str`. """ if not isinstance(value, str): raise TypeError(f" should be {str}, {type(value)} given.") self._local_version = value @property def real_local_version(self) -> str: """ Provides the real local version. """ return self.get_real_parsed_version(self.local_version) def set_local_version(self, value: str) -> "VersionUtility": """ Sets the local version to work with. :param value: The local version to work with. """ self.local_version = value return self @staticmethod def get_splitted(version: str) -> Tuple[List[str], str]: """ Splits the version from its code name. :param version: The version to split. :return: A tuple. The first index is the digit part of the version, when the second one is the the non-digit part of the version. As example if :code:`1.0.0. Hello World` is given, this method will output: :: ([1,0,0], " Hello World") """ splitted_version: List[str] = version.split(".") def get_version_part() -> List[str]: """ Provides the version part. """ return [x for x in splitted_version if x.isdigit() or x[0].isdigit()] def get_codename_part() -> str: """ Provides the codename part. """ try: return [ x for x in splitted_version if not x.isdigit() and not x[0].isdigit() ][0] except IndexError: return "" return get_version_part(), get_codename_part() def get_real_parsed_version(self, version: str) -> str: """ Provides the real version to work with. :param version: The version to parse. """ return ".".join(self.get_splitted(version)[0]) def literally_compare(self, upstream_version: str) -> bool: """ Compares :code:`new_version` with the given base version. :param new_version: The new version to compare with. :return: - :code:`True`: base version == upstream version - :code:`False`: base version != upstream version """ return self.local_version == upstream_version def is_older_than(self, upstream_version: str) -> bool: """ Compares if the local version is older that the given one. """ return packaging.version.parse( self.real_local_version ) < packaging.version.parse(self.get_real_parsed_version(upstream_version)) def is_equal_to(self, upstream_version: str) -> bool: """ Compares if the local version is equal the given one. """ return packaging.version.parse( self.real_local_version ) == packaging.version.parse(self.get_real_parsed_version(upstream_version)) def is_recent(self, upstream_version: str) -> bool: """ Compares if the upstream version is older that the given one. """ return packaging.version.parse( self.get_real_parsed_version(upstream_version) ) < packaging.version.parse(self.real_local_version) def is_dev(self) -> bool: """ Checks if the local version is the dev one. """ return self.get_splitted(self.local_version)[-1].strip().startswith("dev") def is_master(self) -> bool: """ Checks if the local version is the master one. """ return self.get_splitted(self.local_version)[-1].startswith(" ") @staticmethod def is_cloned() -> bool: # pragma: no cover ## Only used by 1 thing for dev. """ Checks if the local version is a cloned (from git) one. """ file_helper = FileHelper() directory_helper = DirectoryHelper() if not directory_helper.set_path(".git").exists(): return False list_of_files = [ ".coveragerc", ".gitignore", "alembic.ini", "CODE_OF_CONDUCT.md", "CONTRIBUTING.md", "CONTRIBUTORS.md", "MANIFEST.in", "README.md", "requirements.txt", "setup.py", "version.yaml", ] list_of_dirs = ["docs", "PyFunceble", "tests", ".github"] if not all(file_helper.set_path(x).exists() for x in list_of_files): return False if not all(directory_helper.set_path(x).exists() for x in list_of_dirs): return False return True PyFunceble-4.2.29.dev/README.md000066400000000000000000001053511467462152100157150ustar00rootroot00000000000000![image](https://raw.githubusercontent.com/PyFunceble/logo/dev/Green/HD/RM.png) # The tool to check the availability or syntax of domain, IP or URL [![image](https://img.shields.io/badge/code%20style-black-000000.png)](https://github.com/ambv/black) [![image](https://coveralls.io/repos/github/funilrys/PyFunceble/badge.png?branch=dev)](https://coveralls.io/github/funilrys/PyFunceble?branch=dev) [![image](https://img.shields.io/github/license/funilrys/PyFunceble.png)](https://github.com/funilrys/PyFunceble/blob/dev/LICENSE) [![image](https://img.shields.io/pypi/v/pyfunceble-dev.png)](https://pypi.org/project/pyfunceble-dev) [![image](https://img.shields.io/github/issues/funilrys/PyFunceble.png)](https://github.com/funilrys/PyFunceble/issues) [![image](https://static.pepy.tech/badge/pyfunceble-dev)](https://pepy.tech/project/pyfunceble-dev) [![image](https://static.pepy.tech/badge/pyfunceble-dev/month)](https://pepy.tech/project/pyfunceble-dev) [![image](https://static.pepy.tech/badge/pyfunceble-dev/week)](https://pepy.tech/project/pyfunceble-dev) **PyFunceble** aims to provide an accurate availability check through the usage of multiple sources which are for example - to only list a few: - the WHOIS record(s). - the DNS record(s). - the HTTP status code. PyFunceble can be included in your existing project through: - its standard built-in CLI implementation. - its [Python API](https://docs.pyfunceble.com/develop/getting-started.html). - the [PyFunceble web-worker](https://github.com/pyfunceble/web-worker) project that provides the core functionalities of PyFunceble behind a web API. The PyFunceble CLI can test from a hosts file, a plain list of subjects, an AdBlock filter list or even an RPZ record. As of today, PyFunceble is running actively - if not daily - within several servers, laptops, PCs, and Raspberry Pis. It is even used - thanks to our auto continue mechanism - with CI engines like GitHub Action, Travis CI, or GitLab CI. Happy testing with PyFunceble! [![image](https://github.com/PyFunceble/gifs/raw/master/repo-showcase.gif)](https://github.com/PyFunceble/gifs/raw/master/repo-showcase.gif) # Table of Content - [The tool to check the availability or syntax of domain, IP or URL](#the-tool-to-check-the-availability-or-syntax-of-domain-ip-or-url) - [Table of Content](#table-of-content) - [Installation](#installation) - [Packages \& Versioning](#packages--versioning) - [PyPi - Python Package Index](#pypi---python-package-index) - [pyfunceble](#pyfunceble) - [pyfunceble-dev](#pyfunceble-dev) - [Container Image Registry](#container-image-registry) - [pyfunceble](#pyfunceble-1) - [Docker Hub](#docker-hub) - [pyfunceble-dev](#pyfunceble-dev-1) - [Docker Hub](#docker-hub-1) - [ArchLinux](#archlinux) - [Git Repository](#git-repository) - [pyfunceble](#pyfunceble-2) - [GitHub](#github) - [GitLab](#gitlab) - [pyfunceble-dev](#pyfunceble-dev-2) - [GitHub](#github-1) - [GitLab](#gitlab-1) - [From Source](#from-source) - [Usage](#usage) - [Common Setups](#common-setups) - [Container Image Setups](#container-image-setups) - [Data Persitence](#data-persitence) - [Common Examples](#common-examples) - [Documentation as the place to be!](#documentation-as-the-place-to-be) - [Supporting the project](#supporting-the-project) - [Contributors](#contributors) - [Special Thanks](#special-thanks) - [License](#license) # Installation ## Packages & Versioning This project follows the semver standard. PyFunceble is distributed through 2 packages that reflects our 2 main development and deployment branches. Both packages are stable but with 2 different phylosophies. Therefore, the choice is up to you. The 2 packages are `pyfunceble` and `pyfunceble-dev`. If you want a **stable** but **mature**, and **slowly** updating package, you should install the `pyfunceble` package. It reflects the `master` branch which only get updated once the new features and bugfixes of `pyfunceble-dev` are tested long enough to be considered mature. On the other hand, if you want a **stable** but **fast** updating package, you should install the `pyfunceble-dev` package. It reflects the `dev` branch which get updated frequently to allow the community to provide feedbacks as soon as possible. **Recommendation:** For most people the `pyfunceble` package should be sufficient. But if you want to help the community or always want to have the latest features and bugfix as soon as possible, you should prefer the `pyfunceble-dev` package. ## PyPi - Python Package Index Installing from the Python Package Index is for most people the prefered one - after the OS specific packages _(see below)_. Here is an overview of the packages and where they are hosted. | Package | PyPi Link | |----------------|------------------------------------------| | pyfunceble | https://pypi.org/project/PyFunceble | | pyfunceble-dev | https://pypi.org/project/PyFunceblee-dev | ### pyfunceble You can install the **pyfunceble** through `pip3`: ```shell pip3 install --user pyfunceble ``` ### pyfunceble-dev You can install the **pyfunceble-dev** package through `pip3`: ```shell pip3 install --user pyfunceble-dev ``` If you want to help and use the unstable pre-releases, you should install with the `--pre` argument. ```shell pip3 install --user --pre pyfunceble-dev ``` ## Container Image Registry Installing from a Container Image Registry is the way to go if you are in a hurry or always want the best from the beat without having to look if an update is available. :smile: Here is an overview of the packages and where they are hosted. | Host | Package | Link | |------------|----------------|----------------------------------------------------------------------------------------------------------| | Docker Hub | pyfunceble | [https://hub.docker.com/r/pyfunceble/pyfunceble](https://hub.docker.com/r/pyfunceble/pyfunceble) | | Docker Hub | pyfunceble-dev | [https://hub.docker.com/r/pyfunceble/pyfunceble-dev](https://hub.docker.com/r/pyfunceble/pyfunceble-dev) | ### pyfunceble #### Docker Hub You can install the **pyfunceble** image from Docker Hub through `docker`: ```shell docker pull pyfunceble/pyfunceble ``` ### pyfunceble-dev #### Docker Hub You can install the **pyfunceble-dev** image from Docker Hub through `docker`: ```shell docker pull pyfunceble/pyfunceble-dev ``` ## ArchLinux For the **`pyfunceble`** package: ```shell aur-helper -S pyfunceble pyfunceble --version ``` For the **`pyfunceble-dev`** package: ```shell aur-helper -S pyfunceble-dev pyfunceble --version ``` ## Git Repository Installing from a Git Repository with `pip3` is not recommended for general user as you will get the latest development patches even before they get published. But if you are one of those who always want to be in sync with the latest development patches, this is probably for you. Here is an overview of the packages and where they are hosted. | Host | Package | Repository | |--------|----------------|-------------------------------------------------------------------------| | GitHub | pyfunceble | `git+https://github.com/funilrys/PyFunceble.git@master#egg=PyFunceble` | | GitHub | pyfunceble-dev | `git+https://github.com/funilrys/PyFunceble.git@dev#egg=PyFunceble-dev` | | GitLab | pyfunceble | `git+https://gitlab.com/funilrys/PyFunceble.git@master#egg=PyFunceble` | | GitLab | pyfunceble-dev | `git+https://gitlab.com/funilrys/PyFunceble.git@dev#egg=PyFunceble-dev` | ### pyfunceble #### GitHub You can install the **pyfunceble** package from GitHub through `pip3`: ```shell pip3 install --user git+https://github.com/funilrys/PyFunceble.git@master#egg=PyFunceble ``` #### GitLab You can install the **pyfunceble** package from GitLab through `pip3`: ```shell pip3 install --user git+https://gitlab.com/funilrys/PyFunceble.git@master#egg=PyFunceble ``` ### pyfunceble-dev #### GitHub You can install the **pyfunceble-dev** package from GitHub through `pip3`: ```shell pip3 install --user git+https://github.com/funilrys/PyFunceble.git@dev#egg=PyFunceble-dev ``` #### GitLab You can install the **pyfunceble-dev** package from GitLab through `pip3`: ```shell pip3 install --user git+https://gitlab.com/funilrys/PyFunceble.git@dev#egg=PyFunceble-dev ``` ## From Source Installing from source is not recommended at all as you may need to keep the repository up-to-date by yourself. Here is an overview of the packages and where they are hosted. | Host | Package | Branch | Repository | | ------ | -------------- | -------- | -------------------------------------------------------------------------------------------------------- | | GitHub | pyfunceble | `master` | [https://github.com/funilrys/PyFunceble/tree/master](https://github.com/funilrys/PyFunceble/tree/master) | | GitHub | pyfunceble-dev | `dev` | [https://github.com/funilrys/PyFunceble/tree/dev](https://github.com/funilrys/PyFunceble/tree/dev) | | GitLab | pyfunceble | `master` | [https://gitlab.com/funilrys/PyFunceble/tree/master](https://gitlab.com/funilrys/PyFunceble/tree/master) | | GitLab | pyfunceble-dev | `dev` | [https://gitlab.com/funilrys/PyFunceble/tree/master](https://gitlab.com/funilrys/PyFunceble/tree/master) | You can install the package from source through `pip3`: ```shell pip3 install --user https://github.com/funilrys/PyFunceble/archive/{{branch}}.zip # From Github pip3 install --user https://gitlab.com/funilrys/PyFunceble/-/archive/{{branch}}/PyFunceble-{{branch}}.zip # From GitLab ``` # Usage ## Common Setups If you installed PyFunceble through any other method that doesn't involve a container image, you can use PyFunceble "normally" through the `pyfunceble` executable. ```sh pyfunceble --help ``` ## Container Image Setups If you installed PyFunceble through the container image registry method, you can run pyfunceble through: ```sh docker run -it pyfunceble/pyfunceble[-dev] --help ``` **Beware:** if the first parameter starts with a slash (`/`), the entrypoint will assume that you want to run a command within the container. ### Data Persitence If you wish to persist your data, you simply have to mount a volume to the `/home/pyfunceble` directory. Example: ```sh mkdir -p pyf-data echo "example.com" > pyf-data/test.list docker run -v pyf-data:/home/pyfunceble -it pyfunceble/pyfunceble[-dev] -f /home/pyf-data/test.list ``` ## Common Examples Here are some examples to get started. Check the availability of 'example.com'. $ pyfunceble -d example.com Check the availability of 'example.com' with a simple (stdout) output. $ pyfunceble -s -d example.com Check the availability of 'example.com' with extended (stdout) output. $ pyfunceble -a -d example.com Check the availability of 'example.com' and 'example.org'. $ pyfunceble -d example.com example.org Check the availability of 'https://example.com'. $ pyfunceble -u https://example.com Check the availability of 'https://example.com' and 'https://example.org'. $ pyfunceble -u https://example.com https://example.com Check the syntax of 'example.com'. $ pyfunceble --syntax -d example.com Check the reputation of 'example.com'. $ pyfunceble --reputation -d example.com Check the availability of all subjects in the 'myhosts' file. $ pyfunceble -f myhosts Check the availability of all subjects in the 'myhosts' and 'yourhosts' files. $ pyfunceble -f myhosts yourhosts Check the availability of all (decoded) subject of the adblock filter list 'myadblock'. $ pyfunceble --adblock -f myadblock # Documentation as the place to be! Want to know more about details **PyFunceble**? I invite you to read the documentation at [docs.pyfunceble.com](https://docs.pyfunceble.com)! Want a local copy? I get you covered! If you want to run the documentation locally, you can do so by following the instructions below. Through Docker: ```shell docker run -it -p 8080:80 pyfunceble/docs # Open Documentation with browser: http://localhost:8080 palemoon http://127.0.0.1:8000 ``` From source: ```shell # Install dependencies. pip install --user -r requirements.docs.txt # Serve documentation locally. mkdocs serve # Open Documentation with browser. palemoon http://127.0.0.1:8000 ``` **NOTE:** You are also invited to submit changes and improvement to the documentation through a new Pull Request. # Supporting the project [PyFunceble](https://github.com/funilrys/PyFunceble), [Dead-Hosts](https://github.com/dead-hosts), [adblock-decoder](https://github.com/pyunceble/adblock-decoder) and all other analog projects are powered by free time and a lot of coffee! This project helps you and you have to possibility to help back financially? Sponsor [@funilrys](https://github.com/funilrys) through the GitHub Sponsor program by clicking the image below! [![image](https://github.blog/de/wp-content/uploads/sites/3/2019/05/mona-heart-featured.png?w=200)](https://github.com/sponsors/funilrys) # Contributors Thanks to those awesome peoples for their awesome and crazy idea(s), contribution(s) and or issue report which made or make [PyFunceble](https://github.com/funilrys/PyFunceble) a better tool.
Avinash Reddy
Avinash Reddy

๐Ÿ›
BigDargon
BigDargon

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ฃ โš ๏ธ
Fanboynz
Fanboynz

๐Ÿ› ๐Ÿค” ๐Ÿ’ต โš ๏ธ ๐Ÿ““
Haris Guลกiฤ‡
Haris Guลกiฤ‡

๐Ÿ“– ๏ธ๏ธ๏ธ๏ธโ™ฟ๏ธ ๐Ÿ”ง โš ๏ธ ๐Ÿ“น โœ… ๐Ÿ’ป
Imre Eilertsen
Imre Eilertsen

๏ธ๏ธ๏ธ๏ธโ™ฟ๏ธ ๐Ÿ› ๐Ÿ”ฃ ๐Ÿ’ก ๐Ÿ’ต ๐Ÿค” ๐Ÿ“ฃ ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ง โš ๏ธ ๐Ÿ““
Kowith Singkornkeeree
Kowith Singkornkeeree

๐Ÿ›
Mitchell Krog
Mitchell Krog

๏ธ๏ธ๏ธ๏ธโ™ฟ๏ธ ๐Ÿ› ๐Ÿ“ ๐Ÿ’ป ๐Ÿ–‹ ๐Ÿ”ฃ ๐Ÿ“– ๐ŸŽจ ๐Ÿ’ก ๐Ÿ” ๐Ÿค” ๐Ÿš‡ ๐Ÿง‘โ€๐Ÿซ ๐Ÿ“ฆ ๐Ÿ”Œ ๐Ÿ“ฃ ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ง โš ๏ธ โœ… ๐Ÿ“ข ๐Ÿ““
Nilsonfsilva
Nilsonfsilva

๐Ÿ› ๐Ÿš‡ ๐Ÿ“ฆ ๐Ÿ”ง โš ๏ธ
Odyseus
Odyseus

๐Ÿ› โš ๏ธ
Reza Rizqullah
Reza Rizqullah

๐ŸŽจ ๐Ÿ’ป
ScriptTiger
ScriptTiger

๐Ÿ› ๐Ÿค” โš ๏ธ
Stephan van Ruth
Stephan van Ruth

๐Ÿ› โš ๏ธ
Steven Black
Steven Black

๐Ÿค” ๐Ÿ’ต
T145
T145

๐Ÿ› ๐Ÿค”
WaLLy3K
WaLLy3K

๐Ÿ› ๐Ÿค”
Yuki2718
Yuki2718

๐Ÿ› โš ๏ธ
Zachinquarantine
Zachinquarantine

๐Ÿ’ป
ZeroDot1
ZeroDot1

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ โš ๏ธ ๐Ÿ’ป
avatartw
avatartw

๐Ÿ›
dnmTX
dnmTX

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ฃ โš ๏ธ
gwarser
gwarser

๐Ÿ› ๐Ÿ”ฃ โš ๏ธ
hawkeye116477
hawkeye116477

๐Ÿ›
jawz101
jawz101

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ ๐Ÿ”ฃ
keczuppp
keczuppp

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ โš ๏ธ ๐Ÿ”ฃ
opav
opav

๐Ÿ› โš ๏ธ
rusty-snake
rusty-snake

๐Ÿ› ๐Ÿ“–
smed79
smed79

๐Ÿ› ๐Ÿค” ๐Ÿ’ป ๐Ÿ’ฌ โš ๏ธ
speedmann
speedmann

๐Ÿ› โš ๏ธ
spirillen
spirillen

๏ธ๏ธ๏ธ๏ธโ™ฟ๏ธ ๐Ÿ› ๐Ÿ’ป ๐Ÿ–‹ ๐Ÿ”ฃ ๐Ÿ“– ๐Ÿ’ก ๐Ÿค” ๐Ÿšง ๐Ÿง‘โ€๐Ÿซ ๐Ÿ“ฃ ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ง โš ๏ธ โœ… ๐Ÿ“ข ๐Ÿ““
watchman-pypi
watchman-pypi

๐Ÿ›
xxcriticxx
xxcriticxx

๐Ÿ› ๐Ÿค” โš ๏ธ
# Special Thanks Thanks to those awesome organization(s), tool(s) and or people(s) for - Their awesome documentation - Their awesome repository - Their awesome tool/software/source code - Their breaking reports - Their contributions - Their current work/purpose - Their promotion of Py-Funceble - Their support - Their testings reports which helped and/or still help me build, test and or make [PyFunceble](https://github.com/funilrys/PyFunceble) a better tool. - Adam Warner - [@PromoFaux](https://github.com/PromoFaux) - Adblock Plus - [@adblockplus](https://github.com/adblockplus) - asciinema - [@asciinema](https://github.com/asciinema) - Bob Halley - [@rthalley](https://github.com/rthalley) ([DNSPython](https://github.com/rthalley/dnspython)) - Chris Griffith - [@cdgriffith](https://github.com/cdgriffith) ([Box](https://github.com/cdgriffith/Box)) - Daniel - [@dnmTX](https://github.com/dnmTX) - Jonathan Hartley - [@tartley](https://github.com/tartley) ([colorama](https://github.com/tartley/colorama)) - [IANA](https://www.iana.org/) - [ICANN](https://www.icann.org/) ([Root Zone Database](https://www.iana.org/domains/root/db)) - [Iterative](https://github.com/iterative) ([shtab](https://github.com/iterative/shtab)) - Kenneth Reitz - [@kennethreitz](https://github.com/kennethreitz) ([requests](https://github.com/kennethreitz/requests)) - Mitchell Krog - [@mitchellkrogza](https://github.com/mitchellkrogza) - Mohammad Fares - [@faressoft](https://github.com/faressoft) ([Terminalizer](https://github.com/faressoft/terminalizer)) - Pi-Hole - [@pi-hole](https://github.com/pi-hole/pi-hole) - Public Suffix List - [@publicsuffix](https://github.com/publicsuffix) - Reza Rizqullah - [@ybreza](https://github.com/ybreza) - Saurabh Kumar - [@theskumar](https://github.com/theskumar) ([python-dotenv](https://github.com/theskumar/python-dotenv)) - ScriptTiger - [@ScriptTiger](https://github.com/ScriptTiger) - SMed79 - [@SMed79](https://github.com/SMed79) - spirillen - [@spirillen](https://www.mypdns.org/p/Spirillen/) - The YAML Project - [@yaml](https://github.com/yaml) ([pyyaml](https://github.com/yaml/pyyaml)) - [yWorks](https://www.yworks.com) - ([yEd Graph Editor](https://www.yworks.com/products/yed)) # License Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. PyFunceble-4.2.29.dev/alembic.ini000066400000000000000000000036641467462152100165370ustar00rootroot00000000000000# A generic, single database configuration. [alembic] # path to migration scripts script_location = PyFunceble/data/alembic # template used to generate migration files # file_template = %%(rev)s_%%(slug)s # timezone to use when rendering the date # within the migration file as well as the filename. # string value is passed to dateutil.tz.gettz() # leave blank for localtime # timezone = # max length of characters to apply to the # "slug" field # truncate_slug_length = 40 # set to 'true' to run the environment during # the 'revision' command, regardless of autogenerate # revision_environment = false # set to 'true' to allow .pyc and .pyo files without # a source .py file to be detected as revisions in the # versions/ directory # sourceless = false # version location specification; this defaults # to alembic/versions. When using multiple version # directories, initial revisions must be specified with --version-path # version_locations = %(here)s/bar %(here)s/bat alembic/versions # the output encoding used when revision files # are written from script.py.mako # output_encoding = utf-8 [post_write_hooks] # post_write_hooks defines scripts or Python functions that are run # on newly generated revision scripts. See the documentation for further # detail and examples # format using "black" - use the console_scripts runner, against the "black" entrypoint # hooks=black # black.type=console_scripts # black.entrypoint=black # black.options=-l 79 # Logging configuration [loggers] keys = root,sqlalchemy,alembic [handlers] keys = console [formatters] keys = generic [logger_root] level = WARN handlers = console qualname = [logger_sqlalchemy] level = WARN handlers = qualname = sqlalchemy.engine [logger_alembic] level = INFO handlers = qualname = alembic [handler_console] class = StreamHandler args = (sys.stderr,) level = NOTSET formatter = generic [formatter_generic] format = %(levelname)-5.5s [%(name)s] %(message)s datefmt = %H:%M:%S PyFunceble-4.2.29.dev/docs/000077500000000000000000000000001467462152100153615ustar00rootroot00000000000000PyFunceble-4.2.29.dev/docs/about/000077500000000000000000000000001467462152100164735ustar00rootroot00000000000000PyFunceble-4.2.29.dev/docs/about/contributors.md000066400000000000000000000454251467462152100215640ustar00rootroot00000000000000# Contributors Thanks to those awesome peoples for their awesome and crazy idea(s), contribution(s) and or issue report which made or make PyFunceble a better tool.
Avinash Reddy
Avinash Reddy

๐Ÿ›
BigDargon
BigDargon

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ฃ โš ๏ธ
Fanboynz
Fanboynz

๐Ÿ› ๐Ÿค” ๐Ÿ’ต โš ๏ธ ๐Ÿ““
Haris Guลกiฤ‡
Haris Guลกiฤ‡

๐Ÿ“– ๏ธ๏ธ๏ธ๏ธโ™ฟ๏ธ ๐Ÿ”ง โš ๏ธ ๐Ÿ“น โœ… ๐Ÿ’ป
Imre Eilertsen
Imre Eilertsen

๏ธ๏ธ๏ธ๏ธโ™ฟ๏ธ ๐Ÿ› ๐Ÿ”ฃ ๐Ÿ’ก ๐Ÿ’ต ๐Ÿค” ๐Ÿ“ฃ ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ง โš ๏ธ ๐Ÿ““
Kowith Singkornkeeree
Kowith Singkornkeeree

๐Ÿ›
Mitchell Krog
Mitchell Krog

๏ธ๏ธ๏ธ๏ธโ™ฟ๏ธ ๐Ÿ› ๐Ÿ“ ๐Ÿ’ป ๐Ÿ–‹ ๐Ÿ”ฃ ๐Ÿ“– ๐ŸŽจ ๐Ÿ’ก ๐Ÿ” ๐Ÿค” ๐Ÿš‡ ๐Ÿง‘โ€๐Ÿซ ๐Ÿ“ฆ ๐Ÿ”Œ ๐Ÿ“ฃ ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ง โš ๏ธ โœ… ๐Ÿ“ข ๐Ÿ““
Nilsonfsilva
Nilsonfsilva

๐Ÿ› ๐Ÿš‡ ๐Ÿ“ฆ ๐Ÿ”ง โš ๏ธ
Odyseus
Odyseus

๐Ÿ› โš ๏ธ
Reza Rizqullah
Reza Rizqullah

๐ŸŽจ ๐Ÿ’ป
ScriptTiger
ScriptTiger

๐Ÿ› ๐Ÿค” โš ๏ธ
Stephan van Ruth
Stephan van Ruth

๐Ÿ› โš ๏ธ
Steven Black
Steven Black

๐Ÿค” ๐Ÿ’ต
T145
T145

๐Ÿ› ๐Ÿค”
WaLLy3K
WaLLy3K

๐Ÿ› ๐Ÿค”
Yuki2718
Yuki2718

๐Ÿ› โš ๏ธ
Zachinquarantine
Zachinquarantine

๐Ÿ’ป
ZeroDot1
ZeroDot1

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ โš ๏ธ ๐Ÿ’ป
avatartw
avatartw

๐Ÿ›
dnmTX
dnmTX

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ฃ โš ๏ธ
gwarser
gwarser

๐Ÿ› ๐Ÿ”ฃ โš ๏ธ
hawkeye116477
hawkeye116477

๐Ÿ›
jawz101
jawz101

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ ๐Ÿ”ฃ
keczuppp
keczuppp

๐Ÿ› ๐Ÿค” ๐Ÿ’ฌ โš ๏ธ ๐Ÿ”ฃ
opav
opav

๐Ÿ› โš ๏ธ
rusty-snake
rusty-snake

๐Ÿ› ๐Ÿ“–
smed79
smed79

๐Ÿ› ๐Ÿค” ๐Ÿ’ป ๐Ÿ’ฌ โš ๏ธ
speedmann
speedmann

๐Ÿ› โš ๏ธ
spirillen
spirillen

๏ธ๏ธ๏ธ๏ธโ™ฟ๏ธ ๐Ÿ› ๐Ÿ’ป ๐Ÿ–‹ ๐Ÿ”ฃ ๐Ÿ“– ๐Ÿ’ก ๐Ÿค” ๐Ÿšง ๐Ÿง‘โ€๐Ÿซ ๐Ÿ“ฃ ๐Ÿ’ฌ ๐Ÿ‘€ ๐Ÿ”ง โš ๏ธ โœ… ๐Ÿ“ข ๐Ÿ““
watchman-pypi
watchman-pypi

๐Ÿ›
xxcriticxx
xxcriticxx

๐Ÿ› ๐Ÿค” โš ๏ธ
PyFunceble-4.2.29.dev/docs/about/history.md000066400000000000000000000062521467462152100205230ustar00rootroot00000000000000# History and Origins PyFunceble is the little sister of [Funceble](https://github.com/funilrys/funceble) which was archived on 13th March 2018. In March 2018, because Funceble was starting to become a huge unmanageable script, I - Nissar Chababy aka [@funilrys](https://github.com/funilrys) - decided to make it a Python tool while extending my Python knowledge. It was meant for my own use case. Back then, my problem was that I didn't want to download a huge hosts file knowing that most of the entries do not exist or are not reachable - anymore. That's how Py-Funceble started. My objective - now - through this tool is to provide a tool and a Python API which helps the world test the availability of domains, IPs and URL through the gathering and interpretation of information from existing tools or protocols like WHOIS records, DNS lookup, or even HTTP status codes. The base of this tool was my idea. But as with many Open Source projects, communities, or individuals, we evolve with the people we meet, exchange with or just discuss with privately. PyFunceble was and is still not an exception to that. My main idea was to check the availability of domains in a hosts files. But 3 years later, PyFunceble is now capable of a lot including: - The testing of domains, IPs, and URLs. - The checking of the syntax or reputation of a domain, IP, and URL. - The decoding of AdBlock filters, RPZ records, hosts or plain files before a test from the CLI. PyFunceble evolved and will probably continue to evolve with the time and the people using it. In June 2020, the PyFunceble-dev PyPI package - which gets everything as soon as possible compared to the PyFunceble (stable) package - reached 1 million total downloads. I never noticed it until I was reached by someone informing me of it. But, I was shocked. I never thought that something I built from A to Z in my free time will ever reach that point. I was thankful to that nice person for informing me of it. But at the same time concerned about PyFunceble and how it will evolve. That's why I started the development of PyFunceble 4.0.0. My idea as I was refactoring it was to provide a better Python API and implementation of my core ideas along with a better incorporation and extension capability. Indeed, in the last few years, I was so much obsessed with the CLI that I really never wrote each component individually. They were all dependent - if not part of - the CLI. With 4.0.0, you can now import one of the components of PyFunceble and start straight away. No real need to play with the configuration unless you want something very specific. That's how I see the future of PyFunceble. As of today, PyFunceble is running actively - if not daily - within several servers, laptops, PCs, and Raspberry Pis. It is even used - thanks to our auto continue dataset and component - with CI engines like GitHub Action, Travis CI, and GitLab CI. PyFunceble is my tool. But it is indirectly also become yours. Therefore, I invite you to let me know how you use PyFunceble or simply open a discussion - or join an existing one - about anything you do with PyFunceble. But also anything that you - would - like - or dislike - in PyFunceble. Happy testing with PyFunceble! PyFunceble-4.2.29.dev/docs/about/license.md000066400000000000000000000012101467462152100204310ustar00rootroot00000000000000# License Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 - [https://www.apache.org/licenses/LICENSE-2.0](https://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. PyFunceble-4.2.29.dev/docs/about/special-thanks.md000066400000000000000000000043121467462152100217230ustar00rootroot00000000000000# Special Thanks Thanks to those awesome organization(s), tool(s) and or people(s) for - Their awesome documentation - Their awesome repository - Their awesome tool/software/source code - Their breaking reports - Their contributions - Their current work/purpose - Their promotion of Py-Funceble - Their support - Their testings reports which helped and/or still help me build, test and or make [PyFunceble](https://github.com/funilrys/PyFunceble) a better tool. - Adam Warner - [@PromoFaux](https://github.com/PromoFaux) - Adblock Plus - [@adblockplus](https://github.com/adblockplus) - asciinema - [@asciinema](https://github.com/asciinema) - Bob Halley - [@rthalley](https://github.com/rthalley) ([DNSPython](https://github.com/rthalley/dnspython)) - Chris Griffith - [@cdgriffith](https://github.com/cdgriffith) ([Box](https://github.com/cdgriffith/Box)) - Daniel - [@dnmTX](https://github.com/dnmTX) - Jonathan Hartley - [@tartley](https://github.com/tartley) ([colorama](https://github.com/tartley/colorama)) - [IANA](https://www.iana.org/) - [ICANN](https://www.icann.org/) ([Root Zone Database](https://www.iana.org/domains/root/db)) - [Iterative](https://github.com/iterative) ([shtab](https://github.com/iterative/shtab)) - Kenneth Reitz - [@kennethreitz](https://github.com/kennethreitz) ([requests](https://github.com/kennethreitz/requests)) - Mitchell Krog - [@mitchellkrogza](https://github.com/mitchellkrogza) - Mohammad Fares - [@faressoft](https://github.com/faressoft) ([Terminalizer](https://github.com/faressoft/terminalizer)) - Pi-Hole - [@pi-hole](https://github.com/pi-hole/pi-hole) - Public Suffix List - [@publicsuffix](https://github.com/publicsuffix) - Reza Rizqullah - [@ybreza](https://github.com/ybreza) - Saurabh Kumar - [@theskumar](https://github.com/theskumar) ([python-dotenv](https://github.com/theskumar/python-dotenv)) - ScriptTiger - [@ScriptTiger](https://github.com/ScriptTiger) - SMed79 - [@SMed79](https://github.com/SMed79) - spirillen - [@spirillen](https://mypdns.org/spirillen) - The YAML Project - [@yaml](https://github.com/yaml) ([pyyaml](https://github.com/yaml/pyyaml)) - [yWorks](https://www.yworks.com/company) - ([yEd Graph Editor](https://www.yworks.com/products/yed)) PyFunceble-4.2.29.dev/docs/contributing/000077500000000000000000000000001467462152100200705ustar00rootroot00000000000000PyFunceble-4.2.29.dev/docs/contributing/code-of-conduct.md000077700000000000000000000000001467462152100266032../../CODE_OF_CONDUCT.mdustar00rootroot00000000000000PyFunceble-4.2.29.dev/docs/contributing/contributing.md000066400000000000000000000272561467462152100231350ustar00rootroot00000000000000 # Contributing to PyFunceble First off, thanks for taking the time to contribute! โค๏ธ All types of contributions are encouraged and valued. See the Table of Contents for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. ๐ŸŽ‰ > And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about: > > - Star the project > - Tweet about it > - Refer this project in your project's readme > - Mention the project at local meetups and tell your friends/colleagues ## Code of Conduct This project and everyone participating in it is governed by the [PyFunceble Code of Conduct](./code-of-conduct.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to . ## I Have a Question > If you want to ask a question, we assume that you have read the available [Documentation](../index.md). Before you ask a question, it is best to search for existing [Issues](https://github.com/funilrys/PyFunceble/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first. If you then still feel the need to ask a question and need clarification, we recommend the following: - Open an [Issue](https://github.com/funilrys/PyFunceble/issues/new). - Provide as much context as you can about what you're running into. - Provide project and platform versions (nodejs, npm, etc), depending on what seems relevant. We will then take care of the issue as soon as possible. ## I Want To Contribute > ### Legal Notice > > When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license. ### Reporting Bugs #### Before Submitting a Bug Report A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible. - Make sure that you are using the latest version. - Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](../index.md). If you are looking for support, you might want to check [this section](#i-have-a-question)). - To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/funilrys/PyFunceble/issues?q=label%3Abug). - Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue. - Collect information about the bug: - Stack trace (Traceback) - OS, Platform and Version (Windows, Linux, macOS, x86, ARM) - Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant. - Possibly your input and the output - Can you reliably reproduce the issue? And can you also reproduce it with older versions? #### How Do I Submit a Good Bug Report? > You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public. Instead sensitive bugs must be sent by email to . We use GitHub issues to track bugs and errors. If you run into an issue with the project: - Open an [Issue](https://github.com/funilrys/PyFunceble/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.) - Explain the behavior you would expect and the actual behavior. - Please provide as much context as possible and describe the _reproduction steps_ that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case. - Provide the information you collected in the previous section. Once it's filed: - The project team will label the issue accordingly. - A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `needs-repro`. Bugs with the `needs-repro` tag will not be addressed until they are reproduced. - If the team is able to reproduce the issue, it will be marked `needs-fix`, as well as possibly other tags (such as `critical`), and the issue will be left to be [implemented by someone](#your-first-code-contribution). ### Suggesting Enhancements This section guides you through submitting an enhancement suggestion for PyFunceble, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions. #### Before Submitting an Enhancement - Make sure that you are using the latest version. - Read the [documentation](../index.md) carefully and find out if the functionality is already covered, maybe by an individual configuration. - Perform a [search](https://github.com/funilrys/PyFunceble/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. - Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library. #### How Do I Submit a Good Enhancement Suggestion? Enhancement suggestions are tracked as [GitHub issues](https://github.com/funilrys/PyFunceble/issues). - Use a **clear and descriptive title** for the issue to identify the suggestion. - Provide a **step-by-step description of the suggested enhancement** in as many details as possible. - **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you. - You may want to **include screenshots and animated GIFs** which help you demonstrate the steps or point out the part which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux. - **Explain why this enhancement would be useful** to most PyFunceble users. You may also want to point out the other projects that solved it better and which could serve as inspiration. ### Your First Code Contribution We do not any constraint regarding the way to use or configure your IDE. But, we compiled some of the necessary steps that you may need before starting to hack PyFunceble. 1. If you haven't already: Clone or Fork the repository. 2. Create a new branch for your change. 3. Create a virtual environment (recommended) ```shell virtualenv -p python3 venv . venv/bin/activate ``` 4. Install the development related dependencies. ```shell # Assuming you activated the environment. pip3 install -e .[dev,test] ``` 5. Test if pyfunceble is running. ```shell pyfunceble --version ``` 6. Test if tests are running. ```shell tox ``` Once you went through all of those steps, you are ready and can start to code. #### Notes for Code Contributions 1. When you are working on a new feature or a bug, make sure to create a new branch. 2. When developing, please keep in mind that your configuration files located in the `~/.config/pyfunceble/` directory will be ignored. Therefore, you may want to create a new configuration file in the root of the repository. You can overwrite it by using the `PYFUNCEBLE_CONFIG_DIR` environment variable. ### Improving The Documentation Maintaining a documentation is rarely a one man action. If you think a paragraph, a section should be improved or a totally new section added, feel free to write a draft and submit your change through a Pull Request. If you want to test your changes locally, some steps are necessary: 1. If you haven't already: Clone or Fork the repository. 2. Create a new branch for your change. 3. Create a virtual environment (recommended) ```shell virtualenv -p python3 venv . venv/bin/activate ``` 4. Install the docs related dependencies. ```shell # Assuming you activated the environment. pip3 install -e .[docs] ``` 5. Serve the documentation for live testing: ```shell mkdocs serve ``` Once you went through all of those steps, you are ready and can start editing the documentation. ## Styleguides ### Code Format We love unique contributions, but we hate to deal with serveral code formats. Therefore, we adopted [Black](https://github.com/ambv/black), _The uncompromising Python code formatter_, to format our code. No more headache or thinking, just apply the `black` command against your change and you are good to go! ### Code Linting We are human and we sometime make mistakes. One way to reduce issues before a change hits a global deployment is through linting. To reduce headeche, the repository is already configured! You can lint your code before commiting them by running `pylint` against your modified files. ### Tests Coverage We want to have a code test coverage of at lease 60%. Therefore, be sure to run `tox` before commiting your changes! ### Commit Messages Your git message should be consice but informative. Therefore, we ask you the follow the following convention: ``` [Verb] [Description] Paragraphs with some details/context (if needed). ``` ## Attribution This guide is based on the **contributing-gen**. [Make your own](https://github.com/bttger/contributing-gen)! PyFunceble-4.2.29.dev/docs/develop/000077500000000000000000000000001467462152100170175ustar00rootroot00000000000000PyFunceble-4.2.29.dev/docs/develop/checker-responses.md000066400000000000000000000103461467462152100227700ustar00rootroot00000000000000# Checker Responses This page tries to document the response that you may expect from the different checker types. ## Syntax Checker ```json { "checker_type": "SYNTAX", "idna_subject": "example.com", "params": null, "status": "VALID", "status_source": "SYNTAX", "subject": "example.com", "tested_at": "2021-03-09T17:43:24.477977" } ``` ### checker_type The checker type describes the kind of the checker that was used to provide the given response. It should be set to `SYNTAX`, `AVAILABILITY` or `REPUTATION` ### idna_subject The IDNA encoded subject that has been used to perform the tests. ### params The parameters describes the parameter that has been applied to the checker. Most of the time, if you are using the Python API, you should be able to control most of them through the class constructor or their property setters. For the syntax checker, this parameter is set to `null`. ### status The status describes the (final) status that has been gathered by the checker. For the syntax checker, it should be set to `VALID` or `INVALID`. ### status_source The status source describes the last test method that led to the decision of the given status. For the syntax checker, it should always be set to `SYNTAX`. ### subject The subject describes the subject that you supplied to PyFunceble. ## Availability Checker ```json { "checker_type": "AVAILABILITY", "dns_lookup": { "NS": [ "a.iana-servers.net.", "b.iana-servers.net." ] }, "dns_lookup_record": { "dns_name": "example.com.", "follow_nameserver_order": true, "nameserver": "9.9.9.9", "port": 53, "preferred_protocol": "UDP", "query_record_type": "NS", "query_timeout": 5.0, "response": [ "a.iana-servers.net.", "b.iana-servers.net." ], "subject": "example.com", "used_protocol": "UDP" }, "domain_syntax": true, "expiration_date": null, "http_status_code": null, "idna_subject": "example.com", "ip_syntax": false, "ipv4_range_syntax": false, "ipv4_syntax": false, "ipv6_range_syntax": false, "ipv6_syntax": false, "netinfo": null, "netloc": "example.com", "params": { "do_syntax_check_first": false, "use_dns_lookup": true, "use_extra_rules": true, "use_http_code_lookup": true, "use_netinfo_lookup": true, "use_reputation_lookup": false, "use_whois_db": true, "use_whois_lookup": false, "use_platform": false }, "registrar": null, "second_level_domain_syntax": true, "status": "ACTIVE", "status_after_extra_rules": null, "status_before_extra_rules": null, "status_source": "DNSLOOKUP", "status_source_after_extra_rules": null, "status_source_before_extra_rules": null, "subdomain_syntax": false, "subject": "example.com", "tested_at": "2021-03-09T17:42:15.771647", "url_syntax": false, "whois_lookup_record": { "expiration_date": null, "port": 43, "query_timeout": 5.0, "record": null, "server": null, "subject": "example.com", "registrar": null }, "whois_record": null } ``` ## Reputation Checker ```json { "checker_type": "REPUTATION", "dns_lookup": [ "93.184.216.34" ], "dns_lookup_record": { "dns_name": "example.com.", "follow_nameserver_order": true, "nameserver": "9.9.9.9", "port": 53, "preferred_protocol": "UDP", "query_record_type": "A", "query_timeout": 5.0, "response": [ "93.184.216.34" ], "subject": "example.com", "used_protocol": "UDP" }, "domain_syntax": true, "idna_subject": "example.com", "ip_syntax": false, "ipv4_range_syntax": false, "ipv4_syntax": false, "ipv6_range_syntax": false, "ipv6_syntax": false, "params": { "do_syntax_check_first": false, "use_platform": false }, "second_level_domain_syntax": true, "status": "SANE", "status_source": "REPUTATION", "subdomain_syntax": false, "subject": "example.com", "tested_at": "2021-03-09T17:44:02.908452", "url_syntax": false } ```PyFunceble-4.2.29.dev/docs/develop/examples/000077500000000000000000000000001467462152100206355ustar00rootroot00000000000000PyFunceble-4.2.29.dev/docs/develop/examples/domain-availability.md000066400000000000000000000013501467462152100250750ustar00rootroot00000000000000# Domain Availability ```python linenums="1" title="Availability of a domain using the API" from PyFunceble import DomainAvailabilityChecker checker = DomainAvailabilityChecker() to_test = "github.com" # You can do it this way. status = checker.set_subject(to_test).get_status() # Or this way. checker.set_subject(to_test) status = checker.get_status() # We can convert the status to json. status_json = status.to_json() # We can convert the status to dict. status_dict = status.to_dict() # We can ask "questions". print(f"Is {to_test} ACTIVE ?", "yes" if status.is_active() else "no") print(f"Is {to_test} INACTIVE ?", "yes" if status.is_inactive() else "no") print(f"Is {to_test} INVALID ?", "yes" if status.is_invalid() else "no") ```PyFunceble-4.2.29.dev/docs/develop/examples/domain-ip-availability.md000066400000000000000000000015321467462152100255050ustar00rootroot00000000000000# Domain or IP Availability ```python linenums="1" title="Availability of a domain or IP using the API" from PyFunceble import DomainAndIPAvailabilityChecker checker = DomainAndIPAvailabilityChecker() to_test = ["github.com", "192.0.2.1"] for subject in to_test: # You can do it this way. status = checker.set_subject(subject).get_status() # Or this way. checker.set_subject(subject) status = checker.get_status() # We can convert the status to json. status_json = status.to_json() # We can convert the status to dict. status_dict = status.to_dict() # We can ask "questions". print(f"Is {subject} ACTIVE ?", "yes" if status.is_active() else "no") print(f"Is {subject} INACTIVE ?", "yes" if status.is_inactive() else "no") print(f"Is {subject} INVALID ?", "yes" if status.is_invalid() else "no") ```PyFunceble-4.2.29.dev/docs/develop/examples/domain-syntax.md000066400000000000000000000012031467462152100237460ustar00rootroot00000000000000# Domain Syntax ```python linenums="1" title="Syntax of a domain using the API" from PyFunceble import DomainSyntaxChecker checker = DomainSyntaxChecker() to_test = "github.com" # You can do it this way. status = checker.set_subject(to_test).get_status() # Or this way. checker.set_subject(to_test) status = checker.get_status() # We can convert the status to json. status_json = status.to_json() # We can convert the status to dict. status_dict = status.to_dict() # We can ask "questions". print(f"Is {to_test} VALID ?", "yes" if status.is_valid() else "no") print(f"Is {to_test} INVALID ?", "yes" if status.is_invalid() else "no") ```PyFunceble-4.2.29.dev/docs/develop/examples/file-generation.md000066400000000000000000000067151467462152100242400ustar00rootroot00000000000000# File Generation Using the API is great, but how do we get the same file structure as the CLI ? Here is an example that tries to demontrate how to achieve that. ```python linenums="1" title="Test and generate files using the API" import copy import colorama import PyFunceble.facility import PyFunceble.storage from PyFunceble import DomainAvailabilityChecker from PyFunceble.cli.filesystem.dir_structure.restore import ( DirectoryStructureRestoration, ) from PyFunceble.cli.processes.producer import ProducerProcessesManager from PyFunceble.cli.utils import ascii_logo # We initiate the coloration. colorama.init(autoreset=True) # We are in control, so we need to manually start the loader. PyFunceble.facility.ConfigLoader.custom_config = { "cli_testing": { "file_generation": {"plain": True}, "display_mode": {"quiet": True, "color": True}, } } PyFunceble.facility.ConfigLoader.start() print(ascii_logo.get_home_representation()) # This is needed as our idea is to communicate with the producer process instead # of trying to implement everything again. # So, this describes the dataset as they are sent to the tester process # (normally from the CLi). STD_COMMUNICATION_DATASET = { "type": "single", "subject_type": "domain", # Destination inside the output directory. "destination": "my_awesome_pyfunceble_wrapper", "subject": None, "idna_subject": None, "source": "my_awesome_pyfunceble_wrapper", "output_dir": None, # Will be handled automatically "checker_type": "AVAILABILITY", # Must be one of our supported one!! } DOMAINS = ["github.com", "twitter.com", "www.ะฐั€ั€ำะต.com"] # In this example, we are cleaning up and regenerating the output directory # at each run. # # Note: the backup in question is the "dir_structure.json" file. dir_structure_restoration = DirectoryStructureRestoration( parent_dirname=STD_COMMUNICATION_DATASET["destination"] ).restore_from_backup() # We start the producer process. producer_proc = ProducerProcessesManager() # We start the process manager now that we are ready. producer_proc.start() # We start and configure our availability checker. avail_checker = DomainAvailabilityChecker(use_whois_lookup=False) for domain in DOMAINS: # We loop through our list of subject to test. # We parse the current subject to the availability checker. avail_checker.subject = domain # Now we fetch the status object. test_result = avail_checker.get_status() dict_result = test_result.to_dict() # We prepare our communication dataset. communication_dataset = copy.deepcopy(STD_COMMUNICATION_DATASET) communication_dataset = { key: dict_result.get(key, value) for key, value in communication_dataset.items() } # We print the result (for us as we call this script.) print( f"{test_result.subject} (IDNA: {test_result.idna_subject}) " f"is {test_result.status}" ) # We order the generation of the status file by putting our information # to the producer queue. producer_proc.add_to_input_queue( (communication_dataset, test_result), worker_name="main" ) # We are now done, it's time to send the stop signal. # The stop signal will inform the producer process that it needs to stop # listening to new order (from the time it reads the stop signal). producer_proc.send_stop_signal() # Now we wait until it's done. producer_proc.wait() # From here all files were generated we can do whatever we want with them. ```PyFunceble-4.2.29.dev/docs/develop/examples/ip-availability.md000066400000000000000000000013301467462152100242340ustar00rootroot00000000000000# IP Availability ```python linenums="1" title="Availability of an IP using the API" from PyFunceble import IPAvailabilityChecker checker = IPAvailabilityChecker() to_test = "192.0.2.1" # You can do it this way. status = checker.set_subject(to_test).get_status() # Or this way. checker.set_subject(to_test) status = checker.get_status() # We can convert the status to json. status_json = status.to_json() # We can convert the status to dict. status_dict = status.to_dict() # We can ask "questions". print(f"Is {to_test} ACTIVE ?", "yes" if status.is_active() else "no") print(f"Is {to_test} INACTIVE ?", "yes" if status.is_inactive() else "no") print(f"Is {to_test} INVALID ?", "yes" if status.is_invalid() else "no") ```PyFunceble-4.2.29.dev/docs/develop/examples/ip-syntax.md000066400000000000000000000011631467462152100231140ustar00rootroot00000000000000# IP Syntax ```python linenums="1" title="Syntax of an IP using the API" from PyFunceble import IPSyntaxChecker checker = IPSyntaxChecker() to_test = "192.0.2.1" # You can do it this way. status = checker.set_subject(to_test).get_status() # Or this way. checker.set_subject(to_test) status = checker.get_status() # We can convert the status to json. status_json = status.to_json() # We can convert the status to dict. status_dict = status.to_dict() # We can ask "questions". print(f"Is {to_test} VALID ?", "yes" if status.is_valid() else "no") print(f"Is {to_test} INVALID ?", "yes" if status.is_invalid() else "no") ```PyFunceble-4.2.29.dev/docs/develop/examples/url-availability.md000066400000000000000000000013561467462152100244360ustar00rootroot00000000000000# URL Availability ```python linenums="1" title="Availability of a URL using the API" from PyFunceble import URLAvailabilityChecker checker = URLAvailabilityChecker() to_test = "http://github.com/pyfunceble" # You can do it this way. status = checker.set_subject(to_test).get_status() # Or this way. checker.set_subject(to_test) status = checker.get_status() # We can convert the status to json. status_json = status.to_json() # We can convert the status to dict. status_dict = status.to_dict() # We can ask "questions". print(f"Is {to_test} ACTIVE ?", "yes" if status.is_active() else "no") print(f"Is {to_test} INACTIVE ?", "yes" if status.is_inactive() else "no") print(f"Is {to_test} INVALID ?", "yes" if status.is_invalid() else "no") ```PyFunceble-4.2.29.dev/docs/develop/examples/url-syntax.md000066400000000000000000000012121467462152100233010ustar00rootroot00000000000000# URL Syntax ```python linenums="1" title="Syntax of a URL using the API" from PyFunceble import URLSyntaxChecker checker = URLSyntaxChecker() to_test = "https://github.com/pyfunceble" # You can do it this way. status = checker.set_subject(to_test).get_status() # Or this way. checker.set_subject(to_test) status = checker.get_status() # We can convert the status to json. status_json = status.to_json() # We can convert the status to dict. status_dict = status.to_dict() # We can ask "questions". print(f"Is {to_test} VALID ?", "yes" if status.is_valid() else "no") print(f"Is {to_test} INVALID ?", "yes" if status.is_invalid() else "no") ```PyFunceble-4.2.29.dev/docs/develop/getting-started.md000066400000000000000000000076341467462152100224600ustar00rootroot00000000000000# Getting Started PyFunceble has an internal API that can be used for you own logic. Before PyFunceble `v4.0.0`, the internal API was extremely tight to the CLI. Therefore it has been hard for developers to reuse PyFunceble as part of their program because there was a lot to activate or deactivate to get things started. Since PyFunceble `v4.0.0`, it is possible to use the internel checkers without any initial configuration or initialization of any sort. In other words: Simply choose your checker, interact with it and get what you are looking for! ## The Basics Before starting to play with any [checkers](./api-reference/checker/index.md), let me explain some basics. To get started, you mostly need to understand the following classes: 1. [`CheckerBase`](./api-reference/checker/base.md) 2. [`CheckerStatusBase`](./api-reference/checker/status_base.md) The first one is the base class of all checkers, and the second one is the base of all status you get from any checker when you call the `.get_status()` method. ### Interacting with checkers !!! note The method described below is the same for all available checkers. Let's say we want to test the availability of the **domain** `github.com`. We first have to select and prepare the checker. ```python linenums="1" from PyFunceble import from PyFunceble import Domain checker = DomainAvailabilityChecker() ``` We then declare the subject that we want to test: ```python linenums="1" hl_lines="4 5 6" from PyFunceble import from PyFunceble import Domain checker = DomainAvailabilityChecker() checker.set_subject("github.com") # This is the same. checker.subject = "github.com" ``` Now, we trigger the query of the status: ```python linenums="1" hl_lines="8" from PyFunceble import from PyFunceble import Domain checker = DomainAvailabilityChecker() checker.set_subject("github.com") # This is the same. checker.subject = "github.com" status = checker.get_status() ``` Once we have the status, we can print the `#!python dict()` or JSON representation. ```python linenums="1" hl_lines="10 11 12 14 15 16" from PyFunceble import from PyFunceble import Domain checker = DomainAvailabilityChecker() checker.set_subject("github.com") # This is the same. checker.subject = "github.com" status = checker.get_status() print("DICT REPRESENTATION") print(status.to_dict()) print("-" * 80) print("JSON REPRESENTATION") print(status.to_json()) print("-" * 80) ``` We can also interact with any of the attributes of the status object: ```python linenums="1" hl_lines="18" from PyFunceble import from PyFunceble import Domain checker = DomainAvailabilityChecker() checker.set_subject("github.com") # This is the same. checker.subject = "github.com" status = checker.get_status() print("DICT REPRESENTATION") print(status.to_dict()) print("-" * 80) print("JSON REPRESENTATION") print(status.to_json()) print("-" * 80) print(f"{status.idna_subject} is {status.status}") ``` Finally, and probably most importantly, we can ask questions. !!! note Each checker has its own set of method. Be sure the read them or follow the autocomplete of your favorite editor. ```python linenums="1" hl_lines="20 21 22 23 24 25" from PyFunceble import from PyFunceble import Domain checker = DomainAvailabilityChecker() checker.set_subject("github.com") # This is the same. checker.subject = "github.com" status = checker.get_status() print("DICT REPRESENTATION") print(status.to_dict()) print("-" * 80) print("JSON REPRESENTATION") print(status.to_json()) print("-" * 80) print(f"{status.idna_subject} is {status.status}") # Is it active ? print("Is GitHub active ?", "yes" if status.is_active() else "no") # Is it inactive ? print("Is GitHub inactive ?", "yes" if status.is_inactive() else "no") # Is it invalid ? print("Is github.com invalid ?", "yes" if status.is_invalid() else "no") ``` That's it, you went through the basic. Feel free to discover other checkers or ask questions if something is not clear. PyFunceble-4.2.29.dev/docs/gen_ref_pages.py000077500000000000000000000032521467462152100205240ustar00rootroot00000000000000#!/usr/bin/env python3 """ Generate the code reference pages. Everything under /develop/api-references is actually generated by this script. """ import os import shutil from pathlib import Path import mkdocs_gen_files CODE_PATHS = ["PyFunceble"] DOCPATH = "develop/api-references" EXCLUDE_MODULES = ["PyFunceble.data"] try: # Ensure that we cleanup the directory before we start generating the files. shutil.rmtree(DOCPATH) except FileNotFoundError: shutil.rmtree(os.path.join("docs", DOCPATH), ignore_errors=True) nav = mkdocs_gen_files.Nav() for code_path in CODE_PATHS: for path in sorted(Path(code_path).rglob("*.py")): module_path = path.with_suffix("") doc_path = path.relative_to(code_path).with_suffix(".md") full_doc_path = Path(DOCPATH, doc_path) parts = list(module_path.parts) if parts[-1] == "__init__": parts: list[str] = parts[:-1] doc_path = doc_path.with_name("index.md") full_doc_path = full_doc_path.with_name("index.md") elif parts[-1] == "__main__": continue identifier = ".".join(parts) if any(f"{x}." in identifier for x in EXCLUDE_MODULES): if os.path.exists(full_doc_path.absolute()): os.remove(full_doc_path.absolute()) continue nav[parts] = doc_path.as_posix() with mkdocs_gen_files.open(full_doc_path, "w") as file_stream: print("::: " + identifier, file=file_stream) mkdocs_gen_files.set_edit_path(full_doc_path, path) with mkdocs_gen_files.open(Path(DOCPATH, "SUMMARY.md"), "w") as nav_file_stream: nav_file_stream.writelines(nav.build_literate_nav()) PyFunceble-4.2.29.dev/docs/help.md000066400000000000000000000010061467462152100166300ustar00rootroot00000000000000# Discussions If you have an idea or want to discuss something with other, you are invited to create a new discussion or participate to an existing one [on GitHub](https://github.com/funilrys/PyFunceble/discussions)! # Issues You should report any issue by opening an issue [on Github](https://github.com/funilrys/PyFunceble/issues). If you consider your issue critical and need personal and private help, please reach [@funilrys through Matrix](https://matrix.to/#/@funilrys:matrix.org) or send an email to him. PyFunceble-4.2.29.dev/docs/index.md000066400000000000000000000046641467462152100170240ustar00rootroot00000000000000# PyFunceble ![image](https://raw.githubusercontent.com/PyFunceble/logo/dev/Green/HD/RM.png)

The tool to check the availability or syntax of domain, IP or URL.

image image image image image

image image image

**PyFunceble** is a tools that aims to provide an accurate availability check through the usage of multiple sources which are for example - to only list a few: - the WHOIS record(s). - the DNS record(s). - the HTTP status code. - a community currated list of **special** rules. PyFunceble can be included in your existing project through: - its standard built-in CLI implementation. - its [Python API](./develop/api-references/index.md). - the [PyFunceble web-worker](https://github.com/pyfunceble/web-worker) (beta) project that provides the core functionalities of PyFunceble behind a web API. The PyFunceble CLI can test from a hosts file, a plain list of subjects, an AdBlock filter list or even an RPZ record file. As of today, PyFunceble is running actively - if not daily - behind a pool of several servers, laptops, PCs, and Raspberry Pis. It is even used - thanks to our auto continue mechanism - with CI engines like GitHub Action, Travis CI, or GitLab CI. PyFunceble-4.2.29.dev/docs/readthedocs_requirements.txt000066400000000000000000000000631467462152100232110ustar00rootroot00000000000000-r ../requirements.txt -r ../requirements.docs.txt PyFunceble-4.2.29.dev/docs/support.md000066400000000000000000000011211467462152100174120ustar00rootroot00000000000000# Supporting PyFunceble [PyFunceble](https://github.com/funilrys/PyFunceble), [Dead-Hosts](https://github.com/dead-hosts), [adblock-decoder](https://github.com/pyunceble/adblock-decoder) and all other analog projects are powered by free time and a lot of coffee! This project helps you and you have to possibility to help back financially? Sponsor [@funilrys](https://github.com/funilrys) through the GitHub Sponsor program by clicking the image below! [![image](https://github.blog/de/wp-content/uploads/sites/3/2019/05/mona-heart-featured.png?w=200)](https://github.com/sponsors/funilrys)PyFunceble-4.2.29.dev/docs/use/000077500000000000000000000000001467462152100161555ustar00rootroot00000000000000PyFunceble-4.2.29.dev/docs/use/ci-cd/000077500000000000000000000000001467462152100171345ustar00rootroot00000000000000PyFunceble-4.2.29.dev/docs/use/ci-cd/github-actions.md000066400000000000000000000125551467462152100224060ustar00rootroot00000000000000# Github Action PyFunceble can be used within a GitHub Action container. The idea is to run PyFunceble within a GitHub Action container and let PyFunceble push the result into a Git Repository. ## Environment Variables | Environment Variable | Description | | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | GITHUB_ACTIONS | The variable PyFunceble will look for to decide which CI "engine" to use. **BEWARE:** If you use this variable to test locally, your configurations may get messy. Please test within an isolated environment. | | PYFUNCEBLE_AUTO_CONFIGURATION | Let PyFunceble manage the configuration files. | | PYFUNCEBLE_CONFIG_DIR | Let PyFunceble know where it should store its configuration files. | | GITHUB_TOKEN | The token PyFunceble has to use to push changes to the repository. | | GIT_NAME | The `git.name` to setup and use. | | GIT_EMAIL | The `git.email` to setup and use. | | GIT_BRANCH | The Git branch to use to store testing results between serveral sessions. | | GIT_DISTRIBUTION_BRANCH | The Git branch to use to store and distribute the final results. | ## Example Here is an example that demonstrate how to use PyFunceble within a GitHub Workflow. ```yaml title=".github/workflows/main.yml" name: PyFunceble CI tests on: push: branches: - "my-awesome-branch" pull_request: branches: - "my-awesome-branch" env: # Let PyFunceble know that it has to manage the configuration by itself. PYFUNCEBLE_AUTO_CONFIGURATION: "YES" # We want PyFunceble to push result to the branch, therefore, we need to # declare our git settings. GIT_NAME: "${{ secrets.GIT_BOT_NAME }}" GIT_EMAIL: "${{ secrets.GIT_BOT_EMAIL }}" # Define the branch PyFunceble has to use while working. GIT_BRANCH: my-awesome-branch # Define the branch PyFunceble will push the final result into. GIT_DISTRIBUTION_BRANCH: my-awesome-branch # Define the path of the configuration directory. PYFUNCEBLE_CONFIG_DIR: "${{ github.workspace }}/.pyfunceble" # By settings this variable, PyFunceble will use its GitHub Action feature # to setup and push to the current repository. GITHUB_TOKEN: "${{ secrets.BOT_REPO_PAT }}" jobs: single: name: Run PyFunceble with a single domain runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v3 name: Clone repository with: token: "${{ secrets.BOT_REPO_PAT }}" - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install pyfunceble-dev - name: Get PyFunceble version run: | pyfunceble --version - name: Run PyFunceble run: | pyfunceble -a --logging-level critical -d github.com file_and_push: name: Run PyFunceble against a file and push result to repository runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: python_version: - "3.12" os: - ubuntu-latest steps: - uses: actions/checkout@v3 name: Clone repository with: token: "${{ secrets.BOT_REPO_PAT }}" - name: Set up Python ${{ matrix.python_version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | pip install pyfunceble-dev - name: Get PyFunceble version run: | pyfunceble --version - name: Run PyFunceble # Warning: this assume that the test.list file is at the root of the # repository. run: | pyfunceble -a --ci --logging-level critical -f test.list ``` PyFunceble-4.2.29.dev/docs/use/ci-cd/gitlab-ci-cd.md000066400000000000000000000103641467462152100217010ustar00rootroot00000000000000# GitLab CI/CD PyFunceble can be used within a GitLab CI/CD runner. The idea is to run PyFunceble within a runner and let PyFunceble push the result into a Git Repository. ## Environment Variables | Environment Variable | Description | | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | GITLAB_CI / GITLAB_USER_ID | The variables PyFunceble will look for to decide which CI "engine" to use. **BEWARE:** If you use this variable to test locally, your configurations may get messy. Please test within an isolated environment. | | PYFUNCEBLE_AUTO_CONFIGURATION | Let PyFunceble manage the configuration files. | | PYFUNCEBLE_CONFIG_DIR | Let PyFunceble know where it should store its configuration files. | | GL_TOKEN | The token PyFunceble has to use to push changes to the repository. | | GIT_NAME | The `git.name` to setup and use. | | GIT_EMAIL | The `git.email` to setup and use. | | GIT_BRANCH | The Git branch to use to store testing results between serveral sessions. | | GIT_DISTRIBUTION_BRANCH | The Git branch to use to store and distribute the final results. | ## Configuration: Personal Access Token A personal access token is needed in order for PyFunceble to automatically push the results. You should get [a personal GitLab access token](https://gitlab.com/profile/personal_access_tokens) with the `read_repository` and `write_repository` scopes. Once created and copied in a safe place, create a new masked variable called `GL_TOKEN` inside the CI/CD settings of your project. The value of the variable should be the newly generated personal access token. ## Example Here is an example that demonstrate how to use PyFunceble within a GitLab CI/CD Runner. !!! warning This example won't push result until you define the `GL_TOKEN` secret environment variable. ```yaml title=".travis.yml" # Python needed, so we use the python image. image: python:latest variables: # Let PyFunceble know that it has to manage the configuration by itself. PYFUNCEBLE_AUTO_CONFIGURATION: "YES" # This is the Git name we have to set. (git config user.name) GIT_EMAIL: "foobar@example.org" # This is the Git Email we have to set. (git config user.email) GIT_NAME: "PyFunceble @ GitLab CI/CD" # Define the branch PyFunceble has to use while working. GIT_BRANCH: my-awesome-branch # Define the branch PyFunceble will push the final result into. GIT_DISTRIBUTION_BRANCH: my-awesome-branch # Define the path of the configuration directory. PYFUNCEBLE_CONFIG_DIR: "${CI_PROJECT_DIR}/.pyfunceble" before_script: - pip3 install pyfunceble-dev run: script: - pyfunceble --version # Warning: this assume that the test.list file is at the root of the # repository. - pyfunceble -a --ci --logging-level critical -f test.list ``` PyFunceble-4.2.29.dev/docs/use/ci-cd/travis-ci.md000066400000000000000000000136511467462152100213650ustar00rootroot00000000000000# Travis CI PyFunceble can be used within a Travis CI instance. The idea is to run PyFunceble within an instance and let PyFunceble push the result into a Git Repository. ## Environment Variables | Environment Variable | Description | | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | TRAVIS_BUILD_DIR | The variables PyFunceble will look for to decide which CI "engine" to use. **BEWARE:** If you use this variable to test locally, your configurations may get messy. Please test within an isolated environment. | | PYFUNCEBLE_AUTO_CONFIGURATION | Let PyFunceble manage the configuration files. | | PYFUNCEBLE_CONFIG_DIR | Let PyFunceble know where it should store its configuration files. | | GH_TOKEN | The token PyFunceble has to use to push changes to the repository. | | GIT_NAME | The `git.name` to setup and use. | | GIT_EMAIL | The `git.email` to setup and use. | | GIT_BRANCH | The Git branch to use to store testing results between serveral sessions. | | GIT_DISTRIBUTION_BRANCH | The Git branch to use to store and distribute the final results. | ## Configuration: GitHub Personal Access Token A personal access token is needed in order for PyFunceble to automatically push the results. If your repository is hosted on GitHub, you have to [generate a new GitHub PAT](https://github.com/settings/tokens/new) with _(at least)_ the `public_repo` scope. Once created and copied in a safe place, you can use the Travis CI CLI to embed your variable into your job description through the following command: ```sh travis encrypt 'GH_TOKEN=MyAwes0meToken' -r 'myowner/myrepo' --add ``` ## Example Here is an example that demonstrate how to use PyFunceble within a Travis CI instance. !!! warning This example won't push result until you define the `GH_TOKEN` secret environment variable. ```yaml title=".gitlab-ci.yml" env: global: # The following is your encrypted GitHub API key. # Indeed as we are going to push to the repository, this is needed. #- GH_TOKEN: # This can be set in the travis-ci https://travis-ci.com/repo/settings as 'Environment Variables' # or as below: secure: encrypted code - secure: QQdKFquFFojFT9XJ1XZp4EMoDTVoXFgqZq8XU+sCVf+pJQR6d/oKBp8rnSTCnZizWOQXUjGXUUxUpSG/dYGyBLjo3rH3rsn9ciZHVfubxbwK860w4sqibl4DvhCv2rdsFtvzXnhm4P9OL3i+krKdewh9fxpNyUU58qOgfnS7mK9FcFhb8z5ak2sxU2XRZedwm6Ro0oyVKs8kFkL4YaADfNyAHlGTfr9rVmE52WXQXQENktb9gFgR2A8ZnmLy0BCMZGkPDShJnjRDWD4DErtasLmLQvWpzOBwdbVJTY6U9KDRXVNdC9lp5E5Ba/dc0y36q6vjfgJR+QchetOtHgNbKYbLB8c26Di90OZCFJsxMNcl1Wct4qFPXkFGvjXrISW6pbdPL5Plto0Ig3iLiulhYOPVArysMIk9ymtSXP+WE7VWX01LQ1fEkIoSfeVZ2caTnCmTsoHVGRRe978CojKaT7yU45kb15hcyDrzptQ8EP2hfxeh5F7KtueQ6Rsb9LFDZMkMDKflZn6a+bRhESlmWWmYB9stzGzTurQA1E1bcSACJ8A8hG5nHBzZYJ2S+OY0PE7UdyOJ0JK0qe/67d+F9ocQdIoFpDDTdgIjHerQnD2wRg1aKPzLDb4jJTpqgr5ssPrqUAKl3st7gyaAZzCEADPDnIBDjOJS+mFWbx9DKgc= # Let PyFunceble know that it has to manage the configuration by itself. PYFUNCEBLE_AUTO_CONFIGURATION: "YES" # This is the Git name we have to set. (git config user.name) - GIT_NAME: "PyFunceble @ Travis CI" # This is the Git Email we have to set. (git config user.email) - GIT_EMAIL: foobar@example.com # Define the branch PyFunceble has to use while working. - GIT_BRANCH: my-awesome-branch # Define the branch PyFunceble will push the final result into. - GIT_DISTRIBUTION_BRANCH: my-awesome-branch # Define the path of the configuration directory. - PYFUNCEBLE_CONFIG_DIR: "${TRAVIS_BUILD_DIR}/.pyfunceble" # This is the language we use. language: python # This is the python version we are going to use for the tests. # Note: you can add any 3.x version to the list. python: - "3.12" # The following will tell Travis CI to ends as fast as possible. matrix: fast_finish: true # Here we are setting what Travis CI have to cache. cache: # We are caching pip3 as we use it to install PyFunceble - pip3 install: # We install the development version of PyFunceble. If you prefer the stable version replace # `pyfunceble-dev` with `pyfunceble`. - pip3 install pyfunceble-dev # Our tests start here. script: - pyfunceble --version # Warning: this assume that the test.list file is at the root of the # repository. - pyfunceble -a --ci --logging-level critical -f test.list # The following initiate email notification logic. notifications: # As we want to get a mail on failure and on status change, we set the following. on_success: change on_failure: always ``` PyFunceble-4.2.29.dev/docs/use/configuration/000077500000000000000000000000001467462152100210245ustar00rootroot00000000000000PyFunceble-4.2.29.dev/docs/use/configuration/environment-variables.md000066400000000000000000000174471467462152100256750ustar00rootroot00000000000000# Environment Variables PyFunceble provides some environment variables to control some of its internal states or logic before it actually loads any configuration files. In this page you will find all environment variables grouped by "features". ## Configuration Management | Environment Variable | Description | | ----------------------------- | ------------------------------------------------------------------------------------ | | PYFUNCEBLE_CONFIG_DIR | If set, PyFunceble will assume its value as the location of the configuration files. | | PYFUNCEBLE_AUTO_CONFIGURATION | If defined with any value, PyFunceble will accept upstream configuration changes. | ## Output Management | Environment Variable | Description | | -------------------------- | ------------------------------------------------------------------------------------ | | PYFUNCEBLE_OUTPUT_LOCATION | Defines the folder where PyFunceble will generate the `output/` folder and datasets. | ## Git / CI Management | Environment Variable | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | GIT_NAME | Defines the `git.name` to setup and use. | | GIT_EMAIL | Defines the `git.email` to setup and use. | | GIT_BRANCH | Defines the branch to use to store results between multiple CI/CD sessions. **WARNING:** This doesn't apply to the final results | | GIT_DISTRIBUTION_BRANCH | Defines the branch to use to distribute the final results of multiple CI/CD sessions. | | GITHUB_TOKEN | Under a GitHub Action worker or Jenkins CI worker, defines the token to use to authenticate ourselves against the GitHub infrastructure. | | GL_TOKEN | Under a GitLab CI/CD runner, defines the token to use to authenticate ourselves against the GitLab infrastructure. | | GH_TOKEN | Under a Travis CI instance, defines the token to use to authenticate ourselves against the GitHub infrastructure. | | PYFUNCEBLE_BYPASS_BYPASS | If set, PyFunceble will skip the bypass logic. Meaning that if a commit match the defined markers _(cf: [ci skip], and others)_, the bypass logic will be skipped - if this variable is defined. | ## Database Management The environment variables listed below are used to share your database credentials with PyFunceble. | Environment Variable | Description | | ---------------------- | -------------------------------------------------------------------------------------------------- | | PYFUNCEBLE_DB_CHARSET | The charset PyFunceble has to use while writing into the database. | | PYFUNCEBLE_DB_HOST | The location of the database. It can be an IP, hostname or an absolute path of a unix socket file. | | PYFUNCEBLE_DB_PORT | When `PYFUNCEBLE_DB_HOST` is not a socket file, the port to reach the database through | | PYFUNCEBLE_DB_USERNAME | The username to use to authenticate ourselves. | | PYFUNCEBLE_DB_PASSWORD | The password to use to authenticate ourselves. | | PYFUNCEBLE_DB_NAME | The name of the database to work with. | ## Debugging The environment variables listed below can be used to control the extended outputs of PyFunceble. !!! danger "Beware!!!" Using the debug mode will help you understand what's going one under the hood, but may also leak private information inside the `{output-dir}/logs` folder. **Never share the debug output unsecurely.** | Environment Variable | Description | | -------------------------- | ------------------------------------------------------------------------------------------- | | PYFUNCEBLE_DEBUG | Activates the debug mode. | | PYFUNCEBLE_DEBUG_LVL | The logging level. Can be any of `NONE`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` or `DEBUG`. | | PYFUNCEBLE_LOGGING_LVL | Alias of `PYFUNCEBLE_DEBUG_LVL`. | | PYFUNCEBLE_DEBUG_ON_SCREEN | Activates the output of debug logs to STDOUT. Should be `true` or `false`. | ## Internal Environment Variables The environment variables shouldn't be set by yourself, but PyFunceble somehow still read and use them. #MayTheForceBeWithYou :star: | Environment Variable | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------- | | APPDATA | Used under Windows to build or get the configuration folder, when `PYFUNCEBLE_CONFIG_DIR` is not found. | | GITHUB_ACTIONS | Used to detect whether we are running under a GitHub Action worker | | GITLAB_CI | Used to detect whether we are running under a GitLab CI/CD runner. | | GITLAB_USER_ID | Used to detect whether we are running under a GitLab CI/CD runner. | | TRAVIS_BUILD_DIR | Used to detect whether we are running under a Travis CI instance. | | JENKINS_URL | Used to detect whether we are running under a Jenkins CI worker. | | JENKINS_HOME | Used to detect whether we are running under a Jenkins CI worker. | | PYFUNCEBLE_STANDALONE_CI | Used to detect whether we are running under a Standalone CI/CD engine. | ## Beta Features !!! danger "Beware!!!" This section is documented, but most of the features below them are not open to everyone - yet. The environment variables listed below, are strictely reserved to selected or power users. | Environment Variable | Description | | ------------------------------------ | --------------------------------------------------------------------- | | PYFUNCEBLE_PLATFORM_API_TOKEN | Set the API token to use when pushing data into the platform API. | | PYFUNCEBLE_PLATFORM_CHECKER_PRIORITY | Set the prioritized checker to accept while testing for the platform. | | PYFUNCEBLE_PLATFORM_CHECKER_EXCLUDE | Set the checker to exclude while testing for the platform. |PyFunceble-4.2.29.dev/docs/use/configuration/index.md000066400000000000000000000035051467462152100224600ustar00rootroot00000000000000# Configuration PyFunceble provides a set of functionalities that you can influence through configuration. There are multiple way to configure PyFunceble so let's get started :smile: PyFunceble primarely load it's configuration from a file called `.PyFunceble.yaml`. That's the file PyFunceble generate with its default settings. However, you can overwrite any of the configuration value through a `.PyFunceble.overwrite.yaml` file or the corresponding CLI parameter. ## TLTR; Location Here a table that show the configuration file location - at best efforts. If your installation is not writing at any of the location listed below, please refer to the [location documentation](location.md) page. If you want to skip and define your own configuration folder, you can define the storage location of the configuration files through the `PYFUNCEBLE_CONFIG_DIR` environment variable. | OS / Engine | Location | | -------------- | ---------------------- | | Linux | `~/.config/PyFunceble` | | MacOS | `~/.config/PyFunceble` | | Windows | `%APPDATA%\PyFunceble` | | GitHub Actions | Workspace | | GitLab CI/CD | Workspace | | Travis CI | Workspace | | Jenkins CI | Workspace | ## Filename-s At you configuration folder, PyFunceble will automatically create 2 files for you. 1. `.PyFunceble.yaml`, this file is the default configuration file for your current version. Overtime, it will be overwritten and updated as features comes and goes from a version to another. This file is provided to ensure PyFunceble run at all time with a fully compatible configuration file. 2. `.PyFunceble.overwrite.yaml`, this is generated empty. One generated, PyFunceble will never write into it. That's the file where you put your own configuration choices overwrites. PyFunceble-4.2.29.dev/docs/use/configuration/location.md000066400000000000000000000041301467462152100231540ustar00rootroot00000000000000# Location Depending on how and where PyFunceble is operated, it will try to load the configuration from dedicated locations. ## Custom Location If you want to skip and define your own configuration folder, you can define the storage location of the configuration files through the `PYFUNCEBLE_CONFIG_DIR` environment variable. ## Operating Systems ### Linux & MacOS Under Linux or MacOS, PyFunceble will look for the following folders respectively. 1. `~/.config/PyFunceble` 2. `~/.PyFunceble` 3. `$PWD` _(current folder)_ The first matching and found folder will be used to install the initial configuration or system files. !!! note If the parent folder does not exist, it will try to look for the next possible location. However, if none is found, it will try to create the `~/.config/PyFunceble` folder. If the `~/.config` folder doesn't exists, it will try the next one until a viable folder is found. !!! danger "Beware!!" Under some circumstances _(cf: under a CI/CD engine)_, the behavior may be different. ### Windows Under Windows, PyFunceble will look for the following folders respectively. 1. `%APPDATA%\PyFunceble` 2. `%CD%` The first matching and found folder will be used to initall the initial configuration or system files. !!! note If the parent folder does not exist, it will try to look for the next possible location. However, if none is found, it will try to create the `%APPDATA%\PyFunceble` folder. If the `%APPDATA%` folder doesn't exists, it will try the next one until a viable folder is found. ## CI / CD Engines When runing under a CI/CD engine, PyFunceble mostly use the workspace folder a the current folder. That means, that if you don't set the `PYFUNCEBLE_CONFIG_DIR` environment variable, the root folder of your repository will be used as the configuration folder. ## Edge Cases ### Cloned Repository If you cloned the [PyFunceble](https://github.com/funilrys/PyFunceble) repository, and you are trying to run a test from the root folder, PyFunceble will consider the repository's root folder as its configuration directory. PyFunceble-4.2.29.dev/docs/use/configuration/parameters/000077500000000000000000000000001467462152100231675ustar00rootroot00000000000000PyFunceble-4.2.29.dev/docs/use/configuration/parameters/SUMMARY.md000066400000000000000000000006741467462152100246550ustar00rootroot00000000000000- [](index.md) - [`cli_decoding`](cli-decoding.md) - [`cli_testing`](cli-testing.md) - [`debug`](debug.md) - [`dns`](dns.md) - [`http_codes`](http-codes.md) - [`links`](links.md) - [`lookup`](lookup.md) - [`max_http_retries`](max-http-retries.md) - [`platform`](platform.md) - [`proxy`](proxy.md) - [`share_logs`](share-logs.md) - [`user_agent`](user-agent.md) - [`verify_ssl_certificates`](verify-ssl-certificates.md)PyFunceble-4.2.29.dev/docs/use/configuration/parameters/cli-decoding.md000066400000000000000000000064361467462152100260430ustar00rootroot00000000000000# `cli_decoding` When using the CLI, you can use some of the parameters listed below to control the way inputed files are being decoded or interpreted. ## Overview ```yaml title=".PyFunceble.overwrite.yaml" cli_decoding: # Provides everything related to the decoding of input files from the CLI. # Enable/Disable the aggressive decoding. # # The aggressive mode is a mode that tries to decode as much as possible without # trying to follow any technical conventions. # # When decoding AdBlock filter lists, it will try to decode almost every # domains it finds. # # When decoding hosts file or plain text files, it will try to convert URLS # (e.g https://example.org/hello/world) into domains to test (e.g example.org). # # CLI Argument: --aggressive aggressive: no # Enable/Disable the (exclusive) decoding using the adblock decoder. # # WARNING: # Activating this parameter in your configuration file, will make # PyFunceble assume that it has to decode adblock files - exclusively. # # CLI Argument: --adblock adblock: no # Enable/Disable the (exclusive) decoding using the RPZ decoder. # # WARNING: # Activating this parameter in your configuration file, will make # PyFunceble assume that it has to decode RPZ files - exclusively. # # CLI Argument: --rpz rpz: no # Enable or disable the reduction of wildcards. # # Meaning that any caught wildcards (e.g. *.example.org) will be reduced so # that we have a "valid" domain to test (e.g. example.org). # # WARNING: # Activating this parameter will reduce wildcards (e.g *.example.org) to # match domains (e.g ecample.org) # # CLI Argument: --wildcard wildcard: no ``` ## `aggressive` Enable or disable the aggressive mode. The aggressive mode is a mode that tries to decode as much as possible without trying to follow any technical conventions. When using this parameter while decoding AdBlock filter lists, it will try to decode almost every domains it finds. However, when using this parameter while decoding hosts or plain lists, it will also convert URLs (e.g `https://example.com/hello/world`) into domains to test (e.g `example.com`). **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--aggressive` ## `adblock` Enable or disable the (exclusive) decoding of AdBlock filter lists. !!! danger "Beware!!!!" If you choose to activate this parameter in your configuration file, PyFunceble will assume that any inputed files are AdBlock filter lists to decode. **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--adblock` ## `rpz` Enable or disable the (exclusive) decoding of RPZ files. !!! danger "Beware!!!!" If you choose to active this parameter in your configuration file, PyFunceble will assume that any inputed files are RPZ files to decode. **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--rpz` ## `wildcard` Enable or disable the reduction of wildcards. Meaning that any caught wildcards (e.g. \*.example.org) will be reduced so that we have a "valid" domain to test (e.g. example.org). **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--wildcard` PyFunceble-4.2.29.dev/docs/use/configuration/parameters/cli-testing.md000066400000000000000000000315701467462152100257410ustar00rootroot00000000000000# `cli_testing` This is where you can configure everything related to the testing through the CLI. ## Overview ```yaml title=".PyFunceble.overwrite.yaml" cli_testing: # Provides everything directly related to the testing through the CLI. # Set the IP to prefix each hosts file lines with. # # CLI Argument: -ip | --hosts-ip hosts_ip: "0.0.0.0" # Set the amount of maximal workers to use to perform tests. # # NOTE: # If set to `null`, the value is implicitly CPU * Cores - 2 # # CLI Argument: -w | --max-workers max_workers: null # Enable/Disable the autocontinue datasets. # # The autocontinue datasets/database is a database that temporarily store the # result of the tested subject in the hope to continue as soon as possible # after a break or shortage. # # CLI Argument: -c | --auto-continue | --continue autocontinue: no # Enable/Disable the inactive datasets. # # The inactive datasets/database is used to store the INACTIVE and INVALID # subjects to purposely retest then at a later time. # # This mechanism let you cleanup your source file while being sure that # pyfunceble will retest the old entries of your source file. After retesting, # pyfunceble will throw the newly ACTIVE subject from the database and put # it into your ACTIVE output files so that you can reintroduce them into # your list. # # CLI Argument: --inactive-db inactive_db: yes # Enable/Disable the whois storage of whois records. # # This mechanism let us avoid spaming the WHOIS servers by storing the # expiration dates from the whois record into a local datasets/database. # Later on, PyFunceble will query the local database first. # # CLI Argument: -wdb | --whois-database whois_db: yes # Enable/Disable the testing and generation of complements. # # A complement is `www.example.org` when `example.org` is given and vice-versa. # # CLI Argument: --complements complements: no # Enable/Disable the expension and testing of single addresses of a CIDR. # # CLI Argument: --cidr cidr_expand: no # Set the cooldown time to apply between each tests. # # This is essential to avoid spaming remote resources - especially WHOIS servers. # # WARNING: # This must be a value >= 0.0 # # CLI Argument: --cooldown-time cooldown_time: 0.0 # Sets the Database Connector type to use. # Available: csv | mariadb | mysql | postgresql # # Set the type of database to use or generate to store long term information-s. # # When set to `mariadb`, `mysql` or `postgesql` the following environment # variables are required. # # PYFUNCEBLE_DB_HOST - The host or unix socket path of the database server. # PYFUNCEBLE_DB_PORT - The port to use to reach the database server. # PYFUNCEBLE_DB_USERNAME - The username to use to connect to the database server - when applicable. # PYFUNCEBLE_DB_PASSWORD - The password to use to connect to the database server - when applicable. # PYFUNCEBLE_DB_NAME - The name of the database to work with. # PYFUNCEBLE_DB_CHARSET - The charset to use - when applicable. # # Available Values: csv | mariadb | mysql | postgresql # # CLI Argument: --database-type db_type: csv # Set the filter to apply while reading inputs. # # In other words, a global filter to apply to select the subject to tests. # Meaning that if you give `\.info$` (for example), we will only test the # subjects that ends with `.info`. # # CLI Argument: --filter file_filter: null # Enable/Disable the mining of subjects. # # When enabled, PyFunceble will follow the HTTP redirects and put all redirected # subjects into the testing queue and outputs. # # CLI Argument: --mining mining: no # Acknowledge/Dismiss that we are testing for subjects that are only on the # local network. # # NOTE: # When enabled, no syntax checking will be processed when performing # availability and reputation tests. # # CLI Argument: --local local_network: no # Enable/Disable the preloading of the given input file(s). # # When enabled, we take the time to pre-load subjects by decoding inputs files # and storing the informatino in the chosen datasets/database format. # The hope is to optimise some of our process by only focusing on testing. # # WARNING: # While this is helpful for long running tasks, this might not be a good # idea if you are testing a URL directly. This process is not optimizied # for sources that are constantly updated (checksums). # # CLI Argument: --preload preload_file: no # Enable/Disable a chancy testing mode that unleashes and bypass the safety # workflow-s in place in hope of speed. # # DANGER / WARNING: # You have been warned. This mode is for the chancy and lucky one. # # You shouldn't use this unless you fele really, really, really lucky and # trust your machine. # # Enabling this mode makes thinks look 'fast', but it may produce some # rather ... unexpected behavior and results - IF N+1 process simultaneously # write the same output file. # # This mode also makes the CLI terminal output unparsable - either. # # **MAY THE FORCE BE WITH YOU!** # # CLI Argument: --chancy chancy_tester: no ci: # Provides everything related to the testing within a Continuous integration # engine. # Enable/Disable the CI/CD mode. # # When enabled, PyFunceble will assume that it works with a git repository. # Therefore, you have to declare the following environment variables to # configure git for pushing - which is normally not available withing a # CI engine. # # GIT_NAME - The `git.name` to setup and use. # GIT_EMAIL - The `git.email` to setup and use. # GIT_BRANCH - (optional) - The git branch to use to distribute results betwen sessions. # GIT_DISTRIBUTION_BRANCH - (optional) - The git branch to use to distribute the final results. # GITHUB_TOKEN - The token to use to authenticate ourselves against GitHub. Read when under a GitHub Action or Jenkins CI worker. # GL_TOKEN - The token to use to authenticate ourselves againt GitLab. Read when under a GitLab Runner. # GH_TOKEN - The token to ue to authenticate ourselves against GitHub. Read when under a Travis CI instance. # # CLI Argument: --ci active: no # Set the commit message to apply to all results commit except the final one. # # CLI Argument: --ci-commit-message commit_message: "PyFunceble - AutoSave" # Set the commit message to apply to the very last and final result commit. # # CLI Argument: --ci-end-commit-message end_commit_message: "PyFunceble - Results" # Set the number of minutes to wait before to start saving and stopping a session. # # This parameter can be understood as the running time of PyFunceble under a # CI Engine. # # CLI Argument: --ci-max-minutes max_exec_minutes: 15 # Set the branch to use to distribute results between multiple CI/CD sessions. # # Environment Variable: GIT_BRANCH # CLI Argument: --ci-branch branch: master # Set the branch to use to distribute the final results of multiple CI/CD session. # # Environment Variable: GIT_DISTRIBUTION_BRANCH # CLI Argument: --ci-distribution-branch distribution_branch: master # Set the command to execute before each (except last) result commit. # # CLI Argument: --ci-command command: null # Set the command to execute before the very last result commit. # # CLI Argument: --ci-end-command end_command: null display_mode: # Provides everything related to the display/OUTPUT of PyFunceble. # Enable/Disable the printing of dots. # # Dots !? Why Dots ? WTH ?! # Yes, you read correctly dots. Those dots are crutial under CI/CD engines # that assumes that no-output within a few minutes is an error. To avoid # such situation when the CI/CD engines just kill the job, we print dots, # when we perform some tasks that may not output anything for a few minutes. # # An example is when you are on the second session of testing and PyFunceble # is going through the list of subjects but it sees that the subject has been # already tested. # # NOTE: # This argument is automatically switched to `yes` when under a CI/CD engine # (aka cli_testing.ci set to yes). # # CLI Argument: --dots dots: no # Enable/Disable the printing of the execution time at the end of a test session. # # CLI Argument: -ex | --execution execution_time: no # Enable/Disable the printing of the percentage stats per status at the end # of a test session. # # CLI Argument: --percentage percentage: yes # Enable/Disable the printing of the registrar stats per subjects at the end # of a test session. # # CLI Argument: --registrar registrar: no # Enable/Disable the printing of any outputs. # # CLI Argument: -q | --quiet quiet: no # Enable/Disable the printing of minimal tabular information when testing. less: yes # Enable/Disable the printing of most tabular information when testing. # # CLI Argument: -a | --all all: no # Enable/Disable the printing of an extreme simple and minimalistic information # when testing. # # CLI Argument: -s | --simple simple: no # Enable/Disable the printing of colored tabular information. # # CLI Argument: --colour | --color colour: yes # Set the status to display to STDOUT. # # WARNING: # When this parameter is not set to `ALL`, only the subjects matching the # selected status will be printed to STDOUT. Howerver, this doesn't have # any effect on the generated files. # # CLI Argument: --display-status status: all # Set the maximal number of registrar to display when we have to print the # registrar stats per subject. # # NOTE: # This doesn't have any effect on the generated files. # # CLI Argument: --max-registrar max_registrar: 15 testing_mode: # Provides and select the testing mode. # # NOTE: # Only one can be active at a time. # Enable/Disable the availability test mode. availability: yes # Enable/Disable the syntax test mode. # # CLI Argument: --syntax syntax: no # Enable/Disable the reputation test mode. # # CLI Argument: --reputation reputation: no days_between: # Provides everything which is x days periodic. # NOT IMPLEMENTED (Anticipation for future usage). db_clean: 28 # Set the minimal number of days between the retest of subject which were # stored into the inactive datasets/database. # # CLI Argument: -dbr | --days-between-db-retest db_retest: 1 sorting_mode: # Provides everything related to the output sorting. # # NOTE: # Only one can be active at a time. # # WARNING: # The parameters below only applies to the generated files. NOT STDOUT. # Enable/Disable the hierarchical sorting. # # CLI Argument: --hierarchical hierarchical: no # Enable/Disable the standard sorting. standard: yes file_generation: # Provides everything related to the generation of files. # Enable/Disable the generation of files. # # CLI Argument: --no-files no_file: no # Enable/Disable the generation of hosts formatted files. # # CLI Argument: -h | --hosts hosts: no # Enable/Disable the generation of plain/raw formatted files. # # CLI Argument: --plain plain: yes # Enable/Disable the generation of analytic files. # # Analytic ?! WTH !? # Yes, analytic! While PyFunceble is really good for a lot of things, sometime # it takes some decision without being really sure about it or without # wanting to be biased. Therefore, it generates files inside the analytic folder. # The files inside the analytic folder are there for human to analyse or # to invite the community to influence PyFunceble. # # If you are sure that the behavior of PyFunceble should be adopted for sure, # fill an issue and let's evolve it together :-) # analytic: yes # Enable/Disable the generation of unified results files. # # WARNING: # This parameter simply generate a unified copy of the STDOUT instead of 1 # file per status. # # CLI Argument: --unified-results unified_results: no # Enable/Disable the merging of the results of all inputted files into one # single output directory. # # Normally, PyFunceble generated a dedicated output folder for each inputted # files. However, if you want the results to be merged inside a single # folder, just switch this parameter. # # CLI Argument: --merge-output merge_output_dirs: no ``` PyFunceble-4.2.29.dev/docs/use/configuration/parameters/debug.md000066400000000000000000000024531467462152100246030ustar00rootroot00000000000000# `debug` PyFunceble provides a debug mode which outputs everything that is being done. While this is helpful for troubleshooting, this is not adviced for everyone. ## Overview ```yaml title=".PyFunceble.overwrite.yaml" debug: # Provides everything related to the debug mode. # Enable/Disable the debug mode. # # NOTE: # When enabled, the output will be found inside the logs output directory. # If you prefer to have the output to STDOUT, you should declare the # following environment variable. # # PYFUNCEBLE_DEBUG_ON_SCREEN=yes # Environment Variable: PYFUNCEBLE_DEBUG # CLI Switch: `--debug` active: no # Set the logging level. # # Available: info, error, debug, critical # # Environment Variables: PYFUNCEBLE_DEBUG_LVL | PYFUNCEBLE_LOGGING_LVL # CLI Switch: --logging-level level: info ``` ## `active` Enable or disable the debug mode. **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--debug` **Environment Variable:** `PYFUNCEBLE_DEBUG=yes` ## `level` Set the minimal logging level. **Type:** string **Default Value:** `info` **Available Values:** `info`, `error`, `debug`, `critical` **CLI Argument:** `--logging-level` **Environment Variable:** `PYFUNCEBLE_DEBUG_LVL=info` | `PYFUNCEBLE_LOGGING_LVL`PyFunceble-4.2.29.dev/docs/use/configuration/parameters/dns.md000066400000000000000000000030341467462152100242750ustar00rootroot00000000000000# `dns` PyFunceble has its own DNS resolver which is extensively used to lookup statuses. In this section, you will find all available parameters. ## Overview ```yaml title=".PyFunceble.overwrite.yaml" dns: # Provides everything related to the DNS resolver & lookup. # Enable/Disable the follow-up of the order of DNS server. # # NOTE: # When disabled, the order of the DNS servers is randomized. # # CLI Argument: --follow-server-order follow_server_order: yes # Enable/Disable the trust mode. # # When this parameter is enabled, we will trust the result of the first DNS # server and only switch to the next server in the list ONLY when it is # unreachable. # # However, when this parameter is disabled, we will ask the other server when # the previous DNS give us a negative response - until a positive on is given. # # CLI Argument: --trust-dns-server trust_server: no # Set the list of DNS server to communicate with. # # WARNING: # IPv6 should be given in this format if a port is explicitly given: # # [ip]:port # # If you omit the braket, the port will be set to the default one (53). # # Example: # - first.dns # - second.dns # # CLI Argument: --dns server: null # Set the protocol to use. # # Available Values: UDP | TCP | HTTPS | TLS # # CLI Argument: --dns-protocol protocol: UDP # Set the delay (in second) to apply between each queries. # # WARNING: # This should be a value >= 0.0. # # CLI Argument: --dns-delay delay: 0.0 ``` PyFunceble-4.2.29.dev/docs/use/configuration/parameters/http-codes.md000066400000000000000000000026641467462152100255730ustar00rootroot00000000000000# `http_codes` PyFunceble can interpret the status codes of a query into a "Human" readable status. This is how you can configure PyFunceble for your own logic. ## Overview ```yaml title=".PyFunceble.overwrite.yaml" http_codes: # Provides everything related to the HTTP code lookup interpolation. # Stops PyFunceble self management of the list. # # NOTE: # This parameter is deprecated. self_managed: no list: # Dictionary with the status codes and their interpolation. up: # A list of status codes to consider as ACTIVE. - 100 - 101 - 102 - 200 - 201 - 202 - 203 - 204 - 205 - 206 - 207 - 208 - 226 - 429 potentially_down: # A list of status codes to consider as potentially INACTIVE. - 400 - 402 - 404 - 409 - 410 - 412 - 414 - 415 - 416 - 451 potentially_up: # A list of status codes to consider as potentially ACTIVE. - 000 - 300 - 301 - 302 - 303 - 304 - 305 - 307 - 308 - 403 - 405 - 406 - 407 - 408 - 411 - 413 - 417 - 418 - 421 - 422 - 423 - 424 - 426 - 428 - 431 - 500 - 501 - 502 - 503 - 504 - 505 - 506 - 507 - 508 - 510 - 511 ``` PyFunceble-4.2.29.dev/docs/use/configuration/parameters/index.md000066400000000000000000000020321467462152100246150ustar00rootroot00000000000000# Parameters As you now know, PyFunceble can be configured through the CLI, or its configuration file. ## CLI Arguments: Behavior while switching boolean parameters When switching boolean parameters through the CLI arguments, you have to keep in mind that the CLI will act like a light switch. Meaning that if you define `yes` in any boolean parameter and you use the CLI argument to quickly switch its value, PyFunceble will be started with the parameter set to `no`. The same thing happens the other way around. if you define `no` in any boolean parameter and you use the CLI argument to quickly switch its value, PyFunceble will be started with the paramet set to `yes`. Let say we set the `verify_ssl_certificates` parameter to `yes`:` ```yaml title=".PyFunceble.overwrite.yaml" verify-ssl-certificates: yes ``` If we now use the `--verify-ssl-certificate` parameter through the CLI ```shell pyfunceble --verify-ssl-certificate -d example.org ``` PyFunceble will starts with the `verify_ssl_certificates` set to `no` - and vice-versa. PyFunceble-4.2.29.dev/docs/use/configuration/parameters/links.md000066400000000000000000000012311467462152100246260ustar00rootroot00000000000000# `links` While PyFunceble has some hard coded URLs, some URL may be changed. The parameters listed below let you control some of the URLs. !!! danger "Beware!!!!" The parameters listed below are not implemented yet. This section is a placeholder for future usage. ## Overview ```yaml title=".PyFunceble.overwrite.yaml" links: # Provides some of the non hard-coded URLs. # WARNING: # The parameters listed bellow are not implemented yet as the # underlaying infrastructure will be rewritten. api_date_format: "https://pyfunceble.funilrys.com/api/date-format" api_no_referrer: "https://pyfunceble.funilrys.com/api/no-referrer" ``` PyFunceble-4.2.29.dev/docs/use/configuration/parameters/lookup.md000066400000000000000000000073561467462152100250350ustar00rootroot00000000000000# `lookup` To lookup or not lookup, that is the question! ## Overview ```yaml title=".PyFunceble.overwrite.yaml" lookup: # Provides everything related to the lookups. # Enable/Disable the usage of DNS records to lookup the status. # # CLI Argument: --dns-lookup # Exclusive CLI Argument: --dns-lookup-only dns: yes # Enable/Disable the usage of HTTP status codes to lookup the status. # # CLI Argument: --http | --http-status-code-lookup # Exclusive CLI Argument: --http-only | --http-status-code-lookup http_status_code: yes # Enable/Disable the usage of network (information) socket to lookup the status. # # CLI Argument: --netinfo-lookup # Exclusive CLI Argument: --netinfo-lookup-only netinfo: yes # Enable/Disable the usage of special rules to lookup or switch the status. # # CLI Argument: --special-lookup # Exclusive CLI Argument: --special-lookup-only special: yes # Enable/Disable the usage of WHOIS records to lookup the status. # # CLI Argument: --whois-lookup # Exclusive CLI Argument: --whois-lookup-only whois: yes # Enable/Disable the usage of the reputation data to lookup the status. # # NOTE: # The reputation lookup is actualy a lookup against the AlienVault IPv4 # reputation file.s # # CLI Argument: --reputation-lookup # Exclusive CLI Argument: --reputation-lookup reputation: no # Enable/Disable the usage of the platform (API) to lookup the status. # # CLI Argument: --platform-lookup # Exclusive CLI Argument: --platform-lookup-only platform: no # Set the timeout to apply to each of our lookup methods - when possible. # # WARNING: # This should be a value >= 0. # # CLI Argument: -t | --timeout timeout: 5 ``` ## `dns` Enable or disable the usage of DNS recors to lookup the status. **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--dns-lookup` **Exclusive CLI Argument:** `--dns-lookup-only` ## `http_status_code` Enable or disable the usage of HTTP status codes to lookup the status. **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--http-only`, `--http-status-code-lookup` **Exclusive CLI Argument:** `--http-only`, `--http-status-code-lookup-only` ## `netinfo` Enable or disable the usage of network (information) socket to lookup the status. **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--netinfo-lookup` **Exclusive CLI Argument:** `--netinfo-lookup-only` ## `special` Enable or disable the usage of special rules to lookup or switch the status. **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--special-lookup` **Exclusive CLI Argument:** `--special-lookup-only` ## `whois` Enable or disable the usage of WHOIS records to lookup the status. **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--whois-lookup` **Exclusive CLI Argument:** `--whois-lookup-only` ## `reputation` Enable or disable the usage of reputation data to lookup the status. **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--reputation-lookup` **Exclusive CLI Argument:** `--reputation-lookup-only` ## `platform` Enable or disable the usage of the platform (API) to lookup the status. **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--platform-lookup` **Exclusive CLI Argument:** `--platform-lookup-only` ## `timeout` Set the timeout to apply to each of our lookup methods - when possible. **Type:** integer **Default Value:** `5` **Available Values:** Any value greater that `0`. **CLI Argument:** `-t`, `--timeout` PyFunceble-4.2.29.dev/docs/use/configuration/parameters/max-http-retries.md000066400000000000000000000006761467462152100267370ustar00rootroot00000000000000# `max_http_retries` To retry or not to retry, that is the question! ## Overview ```yaml title=".PyFunceble.overwrite.yaml" # Set the maximum number of retries to perform before giving up a request. # # WARNING: # This should be an integer >= 0. # # CLI Argument: --max-http-retries max_http_retries: 3 ``` **Type:** integer **Default Value:** `3` **Available Values:** Any value greater than `0`. **CLI Argument:** `--max-http-retries` PyFunceble-4.2.29.dev/docs/use/configuration/parameters/platform.md000066400000000000000000000135041467462152100253400ustar00rootroot00000000000000# `platform` PyFunceble alone is a great tool. What if we could just test the subject that were not already tested by others ? !!! danger "Beware!!!!" The parameters listed below are not production ready. You should use or activate them only if you have good reasons to. ## Overview ```yaml title=".PyFunceble.overwrite.yaml" platform: # Provides everything related to the platform. # PyFunceble alone is a great tool. What if we could just test the subject that # were not already tested by others ? # Enable or disable the push of datasets (cf: test results) into the platform # (API). # # NOTE: # This parameter is useless, unless you have a valid API Token defined # into the PYFUNCEBLE_PLATFORM_API_TOKEN environment variable. # # CLI Argument: --push-platform push: no # Set the preferred pull "method". # # The platform (API) does not only provides datasets but it also offer an # aggregation endpoint that let PyFunceble pull datasets. # When pulling information about a subject that is already known by the platform, # it returns 3 group of results: # # - `frequent`, which provides the status that was mostly been pushed. # - `latest`, which provides the status based on the latest submitted datasets. # - `recommended`, which provides the recommended status. # # CLI Argument: --platform-preferred-origin preferred_status_origin: recommended # Defines the checker type to prioritize when trying to fullfil platform # contracts. # # Notes: # 1. This is a list. The order matters. # 2. One can overwrite this value, by settings a comma separated list of # checker type to prioritize through the PYFUNCEBLE_PLATFORM_CHECKER_PRIORITY # environment variable. # 3. When set to `none`, the platform will throw a random contract at us. # # Example: # Prioritize availability checker until no contract is available, then # prioritize syntax checker until no contract is available, then prioritize # reputation checker until no contract is available. # # - availability # - syntax # - reputation # # Available Values: none | availability | reputation | syntax # # CLI Argument: none checker_priority: - none # Defines the checker type to exclude when trying to fullfil platform # contracts. # # Notes: # 1. This is a list. # 2. One can overwrite this value, by settings a comma separated list of # checker type to exclude through the PYFUNCEBLE_PLATFORM_CHECKER_EXCLUDE # environment variable. # 3. When set to `none`, no checker type will be excluded. # # Example: # Exclude the reputation checker from the list of checker to use to fullfil. # # - reputation # # Available Values: none | availability | reputation | syntax # # CLI Argument: none checker_exclude: - none ``` ## `push` Enable or disable the push of datasets (cf: test results) into the platform (API). !!! danger "Beware!!!!" The parameters listed below are not production ready. You should use or activate them only if you have good reasons to. **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `--push-platform` ## `preferred_status_origin` Set the preferred pull "method". The platform (API) does not only provides datasets but it also offer an aggregation endpoint that let PyFunceble pull datasets. When pulling information about a subject that is already known by the platform, it returns 3 group of results: - `frequent`, which provides the status that was mostly been pushed. - `latest`, which provides the status based on the latest submitted datasets. - `recommended`, which provides the recommended status. !!! danger "Beware!!!!" The parameters listed below are not production ready. You should use or activate them only if you have good reasons to. **Type:** string **Default Value:** `recommended` **Available Values:** `frequent`, `latest`, `recommended` **CLI Argument:** `--platform-preferred-origin` ## `checker_priority` Defines the checker type to prioritize when trying to fullfil platform contracts. !!! note "Notes:" 1. This is a list. The order matters. 2. One can overwrite this value, by settings a comma separated list of checker type to prioritize through the PYFUNCEBLE_PLATFORM_CHECKER_PRIORITY environment variable. 3. When set to `none`, the platform will throw a random contract at us. **Example:** Prioritize availability checker until no contract is available, then prioritize syntax checker until no contract is available, then prioritize reputation checker until no contract is available. ```yaml checker_priority: - availability - syntax - reputation ``` !!! danger "Beware!!!!" The parameters listed below are not production ready. You should use or activate them only if you have good reasons to. **Type:** list[string] **Default Value:** `["none"]` **Available Values:** `none`, `availability`, `reputation`, `syntax` **CLI Argument:** none ## `checker_exclude` Defines the checker type to exclude when trying to fullfil platform contracts. !!! note "Notes:" 1. This is a list. 2. One can overwrite this value, by settings a comma separated list of checker type to exclude through the PYFUNCEBLE_PLATFORM_CHECKER_EXCLUDE environment variable. 3. When set to `none`, no checker type will be excluded. **Example:** Exclude the reputation checker from the list of checker to use to fullfil. ```yaml checker_exclude: - reputation ``` !!! danger "Beware!!!!" The parameters listed below are not production ready. You should use or activate them only if you have good reasons to. **Type:** list[string] **Default Value:** `["none"]` **Available Values:** `none`, `availability`, `reputation`, `syntax` **CLI Argument:** none PyFunceble-4.2.29.dev/docs/use/configuration/parameters/proxy.md000066400000000000000000000102241467462152100246710ustar00rootroot00000000000000# `proxy` PyFunceble can let you proxy requests to another server or service. This parameter let you defines rules and global proxies to use. ## Overview ```yaml title=".PyFunceble.overwrite.yaml" proxy: # Provides everything related to the proxy usage and configuration. # # The idea: # We have two main keys, "global" and "rules". # The system will always follow the global keys unless you define an explit # TLD. # # Example: # # Let's say we want all HTTP requests to go through example.org but we want # all HTTP request for domains ending with `.com`, `.org` and `.dev` to go # through example.com. And, we want all domains ending with `.onion` to go # through example.dev. # # This is how it will look like. # # global: # http: http://example.org:8080 # https: http://example.org:8080 # # rules: # - http: http://example.com:8080 # https: http://example.org:8080 # tld: # - com # - org # - dev # - http: socks5h://example.dev:8080 # https: socks5h://example.dev:8080 # tld: # - onion # global: # Global HTTP proxy to use when no rule is given or matched. # # CLI Argument: --http-proxy http: null # Global HTTPS proxy to use when no rule is given or matched. # # CLI Argument: --https-proxy https: null # The rules to apply. # See example. rules: [] ``` ## Example PyFunceble - like many other python programs - follow any `HTTP_PROXY` or `HTTPS_PROXY` environment variable. However, end-users that want to define a proxy per Top Level Domain are advised to use the configuration parameters as it offers of way to define proxy rules. Through the `proxy.global.http` and `proxy.global.https` parameters, one can set the proxy to reach when no rules is given or matched. However, if you want something more granular, you may use the `proxy.rules` parameter. Let's say we want: - any domains ending with `.com`, `.org`, and `.dev` to be tested through the `http://spec-proxy.example.com` proxy for any HTTP traffic and `http://spec-proxy.example.com:8443` for any HTTPS traffic. - any domains ending with `.ionion` to be tested through the `http://onion-proxy.example.com` proxy. - any other domains to be tested through `http://proxy.example.com` for any HTTP traffic and `http://proxy.example.com:8443` for any HTTP traffic. How would you do that ? It's simple, simply define the following rules: ```yaml title=".PyFunceble.overwrite.yaml" proxy: rules: # Any domains ending with `.com`, `.org` and `.dev` - http: http://spec-proxy.example.com https: http://spec-proxy.example.com:8443 tld: - com - org - dev # Any domains ending with `.onion` - http: http://onion-proxy.example.com https: http://onion-proxy.example.com tld: - onion global: # Any other domains http: http://proxy.example.com https: http://proxy.example.com:8443 ``` ## `global` Set the global HTTP and HTTPS proxies. ### Overview ```yaml title=".PyFunceble.overwrite.yaml" proxy: global: # Global HTTP proxy to use when no rule is given or matched. # # CLI Argument: --http-proxy http: null # Global HTTPS proxy to use when no rule is given or matched. # # CLI Argument: --https-proxy https: null ``` ### `http` Set the proxy to reach for any HTTP traffic when no rule is given or matched. **Type:** string **Default Value:** `null` **Available Values:** User-Defined Values **CLI Argument:** `--http-proxy` ### `https` Set the proxy to reach for any HTTPS traffic when no rule is given or matched. **Type:** string **Default Value:** `null` **Available Values:** User-Defined Values **CLI Argument:** `--https-proxy` ## `rules` Set the proxy rules PyFunceble has to match. (See also: [Example](#example)). **Type:** list[dict] **Default Value:** `[]` **Available Values:** User-Defined Values **CLI Argument:** `--https-proxy` **Boilerplate:** ```yaml - http: {HTTP_PROXY} https: {HTTP_PROXY} tld: - {TLD} - {TLD2} - {TLD3} ``` PyFunceble-4.2.29.dev/docs/use/configuration/parameters/share-logs.md000066400000000000000000000004551467462152100255610ustar00rootroot00000000000000# `share_logs` Let's share errors! !!! danger "Beware!!!!" This parameter is not implemented yet. This section is a placeholder for future usage. ## Overview ```yaml title=".PyFunceble.overwrite.yaml" # Not Implemented yet. Reserved for future usage and implementation. share_logs: no ```PyFunceble-4.2.29.dev/docs/use/configuration/parameters/user-agent.md000066400000000000000000000024041467462152100255630ustar00rootroot00000000000000# `user_agent` PyFunceble can choose a random user-agent to send when making HTTP requests. This is how to parametrize. ## Overview ```yaml title=".PyFunceble.overwrite.yaml" user_agent: # Provides everything related to choice of user agent. # Set the browser to pickup. # # WARNING: # This parameter will be deprecated (soon?). # # Available Values: chrome, edge, firefox, ie, opera, safari browser: chrome # Set the platform to pickup. # # Available Values: linux, macosx, win10 platform: linux # Set the User-Agent to use. # # WARNING: # If you choose to set this argument, the browser or platform arguments # won't be taken into consideration. # # CLI Argument: -ua | --user-agent custom: null ``` ## `browser` Set the browser to pickup. **Type:** string **Default Value:** `chrome` **Available Values:** `chrome`, `edge`, `firefox`, `ie`, `opera`, `safari` **CLI Argument:** None ## `platform` Set the platform to pickup. **Type:** string **Default Value:** `chrome` **Available Values:** `linux`, `macosx`, `win10` **CLI Argument:** None ## `custom` Set the User-Agent to use. **Type:** string **Default Value:** `null` **Available Values:** User-Defined values **CLI Argument:** `-ua`, `--user-agent`PyFunceble-4.2.29.dev/docs/use/configuration/parameters/verify-ssl-certificates.md000066400000000000000000000005731467462152100302640ustar00rootroot00000000000000# `verify_ssl_certificate` To verify or not to verify, that is the question! ## Overview ```yaml title=".PyFunceble.overwrite.yaml" # Enable/Disable the verification of the certificate when making HTTPS requests. verify_ssl_certificate: no ``` **Type:** boolean **Default Value:** `no` **Available Values:** `yes`, `no` **CLI Argument:** `-vsc`, `--verify-ssl-certificate`PyFunceble-4.2.29.dev/docs/use/examples/000077500000000000000000000000001467462152100177735ustar00rootroot00000000000000PyFunceble-4.2.29.dev/docs/use/examples/availability.md000066400000000000000000000050731467462152100227740ustar00rootroot00000000000000# Availability Check ## Domains / IPs Availability PyFunceble can check the availability of domains and IPs. ### Input Source: Inline You can check the availability of a domain or IP, by running PyFunceble with the `-d` argument. ```sh pyfunceble -d github.com ``` The `-d` argument can also take multiple domains to test. ```sh pyfunceble -d github.com gitlab.com gitea.com 93.184.216.34 ``` ### Input Source: File You can check the availability of the domains or IPs located inside a file, by giving the file path-s to PyFunceble through the `-f` argument. ```sh pyfunceble -f ./source.list pyfunceble -f https://example.org/my/awesome/file ``` When using the `-f` argument, the inputted source can be: - any file-s on your filesystem accessible by the user running PyFunceble. - an HTTP (raw) URLs of the file you want PyFunceble to download and check. When testing for the availability of domains or IPs, PyFunceble supports the following file formats: - hosts file - plain text file - AdBlock filter list (please use with the `--adblock` argument) - RPZ (formatted) file (please use with the `--rpz` argument) ## URLs Availability PyFunceble can check the availability of URLs. ### Input Source: Inline You can check the availability of a URL through the `-u` argument of PyFunceble. ```sh pyfunceble -u https://github.com/pyfunceble ``` That `-u` argument can also take multiple URLs to test. ```sh pyfunceble -u https://github.com/pyfunceble https://gitlab.com/funilrys https://gitea.com ``` ### Input Source: File You can check the availability of the URLs located inside a file, by giving the file path-s to PyFunceble through the `-uf` argument. ```sh pyfunceble -uf ./source.url.list pyfunceble -uf https://example.org/my/awesome/file ``` Just like the `-f` argument, when using the `-uf` argument, the inputted source can be: - any file-s on your filesystem accessible by the user running PyFunceble. - an HTTP (raw) URL-s of the file you want PyFunceble to download and check. When testing the availability of URLs, PyFunceble following the following formats: - plain text file PyFunceble-4.2.29.dev/docs/use/examples/syntax.md000066400000000000000000000050741467462152100216510ustar00rootroot00000000000000# Syntax Check ## Domains / IPs Syntax PyFunceble can check the syntax of domains and IPs. ### Input Source: Inline You can check the syntax of a domain or IP, by running PyFunceble with the `-d` argument along with `--syntax` argument. ```sh pyfunceble -d github.com --syntax ``` The `-d` argument can also take multiple domains to test. ```sh pyfunceble -d github.com gitlab.com gitea.com 93.184.216.34 --syntax ``` ### Input Source: File You can check the syntax of the domains or IPs located inside a file, by giving the file path-s to PyFunceble through the `-f` argument. ```sh pyfunceble -f ./source.list --syntax pyfunceble -f https://example.org/my/awesome/file --syntax ``` When using the `-f` argument, the inputted source can be: - any file-s on your filesystem accessible by the user running PyFunceble. - an HTTP (raw) URLs of the file you want PyFunceble to download and check. When testing for the syntax of domains or IPs, PyFunceble supports the following file formats: - hosts file - plain text file - AdBlock filter list (please use with the `--adblock` argument) - RPZ (formatted) file (please use with the `--rpz` argument) ## URLs Syntax PyFunceble can check the syntax of URLs. ### Input Source: Inline You can check the syntax of a URL through the `-u` argument of PyFunceble. ```sh pyfunceble -u https://github.com/pyfunceble ``` That `-u` argument can also take multiple URLs to test. ```sh pyfunceble -u https://github.com/pyfunceble https://gitlab.com/funilrys https://gitea.com ``` ### Input Source: File You can check the snytax of the URLs located inside a file, by giving the file path-s to PyFunceble through the `-uf` argument. ```sh pyfunceble -uf ./source.url.list pyfunceble -uf https://example.org/my/awesome/file ``` Just like the `-f` argument, when using the `-uf` argument, the inputted source can be: - any file-s on your filesystem accessible by the user running PyFunceble. - an HTTP (raw) URL-s of the file you want PyFunceble to download and check. When testing the syntax of URLs, PyFunceble following the following formats: - plain text file PyFunceble-4.2.29.dev/docs/use/faq.md000066400000000000000000000043661467462152100172570ustar00rootroot00000000000000# FAQ ## How to speed up the test process !!! danger "Beware!!!!" When talking about speed, a lot of things have to be taken into consideration. Here is a non-exhaustive list of things that can fluctuate the testing speed. - Bandwidth - DNS Server response time - CPU - ISP filter _(cf: blocking connection to huge amount of IPs)_ - Our very own databases management _(cf: this does not apply to PostgreSQL, MySQL or MariaDB)_ - Size of the dataset to test - Disk I/O in particular as PyFunceble is heavy on the I/O _(cf: RAM Drives and NVMe disks are very suitable for PyFunceble's CSV storage)_ - ... If you have a dedicated server, VM or machine for PyFunceble, you can simply increase the number of maximal workers PyFunceble is allowed to use through the `--max-workers` argument or its `cli_testing.max_workers` setting. By default, the number of worker is equal to the number of CPU Cores minus 2 (`CPU Cores - 2`), but with a minimum of 1. Meaning that if you have `8` CPU threads, the value will be automatically set to `6`. If you have `2` CPU threads, the value will be automatically set to `1`. If that is still not sufficient for you, and you feel chancy, you my try to use the dangerous `--chancy` argument. !!! info Keep in mind that the max workers setting mostly - if not only - affects the tester subprocesses and not the one in charge of generating outputs. Therefore, you may have the feeling that it takes time because you feel that the output is slow but that's actually not the case. (cf: this doesn't apply if you choose to use the `--chancy` argument - or its setting switch). Indeed, because we want to safely write the files _(Disk I/O)_, we still need a single process that reads the submitted results and generates the outputs. This has been a design decision because having safely formatted files is more important that having the feeling that the output is pretty quick. !!! danger "Beware!!!!" No contributor or maintainer of PyFunceble shall be responsible for your decisions. If you felt chancy enough to use the `--chancy` argument, you shouldn't not yield when something inexpected happens. You are still welcome to propose some changes though :smile:.PyFunceble-4.2.29.dev/docs/use/getting-started.md000066400000000000000000000176121467462152100216130ustar00rootroot00000000000000# Getting started If you feel that something is missing, feel free to submit an issue or edit this page on GitHub. ## The basics Before starting to play with PyFunceble, the first recommended action is to read the version to be sure that everything is expected to work as it should. To do that simple execute: ```shell pyfunceble --version ``` ### Testing modes PyFunceble provides 3 testing modes, that you can't use in parallel. You must choose one of the provided testing modes in order for PyFunceble to produce outputs. | Test Mode | Description | Argument | Configuration Parameter | | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | --------------------------------------- | | Availability | This is the default mode.
It exists to help us find the availability / reachability of subjects. | None, Default | `cli_testing.testing_mode.availability` | | Syntax | This is the mode that exclusively check whether the inputed subjects are VALID or INVALID. | `--syntax` | `cli_testing.testing_mode.syntax` | | Reputation | This is the mode that exclusively check whether the inputed subjects have a bad reputation by checking against the OTX IP reputation list. | `--reputation` | `cli_testing.testing_mode.reputation` | ### Input Sources PyFunceble expects you to provide the information needed for launching tests. Therefore, it is important that you understand the different way to input tests subjects into PyFunceble. PyFunceble has 2 _(direct)_ ways to directly get inputs from operators: 1. Inline: You manually type what you want to be tested. 2. Files: You give PyFunceble a path to the file that you want to be decoded and tested. #### Inline: The Quick Way! The "inline" input, describes the process of manually listing the subjects PyFunceble has to test. This can be done through the following arguments: | Argument | Multiple Possible | Example | Description | | ---------------- | ----------------- | ------------------------------------------------------------- | ---------------------------------------- | | `-d`, `--domain` | โœ”๏ธ | `-d example.com 192.0.43.7 github.com` | Inputs a list of domains or IPs to test. | | `-u`, `--url` | โœ”๏ธ | `-u https://example.com http://192.0.43.7 https://github.com` | Inputs a list of URLs to test. | #### File: The Managable Way! The "files" input, describes the process of input a local or remote path to a file that PyFunceble has to read _(or download)_, decode and test. This can be done through the following arguments: | Argument | Multiple Possible | Expected Input Format | Example | Description | | -------------------- | ----------------- | ----------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------- | | `-f`, `--file` | โœ”๏ธ | Hosts File / Plain Text | `-f ./domains.list https://example.org/my/blocklist` | Input a hosts file or plain text file that PyFunceble has to read and test. | | `-uf`, `--url-files` | โœ”๏ธ | Plain Text | `-uf ./urls.list https://example.org/my/urls.txt` | Input a plain text file that PyFunceble has to read and test. | PyFunceble can decode multiple formats. You can influence the decoding mechanism by using ONE of the following arguments: !!! warning Only one decoding method at a time is supported. | Argument | Configuration Parameter | Description | | ----------- | ----------------------- | ---------------------------------------------------------------------------- | | `--adblock` | `cli_decoding.adblock` | Forces PyFunceble to assume that the inputed file is an AdBlock filter list. | | `--rpz` | `cli_decoding.rpz` | Forces PyFunceble to assume that the inputed file is an RPZ formatted file. | You can force PyFunceble to to some extra steps while decoding files - in order to test what you really want. This can be done through the following arguments. | Argument | Configuration Parameter | Description | | -------------- | ------------------------- | ----------------------------------------------------------------------------------------------------- | | `--aggressive` | `cli_decoding.aggressive` | Forces PyFunceble to try to decodes as much as possible - even if doesn't necessarly makes sense. | | `--wildcard` | `cli_decoding.wildcard` | Forces PyFunceble to remove the wildcards parts of subjects. Example: `*.example.org -> example.org`. | You can also force PyFunceble to filter or generate new subjects to test. This can be controlled through the following argument: | Argument | Configuration Parameter | Description | | -------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `--complement` | `cli_testing.complements` | Forces PyFunceble to generate complements.
A complement of a domain is for example `www.example.org` when `example.org` is supplied - and vice-versa. | | `--filter` | `cli_testing.file_filter` | Forces PyFunceble to only tests the matching subjects. Example `--filter "example.org$"` will force PyFunceble to only test subjects that ends with `example.org`. | ### Output Format The PyFunceble CLI has 3 ways of displaying information to you. The (default) output: ```sh pyfunceble -d github.com [...] Subject Status Source ---------------------------------------------------------------------------------------------------- ----------- ---------- github.com ACTIVE WHOIS ``` The complete output, that you can get through the `-a` or `--all` arguments: ```sh pyfunceble -a -d github.com [...] Subject Status Source Expiration Date Registrar HTTP Code Checker ---------------------------------------------------------------------------------------------------- ----------- ---------- ----------------- ------------------------------ ---------- ------------- github.com ACTIVE WHOIS 09-oct-2024 MarkMonitor Inc. 301 AVAILABILITY ``` The simple output, that you can get through the `-s`or `--simple` arguments: ```sh pyfunceble -s -d github.com github.com ACTIVE ``` PyFunceble-4.2.29.dev/docs/use/index.md000066400000000000000000000012371467462152100176110ustar00rootroot00000000000000# User Guides Welcome to the User Guides section! This is where you'll find detailed instructions and examples on how to effectively use PyFunceble. Whether you're a beginner or an experienced user, these guides will help you navigate through the features and functionalities of PyFunceble. In this section, you'll find step-by-step tutorials, best practices, and troubleshooting tips to ensure a smooth and productive experience. We'll try to cover everything from installation and setup to advanced usage scenarios. So, let's dive in and explore PyFunceble together! If you have any questions or need further assistance, don't hesitate to reach us. Happy exploring!PyFunceble-4.2.29.dev/docs/use/installation.md000066400000000000000000000221571467462152100212070ustar00rootroot00000000000000# Installation PyFunceble is distributed through 2 packages that reflects our 2 main development and deployment branches. Both packages are stable but with 2 different phylosophies. Therefore, the choice is up to you. The 2 packages are `pyfunceble` and `pyfunceble-dev`. If you want a **stable** but **mature**, and **slowly** updating package, you should install the `pyfunceble` package. It reflects the `master` branch which only get updated once the new features and bugfixes of `pyfunceble-dev` are tested long enough to be considered mature. On the other hand, if you want a **stable** but **fast** updating package, you should install the `pyfunceble-dev` package. It reflects the `dev` branch which get updated frequently to allow the community to provide feedbacks as soon as possible. **Recommendation:** For most people the `pyfunceble` package should be sufficient. But if you want to help the community or always want to have the latest features and bugfix as soon as possible, you should prefer the `pyfunceble-dev` package. ## Overview: Installation Method | OS | Technology | Tools | Link | | --------- | --------------------------- | ------------ | ------------------------------------ | | Any | PyPi - Python Package Index | `pip3` | [Link](#pypi---python-package-index) | | Any | Container Image Registry | `docker` | [Link](#container-image-registry) | | Any | Git | `pip3` | [Link](#git-repository) | | Any | Zip File | `pip3` | [Link](#from-source) | | ArchLinux | AUR Helper | `aur-helper` | [Link](#arch-linux) | ## PyPi - Python Package Index Installing from the Python Package Index is for most people the prefered one - after the OS specific packages _(see below)_. Here is an overview of the packages and where they are hosted. | Package | PyPi Link | | -------------- | ------------------------------------------------------------------------------- | | pyfunceble | [https://pypi.org/project/PyFunceble](https://pypi.org/project/PyFunceble) | | pyfunceble-dev | [https://pypi.org/project/PyFunceblee-dev](https://pypi.org/project/PyFunceble) | !!! danger "Beware!!" We recommend the usage of the `--user` flag as it installs the required dependencies at the user level. The main reason behind that is to avoid crashes or clashes between you OS package manager and `pip3`. However, if you: - are aware of the possible consequences - are running PyFunceble within a CI engine or in an automated environment you shouldn't use it. ### pyfunceble You can install the **pyfunceble** through `pip3`: ```shell pip3 install --user pyfunceble ``` ### pyfunceble-dev You can install the **pyfunceble-dev** package through `pip3`: ```shell pip3 install --user pyfunceble-dev ``` If you want to help and use the unstable pre-releases, you should install with the `--pre` argument. ```shell pip3 install --user --pre pyfunceble-dev ``` ## Container Image Registry Installing from a Container Image Registry is the way to go if you are in a hurry or always want the best from the beat without having to look if an update is available. :smile: Here is an overview of the packages and where they are hosted. | Host | Package | Link | | ---------- | -------------- | -------------------------------------------------------------------------------------------------------- | | Docker Hub | pyfunceble | [https://hub.docker.com/r/pyfunceble/pyfunceble](https://hub.docker.com/r/pyfunceble/pyfunceble) | | Docker Hub | pyfunceble-dev | [https://hub.docker.com/r/pyfunceble/pyfunceble-dev](https://hub.docker.com/r/pyfunceble/pyfunceble-dev) | ### pyfunceble #### Docker Hub You can install the **pyfunceble** image from Docker Hub through `docker`: ```shell docker pull pyfunceble/pyfunceble ``` ### pyfunceble-dev #### Docker Hub You can install the **pyfunceble-dev** image from Docker Hub through `docker`: ```shell docker pull pyfunceble/pyfunceble-dev ``` ## Arch Linux Installing from the ArchLinux User Repository is the way to go if you are using ArchLinux. Here is an overview of the packages and where they are hosted. | Package | AUR Link | | -------------- | ------------------------------------------------------------------------------------------------------ | | pyfunceble | [https://aur.archlinux.org/packages/pyfunceble](https://aur.archlinux.org/packages/pyfunceble) | | pyfunceble-dev | [https://aur.archlinux.org/packages/pyfunceble-dev](https://aur.archlinux.org/packages/pyfunceble-dev) | ### pyfunceble #### AUR Helper You can install the **pyfunceble** package through your favorite AUR helper: ```shell aur-helper -S pyfunceble ``` #### Manually You can install the **pyfunceble** package manually through the following: ```shell git clone https://aur.archlinux.org/pyfunceble.git pyfunceble cd pyfunceble makepkg -fsri ``` ### pyfunceble-dev #### AUR Helper You can install the **pyfunceble-dev** package through your favorite AUR helper: ```shell aur-helper -S pyfunceble-dev ``` #### Manually You can install the **pyfunceble** package manually through the following: ```shell git clone https://aur.archlinux.org/pyfunceble-dev.git pyfunceble-dev cd pyfunceble-dev makepkg -fsri ``` ## Git Repository Installing from a Git Repository with `pip3` is not recommended for general user as you will easily get the latest development patches even before they get published. But if you are one of those who always want to be in sync with the latest development patches, this is probably for you. Here is an overview of the packages and where they are hosted. | Host | Package | Repository | | ------ | -------------- | ----------------------------------------------------------------------- | | GitHub | pyfunceble | `git+https://github.com/funilrys/PyFunceble.git@master#egg=PyFunceble` | | GitHub | pyfunceble-dev | `git+https://github.com/funilrys/PyFunceble.git@dev#egg=PyFunceble-dev` | | GitLab | pyfunceble | `git+https://gitlab.com/funilrys/PyFunceble.git@master#egg=PyFunceble` | | GitLab | pyfunceble-dev | `git+https://gitlab.com/funilrys/PyFunceble.git@dev#egg=PyFunceble-dev` | !!! danger "Beware!!" We recommend the usage of the `--user` flag as it installs the required dependencies at the user level. The main reason behind that is to avoid crashes or clashes between you OS package manager and `pip3`. However, if you: - are aware of the possible consequences - are running PyFunceble within a CI engine or in an automated environment you shouldn't use it. ### pyfunceble #### GitHub You can install the **pyfunceble** package from GitHub through `pip3`: ```shell pip3 install --user git+https://github.com/funilrys/PyFunceble.git@master#egg=PyFunceble ``` #### GitLab You can install the **pyfunceble** package from GitLab through `pip3`: ```shell pip3 install --user git+https://gitlab.com/funilrys/PyFunceble.git@master#egg=PyFunceble ``` ### pyfunceble-dev #### GitHub You can install the **pyfunceble-dev** package from GitHub through `pip3`: ```shell pip3 install --user git+https://github.com/funilrys/PyFunceble.git@dev#egg=PyFunceble-dev ``` #### GitLab You can install the **pyfunceble-dev** package from GitLab through `pip3`: ```shell pip3 install --user git+https://gitlab.com/funilrys/PyFunceble.git@dev#egg=PyFunceble-dev ``` ## From Source Installing from source is not recommended at all as you may need to keep the repository up-to-date by yourself. Here is an overview of the packages and where they are hosted. | Host | Package | Branch | Repository | | ------ | -------------- | -------- | -------------------------------------------------------------------------------------------------------- | | GitHub | pyfunceble | `master` | [https://github.com/funilrys/PyFunceble/tree/master](https://github.com/funilrys/PyFunceble/tree/master) | | GitHub | pyfunceble-dev | `dev` | [https://github.com/funilrys/PyFunceble/tree/dev](https://github.com/funilrys/PyFunceble/tree/dev) | | GitLab | pyfunceble | `master` | [https://gitlab.com/funilrys/PyFunceble/tree/master](https://gitlab.com/funilrys/PyFunceble/tree/master) | | GitLab | pyfunceble-dev | `dev` | [https://gitlab.com/funilrys/PyFunceble/tree/master](https://gitlab.com/funilrys/PyFunceble/tree/master) | You can install the package from source through `pip3`: ```shell # From Github pip3 install --upgrade --user https://github.com/funilrys/PyFunceble/archive/{{branch}}.zip # From GitLab pip3 install --upgrade --user https://gitlab.com/funilrys/PyFunceble/-/archive/{{branch}}/PyFunceble-{{branch}}.zip ```PyFunceble-4.2.29.dev/docs/use/known-issues.md000066400000000000000000000067601467462152100211550ustar00rootroot00000000000000# Known Issues On this page, you will find any issues that are known and not fixed - yet. ## Python Support Any Python version lower than `3.7` are not compatible with PyFunceble. This means you actually are unable to run any version below Python 3.7 as a number of used builtin features are missing and were first introduced in Python 3.7. Here are some of the message you might experience: ```python Fatal Error: type object 'datetime.datetime' has no attribute 'fromisoformat' ``` ```python ModuleNotFoundError: No module named 'dataclasses' ``` ## PyFunceble CLI ### Combination of `-f`, `-uf` and `--adblock` You can't use the following arguments simultaneously: - `-f` | `--file` - `-uf` | `--url-file` - `--adblock` ### SQL Error: Missing default value If you are trying to move or restore your SQL database from a dump, you may see an error message that looks like this: ```sql SQL Error [1364][HY000]: (conn=12345678) Field 'created_at' doesn't have a default value (conn=12345678) Field 'created_at' doesn't have a default value (conn=12345678) Field 'created_at' doesn't have a default value Field 'created_at' doesn't have a default value ``` The issue arises from the way PyFunceble configures [SQLAlchemy](https://www.sqlalchemy.org/) as PyFunceble is assuming the full control of the datasets by setting the default on the software side and not in the database. To solve the issue, you will have to manually set the default for `created_at` to for example `2020-12-22 09:09:50` in `pyfunceble_whois_record` table. You can use [dBeaver](https://dbeaver.io/) or manually run the following SQL statement inside your database. ```sql ALTER TABLE pyfunceble_whois_record MODIFY COLUMN created_at datetime DEFAULT '2020-12-22 09:09:50' NOT NULL; ``` ## Operating Systems ### Ubuntu #### Ubuntu 20.04.1 LTS - Focal In Ubuntu 20.04, the dynamicly linked library named `libffi.so.6` has been replaced with `libffi.so.7`. This means that PyFunceble will throw such errors: ``` ImportError: libffi.so.6: cannot open shared object file: No such file or directory ``` The problem can be solved through the creation of a softlink between the version with the following: ```shell sudo ln -s /usr/lib/x86_64-linux-gnu/libffi.so.7 /usr/lib/x86_64-linux-gnu/libffi.so.6 ``` !!! warning "" Please locate `libffi.so.7` first through: ```shell find /usr/lib/ -type f -iname 'libffi.so.*' ``` ### Windows #### Windows Powershell with Python or Cygwin There are a number of well Known limitation by running or even installing Python on Windows. If you intend to run PyFunceble through Powershell, you have to ensure that Python is installed into the system's `PATH` environment variable. Otherwise, your Powershell won't be able to locate the PyFunceble executable. If however you intend to run PyFunceble through Cygwin, you have to manually define the `PATH` (as Cygwin won't follow the system-wide settings) or use the absolute path of the PyFunceble executable. !!! note "" Since this issue is not directly related to PyFunceble, you may document yourself throught the [issue #127](https://github.com/funilrys/PyFunceble/issues/127). ## CI / CD Engines ### Travis CI While using PyFunceble under the Travis CI engine, no coloration will be displayed. ### GitLab CI/CD While using PyFunceble under the GitLab CI/CD engine, no coloration will be displayed. ### GitHub Workflows While using PyFunceble under the GitHub Workflows/Actions engine, no coloration will be displayed. PyFunceble-4.2.29.dev/docs/use/update.md000066400000000000000000000175401467462152100177700ustar00rootroot00000000000000# Update Updating PyFunceble is as easy as the installation. ## Overview: Update Method | OS | Technology | Tools | Link | | --------- | --------------------------- | ------------ | ------------------------------------ | | Any | PyPi - Python Package Index | `pip3` | [Link](#pypi---python-package-index) | | Any | Container Image Registry | `docker` | [Link](#container-image-registry) | | Any | Git | `pip3` | [Link](#git-repository) | | Any | Zip File | `pip3` | [Link](#from-source) | | ArchLinux | AUR Helper | `aur-helper` | [Link](#arch-linux) | ## PyPi - Python Package Index Updating a `pip` installed package is straight forward. Just append `--upgrade` to you installation command and you are good to go. Here is an overview of the packages and where they are hosted. | Package | PyPi Link | |----------------|---------------------------------------------------------------------------------| | pyfunceble | [https://pypi.org/project/PyFunceble](https://pypi.org/project/PyFunceble) | | pyfunceble-dev | [https://pypi.org/project/PyFunceblee-dev](https://pypi.org/project/PyFunceble) | !!! danger "Beware!!" We recommend the usage of the `--user` flag as it installs the required dependencies at the user level. The main reason behind that is to avoid crashes or clashes between you OS package manager and `pip3`. However, if you: - are aware of the possible consequences - are running PyFunceble within a CI engine or in an automated environment you shouldn't use it. ### pyfunceble You can update the **pyfunceble** through `pip3`: ```shell pip3 install --user --upgrade pyfunceble ``` ### pyfunceble-dev You can update the **pyfunceble-dev** package through `pip3`: ```shell pip3 install --user --upgrade pyfunceble-dev ``` If you want to help and use the unstable pre-releases, you should update with the `--pre` argument. ```shell pip3 install --user --pre --upgrade pyfunceble-dev ``` ## Container Image Registry Updating from a Container Image Registry is easier. If you allowed your container engine to automatically pull the `latest` tag, you have nothing to do. The new layers are downloaded before you run PyFunceble. Here is an overview of the packages and where they are hosted. | Host | Package | Link | |------------|----------------|----------------------------------------------------------------------------------------------------------| | Docker Hub | pyfunceble | [https://hub.docker.com/r/pyfunceble/pyfunceble](https://hub.docker.com/r/pyfunceble/pyfunceble) | | Docker Hub | pyfunceble-dev | [https://hub.docker.com/r/pyfunceble/pyfunceble-dev](https://hub.docker.com/r/pyfunceble/pyfunceble-dev) | ## Arch Linux Updating from the ArchLinux User Repository is straight forward. Here is an overview of the packages and where they are hosted. | Package | AUR Link | |----------------|--------------------------------------------------------------------------------------------------------| | pyfunceble | [https://aur.archlinux.org/packages/pyfunceble](https://aur.archlinux.org/packages/pyfunceble) | | pyfunceble-dev | [https://aur.archlinux.org/packages/pyfunceble-dev](https://aur.archlinux.org/packages/pyfunceble-dev) | ### pyfunceble #### AUR Helper You can update the **pyfunceble** package through your favorite AUR helper: ```shell aur-helper -Syu pyfunceble ``` #### Manually You can update the **pyfunceble** package manually through the following: ```shell git clone https://aur.archlinux.org/pyfunceble.git pyfunceble cd pyfunceble makepkg -fsri ``` ### pyfunceble-dev #### AUR Helper You can update the **pyfunceble-dev** package through your favorite AUR helper: ```shell aur-helper -Syu pyfunceble-dev ``` #### Manually You can update the **pyfunceble** package manually through the following: ```shell git clone https://aur.archlinux.org/pyfunceble-dev.git pyfunceble-dev cd pyfunceble-dev makepkg -fsri ``` ## Git Repository Updating from the Git Repository with `pip3` is just like a normal update of `pip` installed package. Just add `--upgrade` to your installation command and you are good to go. Here is an overview of the packages and where they are hosted. | Host | Package | Repository | |--------|----------------|-------------------------------------------------------------------------| | GitHub | pyfunceble | `git+https://github.com/funilrys/PyFunceble.git@master#egg=PyFunceble` | | GitHub | pyfunceble-dev | `git+https://github.com/funilrys/PyFunceble.git@dev#egg=PyFunceble-dev` | | GitLab | pyfunceble | `git+https://gitlab.com/funilrys/PyFunceble.git@master#egg=PyFunceble` | | GitLab | pyfunceble-dev | `git+https://gitlab.com/funilrys/PyFunceble.git@dev#egg=PyFunceble-dev` | !!! danger "Beware!!" We recommend the usage of the `--user` flag as it installs the required dependencies at the user level. The main reason behind that is to avoid crashes or clashes between you OS package manager and `pip3`. However, if you: - are aware of the possible consequences - are running PyFunceble within a CI engine or in an automated environment you shouldn't use it. ### pyfunceble #### GitHub You can update the **pyfunceble** package from GitHub through `pip3`: ```shell pip3 install --user --upgrade git+https://github.com/funilrys/PyFunceble.git@master#egg=PyFunceble ``` #### GitLab You can update the **pyfunceble** package from GitLab through `pip3`: ```shell pip3 install --user --upgrade git+https://gitlab.com/funilrys/PyFunceble.git@master#egg=PyFunceble ``` ### pyfunceble-dev #### GitHub You can update the **pyfunceble-dev** package from GitHub through `pip3`: ```shell pip3 install --user --upgrade git+https://github.com/funilrys/PyFunceble.git@dev#egg=PyFunceble-dev ``` #### GitLab You can update the **pyfunceble-dev** package from GitLab through `pip3`: ```shell pip3 install --user --upgrade git+https://gitlab.com/funilrys/PyFunceble.git@dev#egg=PyFunceble-dev ``` ## From Source Updating from the source with `pip3` is just like a normal update of `pip` installed package. Just add `--upgrade` to your installation command and you are good to go. Here is an overview of the packages and where they are hosted. | Host | Package | Branch | Repository | | ------ | -------------- | -------- | -------------------------------------------------------------------------------------------------------- | | GitHub | pyfunceble | `master` | [https://github.com/funilrys/PyFunceble/tree/master](https://github.com/funilrys/PyFunceble/tree/master) | | GitHub | pyfunceble-dev | `dev` | [https://github.com/funilrys/PyFunceble/tree/dev](https://github.com/funilrys/PyFunceble/tree/dev) | | GitLab | pyfunceble | `master` | [https://gitlab.com/funilrys/PyFunceble/tree/master](https://gitlab.com/funilrys/PyFunceble/tree/master) | | GitLab | pyfunceble-dev | `dev` | [https://gitlab.com/funilrys/PyFunceble/tree/master](https://gitlab.com/funilrys/PyFunceble/tree/master) | You can install the package from source through `pip3`: ```shell # From Github pip3 install --upgrade --user https://github.com/funilrys/PyFunceble/archive/{{branch}}.zip # From GitLab pip3 install --upgrade --user https://gitlab.com/funilrys/PyFunceble/-/archive/{{branch}}/PyFunceble-{{branch}}.zip ```PyFunceble-4.2.29.dev/examples/000077500000000000000000000000001467462152100162475ustar00rootroot00000000000000PyFunceble-4.2.29.dev/examples/api_usage/000077500000000000000000000000001467462152100202045ustar00rootroot00000000000000PyFunceble-4.2.29.dev/examples/api_usage/advanced.py000066400000000000000000000017661467462152100223350ustar00rootroot00000000000000""" This is an advanced example which get more information about the tested element. """ from PyFunceble import DomainAndIPAvailabilityChecker, URLAvailabilityChecker SUBJECTS = ["google.com", "github.com", "example.org", "9.9.9.10", "149.112.112.10"] if __name__ == "__main__": domain_ip_avail_checker = DomainAndIPAvailabilityChecker(use_whois_lookup=False) url_avail_checker = URLAvailabilityChecker() for subject in SUBJECTS: domain_ip_avail_checker.subject = subject url_avail_checker.subject = f"https://{subject}" domain_ip_status = domain_ip_avail_checker.get_status() url_status = url_avail_checker.get_status() print( f"============== COMPLETE DATA: {domain_ip_avail_checker.subject} " "==============" ) print(domain_ip_status.to_json(), "\n\n") print( f"============== COMPLETE DATA: {url_avail_checker.subject} ==============" ) print(url_status.to_json(), "\n\n") PyFunceble-4.2.29.dev/examples/api_usage/basic.py000066400000000000000000000010251467462152100216350ustar00rootroot00000000000000""" This is a basic example which prints one of the availability of the given domain and URL. .. note: Official output: ACTIVE, INACTIVE, INVALID """ from PyFunceble import DomainAndIPAvailabilityChecker, URLAvailabilityChecker if __name__ == "__main__": print("Start of basic example.") DOMAIN = "github.com" URL = f"https://{DOMAIN}" print(DOMAIN, DomainAndIPAvailabilityChecker(DOMAIN).get_status().status) print(URL, URLAvailabilityChecker(URL).get_status().status) print("End of basic example ") PyFunceble-4.2.29.dev/examples/api_usage/basic_syntax.py000066400000000000000000000032651467462152100232530ustar00rootroot00000000000000""" This is a basic example which checks syntax. """ from PyFunceble import ( DomainSyntaxChecker, IPv4SyntaxChecker, SubDomainSyntaxChecker, URLSyntaxChecker, ) if __name__ == "__main__": print(f"Starting syntax check using {DomainSyntaxChecker}") checker = DomainSyntaxChecker() for domain in ["google.com", "forest-jump"]: print(f"{domain} VALID ? {checker.set_subject(domain).is_valid()}") print(f"Finished syntax check using {DomainSyntaxChecker}\n") print(f"Starting syntax check using {URLSyntaxChecker}") checker = URLSyntaxChecker() for domain in ["https://google.com", "https://forest-jump"]: print(f"{domain} VALID ? {checker.set_subject(domain).is_valid()}") print(f"Finished syntax check using {URLSyntaxChecker}\n") print(f"Starting syntax check using {IPv4SyntaxChecker}") checker = IPv4SyntaxChecker() for domain in ["216.58.207.46", "257.58.207.46"]: print(f"{domain} VALID ? {checker.set_subject(domain).is_valid()}") print(f"Finished syntax check using {IPv4SyntaxChecker}\n") print(f"Starting syntax check (range) using {IPv4SyntaxChecker}") checker = IPv4SyntaxChecker() for domain in ["192.168.0.0/24", "192.168.0.0"]: print(f"{domain} VALID range ? {checker.set_subject(domain).is_valid_range()}") print(f"Finished syntax check (range) using {IPv4SyntaxChecker}\n") print(f"Starting syntax check using {SubDomainSyntaxChecker}") checker = SubDomainSyntaxChecker() for domain in ["hello.google.com", "google.com"]: print(f"{domain} VALID ? {checker.set_subject(domain).is_valid()}") print(f"Finished syntax check using {SubDomainSyntaxChecker}\n") PyFunceble-4.2.29.dev/examples/api_usage/custom_configuration.py000066400000000000000000000030541467462152100250210ustar00rootroot00000000000000""" This is an example about how we can update the configuration while developping on top of PyFunceble. """ import PyFunceble.facility from PyFunceble import DomainAvailabilityChecker # We preset the indexes (from .PyFunceble.yaml) that we want to update. CUSTOM_CONFIGURATION_INDEX_VALUE_TO_SET = { "lookup": {"whois": False, "dns": False}, "cli_testing": {"db_type": "csv"}, } if __name__ == "__main__": # We parse our custom indexes to PyFunceble before starting to use it. PyFunceble.facility.ConfigLoader.start() PyFunceble.facility.ConfigLoader.custom_config = ( CUSTOM_CONFIGURATION_INDEX_VALUE_TO_SET ) # From now, each call of test so in this example PyFuncebleTest, # will not try to get/request the WHOIS record. DOMAINS = ["google.com", "github.com"] print("Start with global custom configuration.") for DOMAIN in DOMAINS: # This should return None. print(DOMAIN, DomainAvailabilityChecker(DOMAIN).get_status().whois_record) print("End with global custom configuration.\n") print("Start with local setting.") for DOMAIN in DOMAINS: print(f"Start of WHOIS record of {DOMAIN} \n") # This part should return the WHOIS record. # This will - at each call we manually overwrite the configurated value. print( DOMAIN, DomainAvailabilityChecker(DOMAIN, use_whois_lookup=True) .get_status() .whois_record, ) print(f"End of WHOIS record of {DOMAIN} \n") print("End with local setting.") PyFunceble-4.2.29.dev/examples/api_usage/file_generation.py000066400000000000000000000100121467462152100237020ustar00rootroot00000000000000""" This is an example which let us manipulate the data and also generate the files as if it was the CLI. """ import copy import os import sys import colorama import PyFunceble.facility import PyFunceble.storage from PyFunceble import DomainAvailabilityChecker from PyFunceble.cli.filesystem.dir_structure.restore import ( DirectoryStructureRestoration, ) from PyFunceble.cli.processes.producer import ProducerProcessesManager from PyFunceble.utils.platform import PlatformUtility # This is needed as our idea is to communicate with the producer thread instead # of trying to reimplement everything. # So, this describes the dataset as they are sent to the tester thread (normally) STD_COMMUNICATION_DATASET = { "type": "single", "subject_type": "domain", # Destination inside the output directory. "destination": "my_awesome_pyfunceble_wrapper", "subject": None, "idna_subject": None, "source": "my_awesome_pyfunceble_wrapper", "output_dir": None, # Will be handled autom "checker_type": "AVAILABILITY", # Must be one of our supported one!! } DOMAINS = ["github.com", "twitter.com"] if __name__ == "__main__": # We initiate the coloration. colorama.init(autoreset=True) # We are in control, so we need to manually start the loading. PyFunceble.facility.ConfigLoader.custom_config = { "cli_testing": { "file_generation": {"plain": True}, "display_mode": {"quiet": True}, } } PyFunceble.facility.ConfigLoader.start() # In this example, we are cleaning up and regenerating the output directory # at each run. dir_structure_restoration = DirectoryStructureRestoration( parent_dirname=STD_COMMUNICATION_DATASET["destination"] ).restore_from_backup() # We start the producer thread. producer_process_manager = ProducerProcessesManager( max_worker=1, daemon=True, generate_output_queue=False ) producer_process_manager.start() # We start and configure our availability checker. avail_checker = DomainAvailabilityChecker(use_whois_lookup=False) for domain in DOMAINS: # We loop through our list of subject to test. # We parse the current subject to the availability checker. avail_checker.subject = domain # Now we fetch the status object. test_result = avail_checker.get_status() # We prepare our communication dataset. communication_dataset = copy.deepcopy(STD_COMMUNICATION_DATASET) communication_dataset["subject"] = test_result.subject communication_dataset["idna_subject"] = test_result.idna_subject # We print the result (for us as we call this script.) print( f"{test_result.idna_subject} (IDNA: {test_result.subject}) " f"is {test_result.status}" ) # We order the generation of the status file by putting our information # to the producer queue. producer_process_manager.add_to_input_queue( (communication_dataset, test_result) ) # We are now done, it's time to send the stop signal. # The stop signal will inform thhe producer thread that it needs to stop # listening to new order (from the time it reads the stop signal). producer_process_manager.send_stop_signal(worker_name="main") # Now we wait until it's done. producer_process_manager.wait() # From here all files were generated we can do whatever we want with them. unix_path = os.path.join( dir_structure_restoration.get_output_basedir(), "domains", "ACTIVE", "list" ) win_path = f"{unix_path}.txt" path_to_use = unix_path if PlatformUtility.is_unix() else win_path if os.path.isfile(path_to_use): print( f"{colorama.Style.BRIGHT}{colorama.Fore.GREEN}All right, " "files correctly generated!" ) sys.exit(0) else: print( f"{colorama.Style.BRIGHT}{colorama.Fore.RED}Something went wrong, " "files not correctly generated!" ) sys.exit(1) PyFunceble-4.2.29.dev/examples/api_usage/loop.py000066400000000000000000000024721467462152100215340ustar00rootroot00000000000000""" This is a loop example which tests a list of domain and processes some action according to one of the official output of PyFunceble. Note: * Official output: ACTIVE, INACTIVE, INVALID * You should always use PyFunceble().test() as it's the method which is especially suited for `__name__ != '__main__'` usage. """ from PyFunceble import DomainAndIPAvailabilityChecker, URLAvailabilityChecker DOMAINS = ["twitter.com", "google.com", "github.com", "github.comcomcom", "funilrys.co"] def domain_status(domain_or_ip): """ Check the status of the given domain name or IP. Argument: - domain_or_ip: str The domain or IPv4 to test. Returns: str The status of the domain. """ return DomainAndIPAvailabilityChecker(domain_or_ip).get_status().status def url_status(url): """ Check the status of the given url. Argument: - url: str The URL to test. Returns: str The status of the URL. """ return URLAvailabilityChecker(url).get_status().status if __name__ == "__main__": print("Start of loop example.") for domain in DOMAINS: print( f"{domain} is {domain_status(domain)} and " f"http://{domain} is {url_status(f'http://{domain}')} " ) print("End of loop example.") PyFunceble-4.2.29.dev/examples/api_usage/reputation.py000066400000000000000000000022641467462152100227540ustar00rootroot00000000000000""" This is an example which checks that the test with the reputation data is correct. """ import colorama from PyFunceble import DomainAndIPReputationChecker from PyFunceble.dataset.ipv4_reputation import IPV4ReputationDataset reputation_checker = DomainAndIPReputationChecker() reputation_dataset = IPV4ReputationDataset().get_content() LIMIT = 10 MALICIOUS_SUBJECTS = [ next(reputation_dataset).split("#", 1)[0] for _ in range(LIMIT + 1) ] SANE_SUBJECTS = ["twitter.com", "google.com", "github.com"] if __name__ == "__main__": colorama.init(autoreset=True) for subject in MALICIOUS_SUBJECTS: reputation_checker.subject = subject status = reputation_checker.get_status() if not status.is_malicious(): raise RuntimeError(f"Something is wrong with {subject}.") print(f"{subject} is {status.status}") for subject in SANE_SUBJECTS: reputation_checker.subject = subject status = reputation_checker.get_status() if not status.is_sane(): raise RuntimeError( f"Something is wrong with {subject}. Dataset:\n{status.to_json()}" ) print(f"{subject} is {status.status}") PyFunceble-4.2.29.dev/examples/demo/000077500000000000000000000000001467462152100171735ustar00rootroot00000000000000PyFunceble-4.2.29.dev/examples/demo/config.sh.in000066400000000000000000000012241467462152100214000ustar00rootroot00000000000000# Common config for demo scripts configure() { DELAY=0.07 DELAY_SEP=0.22 DELAY_PROMPT=0.6 # No messages/warnings in the current versions of the scripts # but if we add them, their colors can be changed here # COLOR_WARNING='1;91' # COLOR_MESSAGE='1;32' # If you want to use the colorful prompt TUTERM_NAME='PyFunceble-demo' # Set the terminal width/height } prompt() { # For a more colorful prompt, uncomment the following: # echo -ne "\033[1;94m$TUTERM_NAME \033[1;35m$(pwd | sed "s:$HOME:~:")\033[0;33m $\033[0m " echo -ne '\e[34m(tuterm)\e[m \e[33mpyfunceble\e[m @ \e[36mfunilrys\e[m \e[32m~\e[m $ ' } PyFunceble-4.2.29.dev/examples/demo/landing_page_demo_1.tut000066400000000000000000000007211467462152100235650ustar00rootroot00000000000000#!/usr/bin/env tuterm # pyfunceble-io-title: PyFunceble gives you the availability of a domain! # asciinema-title: PyFunceble domains availability # asciinema-cols: 200 # asciinema-rows: 20 source config.sh.in run() { c pyfunceble --version c pyfunceble -a -d example.org c pyfunceble -a -d example.org --whois-lookup c pyfunceble -a -d exampleeeeeeeeeeeeeeeeeeeee.com c pyfunceble -a -d microsoft_google.com c exit } # vim: filetype=sh PyFunceble-4.2.29.dev/examples/demo/landing_page_demo_2.tut000066400000000000000000000015241467462152100235700ustar00rootroot00000000000000#!/usr/bin/env tuterm # pyfunceble-io-title: PyFunceble gives you the availability of an IP! # asciinema-title: PyFunceble IP availability # asciinema-cols: 200 # asciinema-rows: 20 source config.sh.in run() { c pyfunceble --version c pyfunceble -d 9.9.9.10 # quad9 Neutral stable (unfiltered) c pyfunceble -d 2620:fe::fe # quad9 IPv6 (As I recall GHA now supports IPv6) c pyfunceble -d 194.187.99.221 # Adult CDN: https://mypdns.org/my-privacy-dns/porn-records/-/issues?scope=all&state=all&label_name[]=IP%3A%3ABlackListing c pyfunceble -d 45.136.204.40 # 23 phis: https://github.com/mitchellkrogza/phishing/pull/67 c pyfunceble -u http://18.191.88.103/login.html # As we can do urls too, this is a inactive Phis c exit } # vim: filetype=sh PyFunceble-4.2.29.dev/examples/demo/landing_page_demo_3.tut000066400000000000000000000010301467462152100235610ustar00rootroot00000000000000#!/usr/bin/env tuterm # pyfunceble-io-title: PyFunceble gives you the availability of a URL! # asciinema-title: PyFunceble URL availability # asciinema-cols: 200 # asciinema-rows: 20 workDir="$(dirname $(realpath ${0}))" source "${workDir}/config.sh.in" run() { c pyfunceble --version c pyfunceble -u https://github.com/funilrys c pyfunceble -u https://github.com/microsoft_google c pyfunceble -u https://microsoft_google.com c pyfunceble -u https://microsoft_google.com --local c exit } # vim: filetype=sh PyFunceble-4.2.29.dev/examples/demo/record.sh000066400000000000000000000035121467462152100210060ustar00rootroot00000000000000#!/usr/bin/env bash set -e hash awk hash pyfunceble tmpDir="/tmp/pyfunceble-demos" if [[ ! -d ${tmpDir} ]] then mkdir -p "${tmpDir}" fi echo "Pre-warming for better recording performance" pyfunceble --version >/dev/null for file in "${@}"; do castFile="${tmpDir}/$(basename "${file}").cast" castTitle="$(fgrep "asciinema-title" ${file} | awk -v FS=": " '{ print $2}')" castColumns="$(fgrep "asciinema-cols" ${file} | awk -v FS=": " '{ print $2}')" castRows="$(fgrep "asciinema-rows" ${file} | awk -v FS=": " '{ print $2}')" if [[ -z "${castTitle}" ]] then castTitle="PyFunceble" fi if [[ -z "${castColumns}" ]] then castColumns=200 fi if [[ -z "${castRows}" ]] then castRows=20 fi rm -f "${castFile}" stty cols "${castColumns}" rows "${castRows}" asciinema rec -t "${castTitle}" -c "tuterm ${file} --mode demo" "${castFile}" done #!/usr/bin/env bash set -e hash awk hash pyfunceble tmpDir="/tmp/pyfunceble-demos" if [[ ! -d ${tmpDir} ]] then mkdir -p "${tmpDir}" fi echo "Pre-warming for better recording performance" pyfunceble --version >/dev/null for file in "${@}"; do castFile="${tmpDir}/$(basename "${file}").cast" castTitle="$(fgrep "asciinema-title" ${file} | awk -v FS=": " '{ print $2}')" castColumns="$(fgrep "asciinema-cols" ${file} | awk -v FS=": " '{ print $2}')" castRows="$(fgrep "asciinema-rows" ${file} | awk -v FS=": " '{ print $2}')" if [[ -z "${castTitle}" ]] then castTitle="PyFunceble" fi if [[ -z "${castColumns}" ]] then castColumns=200 fi if [[ -z "${castRows}" ]] then castRows=20 fi rm -f "${castFile}" stty cols "${castColumns}" rows "${castRows}" asciinema rec -t "${castTitle}" -c "tuterm ${file} --mode demo" "${castFile}" done PyFunceble-4.2.29.dev/examples/demo/record_all.sh000077500000000000000000000002141467462152100216350ustar00rootroot00000000000000#!/usr/bin/env bash set -e workDir="$(dirname $(realpath ${0}))" for file in ${workDir}/*.tut do ${workDir}/record.sh "${file}" done PyFunceble-4.2.29.dev/examples/demo/replay.sh000077500000000000000000000004461467462152100210320ustar00rootroot00000000000000#!/usr/bin/env bash set -e hash pyfunceble tmpDir="/tmp/pyfunceble-demos" for file in "${@}"; do castFile="${tmpDir}/$(basename "${file}").cast" if [[ -f "${castFile}" ]] then asciinema play "${castFile}" else echo "File not found: ${castFile}" fi done PyFunceble-4.2.29.dev/examples/demo/replay_all.sh000077500000000000000000000002121467462152100216510ustar00rootroot00000000000000#!/usr/bin/env bash set -e workDir="$(dirname $(realpath ${0}))" for file in ${workDir}/*.tut do ${workDir}/replay.sh ${file} done PyFunceble-4.2.29.dev/examples/demo/upload.sh000066400000000000000000000007501467462152100210150ustar00rootroot00000000000000#!/usr/bin/env bash set -e hash asciinema hash grep hash sed tmpDir="/tmp/pyfunceble-demos" for file in "${@}"; do castFile="/${tmpDir}/$(basename "${file}").cast" asciinema upload ${castFile} | grep 'https:' | sed 's/^\s*//' done #!/usr/bin/env bash set -e hash asciinema hash grep hash sed tmpDir="/tmp/pyfunceble-demos" for file in "${@}"; do castFile="/${tmpDir}/$(basename "${file}").cast" asciinema upload ${castFile} | grep 'https:' | sed 's/^\s*//' done PyFunceble-4.2.29.dev/examples/demo/upload_all.sh000077500000000000000000000022601467462152100216460ustar00rootroot00000000000000#!/usr/bin/env bash set -e workDir="$(dirname $(realpath ${0}))" tmpDir="/tmp/pyfunceble-demos" jsonDest="${tmpDir}/asciinema_demo.json" jsonTemplate='{"title": "%%title%%","link": "%%link%%"}' templates=() finalJson="" for file in ${workDir}/*.tut do pyfuncebleIOTitle="$(fgrep "pyfunceble-io-title" ${file} | awk -v FS=": " '{ print $2}')" if [[ -z "${pyfuncebleIOTitle}" ]] then pyfuncebleIOTitle="PyFunceble-Demo" fi # uploadLink=$(${workDir}/upload.sh ${file}) uploadLink="https://github.com" if [[ "${uploadLink}" =~ ^https:.* ]] then localTemplate="${jsonTemplate}" localTemplate="${localTemplate//%%title%%/${pyfuncebleIOTitle}}" localTemplate="${localTemplate//%%link%%/${uploadLink}/iframe}" templates[${#templates[@]}]="${localTemplate}" fi done finalJson+="[" templatesLength="${#templates[@]}" for index in "${!templates[@]}" do if [[ ! -z ${templates[${index}]} ]] then finalJson+="${templates[${index}]}" if [[ "${index}" != "$((${templatesLength}-1))" ]] then finalJson+="," fi fi done finalJson+="]" echo "${finalJson}" >> "${jsonDest}" PyFunceble-4.2.29.dev/examples/lists/000077500000000000000000000000001467462152100174055ustar00rootroot00000000000000PyFunceble-4.2.29.dev/examples/lists/adblock000066400000000000000000000005651467462152100207350ustar00rootroot00000000000000!@@||funceble.world/js !funilrys.com##body !||world.hello/*ad.xml @@||cnn.com/*ad.xml bing.com,bingo.com#@##adBanner facebook.com###player-above-2 hello#@#badads hubgit.com|oohay.com|ipa.elloh.dlorw#@#awesomeWorld yahoo.com,msn.com,api.hello.world#@#awesomeWorld ||api.google.com/papi/action$popup ||google.com$script,image ||twitter.com^ ~github.com,hello.world##.wrapper PyFunceble-4.2.29.dev/examples/lists/idna000066400000000000000000000000741467462152100202440ustar00rootroot00000000000000bittrรฉแบ‹.com coinbศงse.com cryptopiแบก.com cแน™yptopia.comPyFunceble-4.2.29.dev/examples/lists/simple000066400000000000000000000025471467462152100206310ustar00rootroot00000000000000paris-.blogspot.com.ar ip6-allrouters film-porno-.ze.cx paris-.blogspot.com.br ip6-allnodes paris-.blogspot.gr google.com #jfeofjeio paris-.blogspot.no paris-.blogspot.co.id paris-.blogspot.mx alyssa-.ifrance.com xbasfbno.info javakiba.org* 247?realmedia.com piti.bplaced.net mangas-porno-.has.it m.pr0gramm.com localhost adtrackone.eu$document ip6-localnet local paris-.blogspot.ch paris-.blogspot.co.uk i-52b.-xxx.ut.bench.utorrent.com kdowqlpt.info static.hk.rs ip6-localhost freeโ€celebrityโ€tube.com px.moatads.compx.moatads.com hurensohn.pr0gramm.com hans.pr0gramm.com metrika.ron.si publicโ€sluts.net xy.nullrefexcep.com px.moatads.com,z.moatads.com abc.pema.cl telemetry.appex.bing.net:443 paris-.blogspot.com.tr ip6-mcastprefix goreanharbourreysa-.4ya.nl paris-.blogspot.com adblade.com,popup paris-.blogspot.ca paris-.blogspot.sk cryweb.github.io web.die-news.pw mailto:info@mypornbible.com allosexe-.myblox.fr gogog@hehehe.blogspot.de websitealive[0-9].com ip6-allhosts crywebber.github.io azvjudwr.info host.d-ns.ga paris-.blogspot.it jroqvbvw.info securepubads.g.doubleclick.net ip6-loopback localhost.localdomain st.kjli.fi 1-1-1-.ib.adnxs.com jyhfuqoh.info cdn.rove.cl sexchat-.startspin.nl paris-.blogspot.com.es paris-.blogspot.de broadcasthost cdnfile.xyz xmr.-eu1.nanopool.org durl=px.moatads.com moherland.pl, 0.0.0.0 preview-.stripchat.com paris-.blogspot.pt PyFunceble-4.2.29.dev/mkdocs.yml000066400000000000000000000101621467462152100164340ustar00rootroot00000000000000site_name: PyFunceble theme: name: material palette: # Palette toggle for dark mode - scheme: slate primary: indigo toggle: icon: material/brightness-4 name: Switch to light mode # Palette toggle for light mode - scheme: default primary: indigo toggle: icon: material/brightness-7 name: Switch to dark mode logo: https://github.com/PyFunceble/logo/raw/master/Green/HD/Logomark.png favicon: https://github.com/PyFunceble/logo/raw/master/Green/Favicons/75x75.png features: - navigation.footer - content.action.edit - content.code.copy - navigation.tabs - content.code.annotate icon: repo: fontawesome/brands/github # TOOD: Switch to main branch. edit_uri: edit/switch-to-mkdocs/docs/ extra: social: - icon: fontawesome/brands/twitter link: https://twitter.com/pyfunceble - icon: fontawesome/brands/docker link: https://hub.docker.com/u/pyfunceble - icon: fontawesome/brands/github link: https://github.com/funilrys/PyFunceble - icon: fontawesome/brands/github link: https://github.com/PyFunceble copyright: | Copyright © 2017 - 2024 Nissar Chababy (@funilrys) & PyFunceble Contributors markdown_extensions: - admonition - pymdownx.highlight: anchor_linenums: yes line_spans: __span pygments_lang_class: yes - pymdownx.inlinehilite - pymdownx.snippets - pymdownx.details - pymdownx.superfences - pymdownx.tabbed: alternate_style: yes - footnotes - tables - attr_list - pymdownx.emoji: emoji_index: !!python/name:material.extensions.emoji.twemoji emoji_generator: !!python/name:material.extensions.emoji.to_svg plugins: - search - offline: enabled: true - autorefs - mkdocstrings: default_handler: python handlers: python: options: docstring_style: sphinx - gen-files: scripts: - docs/gen_ref_pages.py - literate-nav: nav_file: SUMMARY.md - section-index - git-revision-date-localized: enable_creation_date: yes fallback_to_build_date: yes repo_name: funilrys/PyFunceble repo_url: https://github.com/funilrys/PyFunceble nav: - Home: - index.md - Installation: use/installation.md - Update: use/update.md - User Guides: - use/index.md - Installation: use/installation.md - Update: use/update.md - Getting Started: use/getting-started.md - Examples: - Availability Check: use/examples/availability.md - Syntax Check: use/examples/syntax.md - Configuration: - use/configuration/index.md - Location: use/configuration/location.md - Environment Variables: use/configuration/environment-variables.md - Parameters: use/configuration/parameters/ - CI/CD: - GitHub Actions: use/ci-cd/github-actions.md - GitLab CI/CD: use/ci-cd/gitlab-ci-cd.md - Travis CI: use/ci-cd/travis-ci.md - FAQ: use/faq.md - Known Issues: use/known-issues.md - Developer Guides: - Getting Started: develop/getting-started.md - Checker Responses: develop/checker-responses.md - Examples: - Domain Availability: develop/examples/domain-availability.md - Domain Syntax: develop/examples/domain-syntax.md - Domain & IP Availability: develop/examples/domain-ip-availability.md - IP Availability: develop/examples/ip-availability.md - IP Syntax: develop/examples/ip-syntax.md - URL Availability: develop/examples/url-availability.md - URL Syntax: develop/examples/url-syntax.md - File Generation: develop/examples/file-generation.md - Code References: develop/api-references/index.md - Contribution Guides: - Contributing: contributing/contributing.md - Code of Conduct: contributing/code-of-conduct.md - About: - History & Origins: about/history.md - License: about/license.md - Contributors: about/contributors.md - Special Thanks: about/special-thanks.md - Get Help: help.md - Support: support.md PyFunceble-4.2.29.dev/output/000077500000000000000000000000001467462152100157715ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/.gitignore000066400000000000000000000000441467462152100177570ustar00rootroot00000000000000* !.gitignore !__pyfunceble_origin__PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/000077500000000000000000000000001467462152100222705ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/.gitignore000066400000000000000000000001021467462152100242510ustar00rootroot00000000000000* !.gitignore !Analytic/ !domains/ !ips/ !hosts/ !logs/ !splitted/PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/Analytic/000077500000000000000000000000001467462152100240345ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/Analytic/.gitignore000066400000000000000000000001241467462152100260210ustar00rootroot00000000000000* !.gitignore !/ACTIVE/ !/POTENTIALLY_ACTIVE/ !/POTENTIALLY_INACTIVE/ !/SUSPICIOUS/ PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/Analytic/ACTIVE/000077500000000000000000000000001467462152100250075ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/Analytic/ACTIVE/.gitignore000066400000000000000000000000161467462152100267740ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/Analytic/POTENTIALLY_ACTIVE/000077500000000000000000000000001467462152100266735ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/Analytic/POTENTIALLY_ACTIVE/.gitignore000066400000000000000000000000161467462152100306600ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/Analytic/POTENTIALLY_INACTIVE/000077500000000000000000000000001467462152100271225ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/Analytic/POTENTIALLY_INACTIVE/.gitignore000066400000000000000000000000161467462152100311070ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/Analytic/SUSPICIOUS/000077500000000000000000000000001467462152100255425ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/Analytic/SUSPICIOUS/.gitignore000066400000000000000000000000161467462152100275270ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/000077500000000000000000000000001467462152100237225ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/.gitignore000066400000000000000000000001151467462152100257070ustar00rootroot00000000000000* !.gitignore !/ACTIVE/ !/INACTIVE/ !/INVALID/ !/MALICIOUS/ !/SANE/ !/VALID/ PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/ACTIVE/000077500000000000000000000000001467462152100246755ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/ACTIVE/.gitignore000066400000000000000000000000161467462152100266620ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/INACTIVE/000077500000000000000000000000001467462152100251245ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/INACTIVE/.gitignore000066400000000000000000000000161467462152100271110ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/INVALID/000077500000000000000000000000001467462152100250105ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/INVALID/.gitignore000066400000000000000000000000161467462152100267750ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/MALICIOUS/000077500000000000000000000000001467462152100252475ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/MALICIOUS/.gitignore000066400000000000000000000000161467462152100272340ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/SANE/000077500000000000000000000000001467462152100244505ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/SANE/.gitignore000066400000000000000000000000161467462152100264350ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/VALID/000077500000000000000000000000001467462152100245615ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/domains/VALID/.gitignore000066400000000000000000000000161467462152100265460ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/000077500000000000000000000000001467462152100234305ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/.gitignore000066400000000000000000000001151467462152100254150ustar00rootroot00000000000000* !.gitignore !/ACTIVE/ !/INACTIVE/ !/INVALID/ !/MALICIOUS/ !/SANE/ !/VALID/ PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/ACTIVE/000077500000000000000000000000001467462152100244035ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/ACTIVE/.gitignore000066400000000000000000000000161467462152100263700ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/INACTIVE/000077500000000000000000000000001467462152100246325ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/INACTIVE/.gitignore000066400000000000000000000000161467462152100266170ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/INVALID/000077500000000000000000000000001467462152100245165ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/INVALID/.gitignore000066400000000000000000000000161467462152100265030ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/MALICIOUS/000077500000000000000000000000001467462152100247555ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/MALICIOUS/.gitignore000066400000000000000000000000161467462152100267420ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/SANE/000077500000000000000000000000001467462152100241565ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/SANE/.gitignore000066400000000000000000000000161467462152100261430ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/VALID/000077500000000000000000000000001467462152100242675ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/hosts/VALID/.gitignore000066400000000000000000000000161467462152100262540ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/000077500000000000000000000000001467462152100230635ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/.gitignore000066400000000000000000000001151467462152100250500ustar00rootroot00000000000000* !.gitignore !/ACTIVE/ !/INACTIVE/ !/INVALID/ !/MALICIOUS/ !/SANE/ !/VALID/ PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/ACTIVE/000077500000000000000000000000001467462152100240365ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/ACTIVE/.gitignore000066400000000000000000000000161467462152100260230ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/INACTIVE/000077500000000000000000000000001467462152100242655ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/INACTIVE/.gitignore000066400000000000000000000000161467462152100262520ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/INVALID/000077500000000000000000000000001467462152100241515ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/INVALID/.gitignore000066400000000000000000000000161467462152100261360ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/MALICIOUS/000077500000000000000000000000001467462152100244105ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/MALICIOUS/.gitignore000066400000000000000000000000161467462152100263750ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/SANE/000077500000000000000000000000001467462152100236115ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/SANE/.gitignore000066400000000000000000000000161467462152100255760ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/VALID/000077500000000000000000000000001467462152100237225ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/ips/VALID/.gitignore000066400000000000000000000000161467462152100257070ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/logs/000077500000000000000000000000001467462152100232345ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/logs/.gitignore000066400000000000000000000001031467462152100252160ustar00rootroot00000000000000* !.gitignore !/date_format/ !/no_referrer/ !/percentage/ !/whois/ PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/logs/percentage/000077500000000000000000000000001467462152100253515ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/logs/percentage/.gitignore000066400000000000000000000000161467462152100273360ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/splitted/000077500000000000000000000000001467462152100241205ustar00rootroot00000000000000PyFunceble-4.2.29.dev/output/__pyfunceble_origin__/splitted/.gitignore000066400000000000000000000000161467462152100261050ustar00rootroot00000000000000* !.gitignore PyFunceble-4.2.29.dev/requirements.dev.txt000066400000000000000000000000311467462152100204640ustar00rootroot00000000000000black flake8 isort pylintPyFunceble-4.2.29.dev/requirements.docs.txt000066400000000000000000000005341467462152100206460ustar00rootroot00000000000000# Mkdocs mkdocs~=1.5 mkdocstrings[python]~=0.26 mkdocs-material~=9.5 mkdocs-git-revision-date-localized-plugin~=1.2 mkdocs-gen-files~=0.5 mkdocs-literate-nav~=0.6 mkdocs-section-index~=0.3 mkdocs-git-authors-plugin~=0.9 mkdocs-macros-plugin~=1.2 pymdown-extensions~=10.9 zipp>=3.19.1 # not directly required, pinned by Snyk to avoid a vulnerabilityPyFunceble-4.2.29.dev/requirements.test.txt000066400000000000000000000000151467462152100206670ustar00rootroot00000000000000tox coverage PyFunceble-4.2.29.dev/requirements.txt000066400000000000000000000003551467462152100177200ustar00rootroot00000000000000alembic colorama cryptography~=42.0 dnspython[DOH]~=2.6.0 domain2idna~=1.12.0 inflection packaging PyMySQL python-box[all]~=6.0.0 python-dotenv PyYAML requests[socks]<3 setuptools>=65.5.1 shtab SQLAlchemy[postgresql-psycopg2binary]~=2.0 PyFunceble-4.2.29.dev/requirements.win.txt000066400000000000000000000003461467462152100205140ustar00rootroot00000000000000alembic colorama cryptography~=42.0 dnspython[DOH]~=2.6.0 domain2idna~=1.12.0 inflection packaging PyMySQL python-box[all]~=6.0.0 python-dotenv PyYAML requests<3 setuptools>=65.5.1 shtab SQLAlchemy[postgresql-psycopg2binary]~=2.0 PyFunceble-4.2.29.dev/setup.cfg000066400000000000000000000007271467462152100162600ustar00rootroot00000000000000[isort] profile = black [flake8] max-line-length = 88 extend-ignore = E203 [pylint] max-line-length = 88 [pylint.'MESSAGES CONTROL'] disable = abstract-method, consider-using-f-string, consider-using-with, too-few-public-methods, too-many-arguments, too-many-branches, too-many-function-args, too-many-instance-attributes, too-many-public-methods, too-many-positional-arguments [pylint.'SIMILARITIES'] min-similarity-lines = 40PyFunceble-4.2.29.dev/setup.py000066400000000000000000000253261467462152100161530ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Welcome to PyFunceble! PyFunceble is the little sister of Funceble (https://github.com/funilrys/funceble) which was archived on 13th March 2018. In March 2018, because Funceble was starting to become a huge unmanageable script, I - Nissar Chababy aka `@funilrys`_ - decided to make it a Python tool for the purpose of extending my Python knowledge. It was meant for my own use case. Back then, my problem was that I didn't want to download a huge hosts file knowing that most of the entries do not exist anymore. That's how Py-Funceble started. My objective - now - through this tool is to provide a tool and a Python API which helps the world test the availability of domains, IPs and URL through the gathering and interpretation of information from existing tools or protocols like WHOIS records, DNS lookup, or even HTTP status codes. The base of this tool was my idea. But as with many Open Source (related) projects, communities or individuals, we evolve with the people we meet, exchange with or just discuss with privately. PyFunceble was and is still not an exception to that. My main idea was to check the availability of domains in hosts files. But 3 years later, PyFunceble is now capable of a lot including: - The testing of domains, IPs, and URLs. - The checking of the syntax or reputation of a domain, IPs, and URLs. - The decoding of AdBlock filters, RPZ records, or plain files before a test from the CLI. PyFunceble evolved and will probably continue to evolve with the time and the people using it. In June 2020, The PyFunceble-dev PyPI package - which gets everything as soon as possible compared to the PyFunceble (stable) package - reached 1 million total downloads. I never noticed it until I was reached by someone informing me of it. But, I was shocked. I never thought that something I built from A to Z in my free time will ever reach that point. I was thankful to that nice person for informing me of it. But at the same time concerned about PyFunceble and how it will evolve. That's why I started the development of PyFunceble 4.0.0. My idea as I was refactoring it was to provide a better Python API and implementation of my core ideas along with a better incorporation and extension capability. Indeed, in the last few years, I was so much obsessed with the CLI that I really never wrote each component individually. They were all dependent - if not part of - the CLI. With 4.0.0, you can now import one of the components of PyFunceble and start straight away. No real need to play with the configuration unless you want something very specific. That's how I see the future of PyFunceble. As of today, PyFunceble is running actively - if not daily - within several servers, laptops, PCs, and Raspberry Pis. It is even used - thanks to our auto continue dataset and component - with CI engines like GitHub Action, Travis CI, and GitLab CI. PyFunceble is my tool. But it is indirectly also become yours. Therefore, I invite you to let me know how you use PyFunceble or simply open a discussion - or join an existing one - about anything you do with PyFunceble. But also anything that you - would - like - or dislike - in PyFunceble. Happy testing with PyFunceble! Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/#/special-thanks Contributors: https://pyfunceble.github.io/#/contributors Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import platform import re from typing import List import setuptools def is_win_platform(): """ Checks if the current platform is Windows. """ WIN_PLATFORMS = ["windows", "cygwin", "cygwin_nt-10.0"] return platform.system().lower() in WIN_PLATFORMS def get_requirements(*, mode="standard"): """ This function extract all requirements from requirements.txt. """ mode2files = { "standard": ["requirements.txt"], "dev": ["requirements.dev.txt"], "docs": ["requirements.docs.txt"], "test": ["requirements.test.txt"], "psql": ["requirements.txt"], } if is_win_platform(): for known_mode, files in mode2files.items(): new_files = set() for file in files: win_file = file.replace(".txt", ".win.txt") if os.path.isfile(win_file): new_files.add(win_file) else: new_files.add(file) mode2files[known_mode] = list(new_files) mode2files["full"] = [y for x in mode2files.values() for y in x] result = set() for file in mode2files[mode]: with open(file, "r", encoding="utf-8") as file_stream: for line in file_stream: line = line.strip() if not line or line.startswith("#"): continue if "#" in line: line = line[: line.find("#")].strip() if not line: continue result.add(line) if mode == "psql": result.add("psycopg2") return list(result) def get_version(): """ This function will extract the version from PyFunceble/__init__.py """ to_match = re.compile(r'PROJECT_VERSION.*=\s+"(.*)"') try: extracted = to_match.findall( open("PyFunceble/storage.py", encoding="utf-8").read() )[0] except FileNotFoundError: # pragma: no cover extracted = to_match.findall( open("../PyFunceble/storage.py", encoding="utf-8").read() )[0] return extracted[: extracted.rfind(".")] def get_long_description(): # pragma: no cover """ This function return the long description. """ return open("README.md", encoding="utf-8").read() def get_console_scripts(): # pragma: no cover """ Provides the console scripts based on the environment. """ result = [ "PyFunceble=PyFunceble.cli.entry_points.pyfunceble.cli:tool", "pyfunceble=PyFunceble.cli.entry_points.pyfunceble.cli:tool", "clean-pyfunceble=PyFunceble.cli.entry_points.clean:cleaner", ] dev_console_vars: List[str] = [ "PYFUNCEBLE_INSTALL_DEVTOOLS", "PYFUNCEBLE_DEVTOOLS", ] helper_console_vars = [ "PYFUNCEBLE_INSTALL_HELPERS", "PYFUNCEBLE_HELPTOOLS", ] if any(x in os.environ for x in dev_console_vars): result.append( "production-pyfunceble=PyFunceble.cli.entry_points.production:producer" ) if any(x in os.environ for x in helper_console_vars + dev_console_vars): result.extend( [ "public-suffix-pyfunceble=PyFunceble.cli.entry_points.public_suffix:generator", "iana-pyfunceble=PyFunceble.cli.entry_points.iana:generator", ] ) return result if __name__ == "__main__": setuptools.setup( name="PyFunceble-dev", version=get_version(), python_requires=">=3.8, <4", install_requires=get_requirements(mode="standard"), extras_require={ "docs": get_requirements(mode="docs"), "dev": get_requirements(mode="dev"), "test": get_requirements(mode="test"), "psql": get_requirements(mode="psql"), "full": get_requirements(mode="full"), }, description="The tool to check the availability or syntax of domain, IP or URL.", long_description=get_long_description(), long_description_content_type="text/markdown", author="funilrys", author_email="contact@funilrys.com", license="Apache 2.0", url="https://github.com/funilrys/PyFunceble", project_urls={ "Documentation": "https://docs.pyfunceble.com", "Funding": "https://github.com/sponsors/funilrys", "Source": "https://github.com/funilrys/PyFunceble/tree/dev", "Tracker": "https://github.com/funilrys/PyFunceble/issues", }, platforms=["any"], packages=setuptools.find_packages( exclude=("*.tests", "*.tests.*", "tests.*", "tests") ), include_package_data=True, keywords=[ "PyFunceble", "syntax-checker", "reputation-checker", "availability-checker", ], classifiers=[ "Environment :: Console", "Topic :: Internet", "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Programming Language :: Python", "Programming Language :: Python :: 3", "License :: OSI Approved", ], test_suite="setup._test_suite", entry_points={"console_scripts": get_console_scripts()}, ) PyFunceble-4.2.29.dev/tests/000077500000000000000000000000001467462152100155735ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/__init__.py000066400000000000000000000046011467462152100177050ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides our tests. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ PyFunceble-4.2.29.dev/tests/checker/000077500000000000000000000000001467462152100171775ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/checker/__init__.py000066400000000000000000000000001467462152100212760ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/checker/availability/000077500000000000000000000000001467462152100216515ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/checker/availability/__init__.py000066400000000000000000000000001467462152100237500ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/checker/availability/test_base.py000066400000000000000000001240231467462152100241760ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our availability checker base. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: disable=too-many-lines import unittest import unittest.mock from PyFunceble.checker.availability.base import AvailabilityCheckerBase from PyFunceble.checker.availability.status import AvailabilityCheckerStatus from PyFunceble.checker.base import CheckerBase from PyFunceble.config.loader import ConfigLoader from PyFunceble.query.dns.query_tool import DNSQueryTool from PyFunceble.query.whois.query_tool import WhoisQueryTool class TestAvailabilityCheckerBase(unittest.TestCase): """ The tests of our availability checker base. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.checker = AvailabilityCheckerBase() def tearDown(self) -> None: """ Destroys everything needed for the tests. """ del self.checker def test_set_use_extra_rules_return(self) -> None: """ Tests the response of the method which let us activate the special rules filtering. """ given = False actual = self.checker.set_use_extra_rules(given) self.assertIsInstance(actual, CheckerBase) def test_set_use_extra_rules_method(self) -> None: """ Tests the method which let us activate the special rules filtering. """ given = False expected = False self.checker.set_use_extra_rules(given) actual = self.checker.use_extra_rules self.assertEqual(expected, actual) def test_set_use_extra_rules_attribute(self) -> None: """ Tests the method which let us activate the special rules filtering through the attribute. """ given = False expected = False self.checker.use_extra_rules = given actual = self.checker.use_extra_rules self.assertEqual(expected, actual) def test_set_use_extra_rules_init(self) -> None: """ Tests the method which let us activate the special rules filtering through the class constructor. """ checker = AvailabilityCheckerBase(use_extra_rules=False) expected = False actual = checker.use_extra_rules self.assertEqual(expected, actual) def test_set_use_extra_rules_not_bool(self) -> None: """ Tests the method which let us activate the special rules filtering through the attribute. In this use case we check the case that the inputted value is not a :py:class:`bool`. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.checker.set_use_extra_rules(given)) def test_guess_and_set_use_extra_rules(self) -> None: """ Tests the method which let us guess and set the value of the :code`use_extra_rules` attribute. """ config_loader = ConfigLoader() config_loader.custom_config = {"lookup": {"special": False}} config_loader.start() self.checker.guess_and_set_use_extra_rules() expected = False actual = self.checker.use_extra_rules self.assertEqual(expected, actual) del config_loader def test_guess_and_set_use_extra_rules_config_not_loaded(self) -> None: """ Tests the method which let us guess and set the value of the :code:`use_extra_rules` attribute; but for the case that the configuration is not loaded. """ self.checker.guess_and_set_use_extra_rules() expected = self.checker.STD_USE_EXTRA_RULES actual = self.checker.use_extra_rules self.assertEqual(expected, actual) def test_set_use_whois_lookup_return(self) -> None: """ Tests the response of the method which let us activate the usage of the WHOIS lookup method. """ given = False actual = self.checker.set_use_whois_lookup(given) self.assertIsInstance(actual, CheckerBase) def test_set_use_whois_lookup_method(self) -> None: """ Tests the method which let us activate the usage of the WHOIS lookup method. """ given = False expected = False self.checker.set_use_whois_lookup(given) actual = self.checker.use_whois_lookup self.assertEqual(expected, actual) def test_set_use_whois_lookup_attribute(self) -> None: """ Tests the method which let us activate the usage of the WHOIS lookup method through the attribute. """ given = False expected = False self.checker.use_whois_lookup = given actual = self.checker.use_whois_lookup self.assertEqual(expected, actual) def test_set_use_whois_lookup_init(self) -> None: """ Tests the method which let us activate the usage of the WHOIS lookup method through the class constructor. """ checker = AvailabilityCheckerBase(use_whois_lookup=False) expected = False actual = checker.use_whois_lookup self.assertEqual(expected, actual) def test_set_use_whois_lookup_not_bool(self) -> None: """ Tests the method which let us activate the usage of the WHOIS lookup method. In this case, we check the case that the inputted value is not a :py:class:`bool`. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.checker.set_use_whois_lookup(given)) def test_guess_and_set_use_whois_lookup(self) -> None: """ Tests the method which let us guess and set the value of the :code`use_whois_lookup` attribute. """ config_loader = ConfigLoader() config_loader.custom_config = {"lookup": {"whois": False}} config_loader.start() self.checker.guess_and_set_use_whois_lookup() expected = False actual = self.checker.use_whois_lookup self.assertEqual(expected, actual) del config_loader def test_guess_and_set_use_whois_lookup_config_not_loaded(self) -> None: """ Tests the method which let us guess and set the value of the :code:`use_whois_lookup` attribute; but for the case that the configuration is not loaded. """ self.checker.guess_and_set_use_extra_rules() expected = self.checker.STD_USE_WHOIS_LOOKUP actual = self.checker.use_whois_lookup self.assertEqual(expected, actual) def test_set_use_dns_lookup_return(self) -> None: """ Tests the response of the method which let us activate the usage of the DNS lookup method. """ given = False actual = self.checker.set_use_dns_lookup(given) self.assertIsInstance(actual, CheckerBase) def test_set_use_dns_lookup_method(self) -> None: """ Tests the method which let us activate the usage of the DNS lookup method. """ given = False expected = False self.checker.set_use_dns_lookup(given) actual = self.checker.use_dns_lookup self.assertEqual(expected, actual) def test_set_dns_lookup_attribute(self) -> None: """ Tests the method which let us activate the usage of the DNS lookup method through the attribute. """ given = False expected = False self.checker.use_dns_lookup = given actual = self.checker.use_dns_lookup self.assertEqual(expected, actual) def test_set_use_dns_lookup_init(self) -> None: """ Tests the method which let us activate the usage of the DNS lookup method through the class constructor. """ checker = AvailabilityCheckerBase(use_dns_lookup=False) expected = False actual = checker.use_dns_lookup self.assertEqual(expected, actual) def test_set_dns_lookup_not_bool(self) -> None: """ Tests the method which let us activate the usage of the DNS lookup method. Here we check the case that the inputted value is not a :py:class:`bool`. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.checker.set_use_dns_lookup(given)) def test_guess_and_set_use_dns_lookup(self) -> None: """ Tests the method which let us guess and set the value of the :code`use_dns_lookup` attribute. """ config_loader = ConfigLoader() config_loader.custom_config = {"lookup": {"dns": False}} config_loader.start() self.checker.guess_and_set_dns_lookup() expected = False actual = self.checker.use_dns_lookup self.assertEqual(expected, actual) del config_loader def test_guess_and_set_use_dns_lookup_config_not_loaded(self) -> None: """ Tests the method which let us guess and set the value of the :code:`use_dns_lookup` attribute; but for the case that the configuration is not loaded. """ self.checker.guess_and_set_dns_lookup() expected = self.checker.STD_USE_DNS_LOOKUP actual = self.checker.use_dns_lookup self.assertEqual(expected, actual) def test_set_use_netinfo_lookup_return(self) -> None: """ Tests the response of the method which let us activate the usage of the NETINFO lookup method. """ given = False actual = self.checker.set_use_netinfo_lookup(given) self.assertIsInstance(actual, CheckerBase) def test_set_use_netinfo_lookup_method(self) -> None: """ Tests the method which let us activate the usage of the NETINFO lookup method. """ given = False expected = False self.checker.set_use_netinfo_lookup(given) actual = self.checker.use_netinfo_lookup self.assertEqual(expected, actual) def test_set_netinfo_lookup_attribute(self) -> None: """ Tests the method which let us activate the usage of the NETINFO lookup method through the attribute. """ given = False expected = False self.checker.use_netinfo_lookup = given actual = self.checker.use_netinfo_lookup self.assertEqual(expected, actual) def test_set_use_netinfo_lookup_init(self) -> None: """ Tests the method which let us activate the usage of the NETINFO lookup method through the class constructor. """ checker = AvailabilityCheckerBase(use_netinfo_lookup=False) expected = False actual = checker.use_netinfo_lookup self.assertEqual(expected, actual) def test_set_netinfo_lookup_not_bool(self) -> None: """ Tests the method which let us activate the usage of the NETINFO lookup method. Here we check the case that the inputted value is not a bool. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.checker.set_use_netinfo_lookup(given)) def test_guess_and_set_use_netinfo_lookup(self) -> None: """ Tests the method which let us guess and set the value of the :code`use_netinfo_lookup` attribute. """ config_loader = ConfigLoader() config_loader.custom_config = {"lookup": {"netinfo": False}} config_loader.start() self.checker.guess_and_set_use_netinfo_lookup() expected = False actual = self.checker.use_netinfo_lookup self.assertEqual(expected, actual) del config_loader def test_guess_and_set_use_netinfo_lookup_config_not_loaded(self) -> None: """ Tests the method which let us guess and set the value of the :code:`use_netinfo_lookup` attribute; but for the case that the configuration is not loaded. """ self.checker.guess_and_set_use_netinfo_lookup() expected = self.checker.STD_USE_NETINFO_LOOKUP actual = self.checker.use_netinfo_lookup self.assertEqual(expected, actual) def test_set_use_http_code_lookup_return(self) -> None: """ Tests the response of the method which let us activate the usage of the HTTP Code lookup method. """ given = False actual = self.checker.set_use_http_code_lookup(given) self.assertIsInstance(actual, CheckerBase) def test_set_use_http_code_lookup_method(self) -> None: """ Tests the method which let us activate the usage of the HTTP Code lookup method. """ given = False expected = False self.checker.set_use_http_code_lookup(given) actual = self.checker.use_http_code_lookup self.assertEqual(expected, actual) def test_set_use_http_code_lookup_attribute(self) -> None: """ Tests the method which let us activate the usage of the HTTP Code lookup method through the attribute. """ given = False expected = False self.checker.use_http_code_lookup = given actual = self.checker.use_http_code_lookup self.assertEqual(expected, actual) def test_set_use_http_code_lookup_init(self) -> None: """ Tests the method which let us activate the usage of the HTTP Code lookup method through the class constructor. """ checker = AvailabilityCheckerBase(use_http_code_lookup=False) expected = False actual = checker.use_http_code_lookup self.assertEqual(expected, actual) def test_set_use_http_code_lookup_not_bool(self) -> None: """ Tests the method which let us activate the usage of the HTTP Code lookup method. Here we check the case that the inputted value is not a:py:class`bool`. """ given = ["Hello", "World!"] self.assertRaises( TypeError, lambda: self.checker.set_use_http_code_lookup(given) ) def test_guess_and_set_use_http_code_lookup(self) -> None: """ Tests the method which let us guess and set the value of the :code`use_http_code_lookup` attribute. """ config_loader = ConfigLoader() config_loader.custom_config = {"lookup": {"http_status_code": False}} config_loader.start() self.checker.guess_and_set_use_http_code_lookup() expected = False actual = self.checker.use_http_code_lookup self.assertEqual(expected, actual) del config_loader def test_guess_and_set_use_http_code_lookup_config_not_loaded(self) -> None: """ Tests the method which let us guess and set the value of the :code:`use_http_code_lookup` attribute; but for the case that the configuration is not loaded. """ self.checker.guess_and_set_use_http_code_lookup() expected = self.checker.STD_USE_HTTP_CODE_LOOKUP actual = self.checker.use_netinfo_lookup self.assertEqual(expected, actual) def test_set_use_reputation_lookup_return(self) -> None: """ Tests the response of the method which let us activate the usage of the reputation lookup method. """ given = True actual = self.checker.set_use_reputation_lookup(given) self.assertIsInstance(actual, CheckerBase) def test_set_use_reputation_lookup_method(self) -> None: """ Tests the method which let us activate the usage of the reputation lookup method. """ given = True expected = True self.checker.set_use_reputation_lookup(given) actual = self.checker.use_reputation_lookup self.assertEqual(expected, actual) def test_set_use_reputation_lookup_attribute(self) -> None: """ Tests the method which let us activate the usage of the reputation lookup method through the attribute. """ given = True expected = True self.checker.use_reputation_lookup = given actual = self.checker.use_reputation_lookup self.assertEqual(expected, actual) def test_set_use_reputation_lookup_init(self) -> None: """ Tests the method which let us activate the usage of the reputation lookup method through the class constructor. """ checker = AvailabilityCheckerBase(use_reputation_lookup=True) expected = True actual = checker.use_reputation_lookup self.assertEqual(expected, actual) def test_set_use_reputation_lookup_not_bool(self) -> None: """ Tests the method which let us activate the usage of the reputation lookup method through. Here we check the case that the inputted value is not a:py:class`bool`. """ given = ["Hello", "World!"] self.assertRaises( TypeError, lambda: self.checker.set_use_reputation_lookup(given) ) def test_guess_and_set_use_reputation_lookup(self) -> None: """ Tests the method which let us guess and set the value of the :code`use_reputation_lookup` attribute. """ config_loader = ConfigLoader() config_loader.custom_config = {"lookup": {"reputation": True}} config_loader.start() self.checker.guess_and_set_use_reputation_lookup() expected = True actual = self.checker.use_reputation_lookup self.assertEqual(expected, actual) del config_loader def test_guess_and_set_use_reputation_lookup_config_not_loaded(self) -> None: """ Tests the method which let us guess and set the value of the :code:`use_reputation_lookup` attribute; but for the case that the configuration is not loaded. """ self.checker.guess_and_set_use_reputation_lookup() expected = self.checker.STD_USE_REPUTATION_LOOKUP actual = self.checker.use_reputation_lookup self.assertEqual(expected, actual) def test_set_use_whois_db_return(self) -> None: """ Tests the response of the method which let us activate the usage of the WHOIS DB. """ given = False actual = self.checker.set_use_whois_db(given) self.assertIsInstance(actual, CheckerBase) def test_set_use_whois_db_method(self) -> None: """ Tests the method which let us activate the usage of the WHOIS DB. """ given = False expected = False self.checker.set_use_whois_db(given) actual = self.checker.use_whois_db self.assertEqual(expected, actual) def test_set_use_whois_db_attribute(self) -> None: """ Tests the method which let us activate the usage of the WHOIS DB through the attribute. """ given = False expected = False self.checker.use_whois_db = given actual = self.checker.use_whois_db self.assertEqual(expected, actual) def test_set_use_whois_db_init(self) -> None: """ Tests the method which let us activate the usage of the WHOIS DB through the class constructor. """ checker = AvailabilityCheckerBase(use_whois_db=False) expected = False actual = checker.use_whois_db self.assertEqual(expected, actual) def test_set_use_whois_db_not_bool(self) -> None: """ Tests the method which let us activate the usage of the WHOIS DB. Here we check the case that the inputted value is not a :py:class:`bool`. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.checker.set_use_whois_db(given)) def test_guess_and_set_use_whois_db(self) -> None: """ Tests the method which let us guess and set the value of the :code`use_whois_db` attribute. """ config_loader = ConfigLoader() config_loader.custom_config = {"cli_testing": {"whois_db": False}} config_loader.start() self.checker.guess_and_set_use_whois_db() expected = False actual = self.checker.use_whois_db self.assertEqual(expected, actual) del config_loader def test_guess_and_set_use_whois_db_config_not_loaded(self) -> None: """ Tests the method which let us guess and set the value of the :code:`use_whois_db` attribute; but for the case that the configuration is not loaded. """ self.checker.guess_and_set_use_whois_db() expected = self.checker.STD_USE_WHOIS_DB actual = self.checker.use_whois_db self.assertEqual(expected, actual) def test_subject_propagator(self) -> None: """ Tests that the subjects and its IDNA counterpart are correctly propagated. """ given = "รคxample.org" expected_subject = "รคxample.org" expected_idna_subject = "xn--xample-9ta.org" self.checker.subject = given actual_subject = self.checker.status.subject actual_idna_propagated = [ self.checker.dns_query_tool.subject, self.checker.whois_query_tool.subject, self.checker.addressinfo_query_tool.subject, self.checker.hostbyaddr_query_tool.subject, self.checker.http_status_code_query_tool.subject, self.checker.domain_syntax_checker.subject, self.checker.ip_syntax_checker.subject, self.checker.url_syntax_checker.subject, self.checker.status.idna_subject, ] self.assertEqual(expected_subject, actual_subject) for actual in actual_idna_propagated: self.assertEqual(expected_idna_subject, actual) # Now, just make sure that when overwrite, the status get changed # propagated too. given = "รคxample.net" expected_subject = "รคxample.net" expected_idna_subject = "xn--xample-9ta.net" self.checker.subject = given actual = self.checker.status.subject actual_idna_propagated = [ self.checker.dns_query_tool.subject, self.checker.whois_query_tool.subject, self.checker.addressinfo_query_tool.subject, self.checker.hostbyaddr_query_tool.subject, self.checker.http_status_code_query_tool.subject, self.checker.domain_syntax_checker.subject, self.checker.ip_syntax_checker.subject, self.checker.url_syntax_checker.subject, self.checker.status.idna_subject, ] self.assertEqual(expected_subject, actual) for actual in actual_idna_propagated: self.assertEqual(expected_idna_subject, actual) def test_should_we_continue_test_positive(self) -> None: """ Tests the method which let us check if we should continue to another test method. """ given = "INVALID" self.checker.status.status = "INACTIVE" expected = False actual = self.checker.should_we_continue_test(given) self.assertEqual(expected, actual) def test_should_we_continue_test_negative(self) -> None: """ Tests the method which let us check if we should continue to another test method. """ given = "VALID" self.checker.status.status = "INACTIVE" expected = False actual = self.checker.should_we_continue_test(given) self.assertEqual(expected, actual) @unittest.mock.patch.object(DNSQueryTool, "query") def test_query_dns_record(self, dns_query_patch: unittest.mock.MagicMock) -> None: """ Tests the method that let us query the (right) DNS record of the given subject. """ dns_query_patch.return_value = ["192.168.1.1"] given = "example.org" expected = {"NS": ["192.168.1.1"]} self.checker.subject = given actual = self.checker.query_dns_record() self.assertEqual(expected, actual) @unittest.mock.patch.object(DNSQueryTool, "query") def test_query_dns_record_no_response( self, dns_query_patch: unittest.mock.MagicMock ) -> None: """ Tests the method that let us query the (right) DNS record of the given subject. Here we test the case that there is systematically no (valid) response. """ dns_query_patch.return_value = [] given = "example.net" expected = dict() # pylint: disable=use-dict-literal self.checker.subject = given actual = self.checker.query_dns_record() self.assertEqual(expected, actual) @unittest.mock.patch.object(DNSQueryTool, "query") def test_query_dns_record_subdomain( self, dns_query_patch: unittest.mock.MagicMock ) -> None: """ Tests the method that let us query the (right) DNS record of the given subject. """ dns_query_patch.return_value = ["192.168.1.2"] given = "test.example.org" expected = {"NS": ["192.168.1.2"]} self.checker.subject = given actual = self.checker.query_dns_record() self.assertEqual(expected, actual) @unittest.mock.patch.object(DNSQueryTool, "query") def test_query_dns_record_ptr( self, dns_query_patch: unittest.mock.MagicMock ) -> None: """ Tests the method that let us query the (right) DNS record of the given subject. """ dns_query_patch.return_value = ["example.org"] given = "192.168.1.1" expected = {"PTR": ["example.org"]} self.checker.subject = given actual = self.checker.query_dns_record() self.assertEqual(expected, actual) def test_query_dns_record_no_subject(self) -> None: """ Tests the method that let us query the (right) DNS record of the given subject. In this case we test the case that the subject is not set. """ # pylint: disable=unnecessary-lambda self.assertRaises(TypeError, lambda: self.checker.query_dns_record()) @unittest.mock.patch.object(DNSQueryTool, "query") def test_query_dns_record_not_valid_subject( self, dns_query_patch: unittest.mock.MagicMock ) -> None: """ Tests the method that let us query the (right) DNS record of the given subject. Here we test the case that the given subject is not correct. """ dns_query_patch.return_value = [] given = "a1" expected = dict() # pylint: disable=use-dict-literal self.checker.subject = given actual = self.checker.query_dns_record() self.assertEqual(expected, actual) @unittest.mock.patch.object( WhoisQueryTool, "expiration_date", new_callable=unittest.mock.PropertyMock ) def test_try_to_query_status_from_whois(self, expiration_date_mock) -> None: """ Tests the method which tries to define the status from the WHOIS record. """ # In this test, we don't care about the database. self.checker.use_whois_db = False self.checker.subject = "example.org" # Let's test the case that no expiration date is found. expiration_date_mock.return_value = None # self.checker.whois_query_tool.get_expiration_date = lambda: None self.checker.whois_query_tool.lookup_record.record = None self.checker.try_to_query_status_from_whois() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_whois_record = None actual_whois_record = self.checker.status.whois_record self.assertEqual(expected_whois_record, actual_whois_record) # Let's test the case that an expiration date is actually given. expiration_date_mock.return_value = "10-nov-1971" self.checker.whois_query_tool.lookup_record.record = "Hello, World!" self.checker.try_to_query_status_from_whois() expected_status = "ACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_source = "WHOIS" actual_source = self.checker.status.status_source self.assertEqual(expected_source, actual_source) expected_whois_record = "Hello, World!" actual_whois_record = self.checker.status.whois_record self.assertEqual(expected_whois_record, actual_whois_record) def test_try_to_query_status_from_dns(self) -> None: """ Tests the method that tries to define the status from the DNS lookup. """ # Let's test the case that no answer is given back. # pylint: disable=unnecessary-lambda self.checker.subject = "example.org" self.checker.query_dns_record = ( lambda: dict() # pylint: disable=use-dict-literal ) self.checker.try_to_query_status_from_dns() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) # Let's test the case that an answer is given back. self.checker.query_dns_record = lambda: {"NS": ["ns1.example.org"]} self.checker.try_to_query_status_from_dns() expected_status = "ACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_source = "DNSLOOKUP" actual_source = self.checker.status.status_source self.assertEqual(expected_source, actual_source) def test_try_to_query_status_from_netinfo(self) -> None: """ Tests the method that tries to define the status from the NETINFO lookup. """ # Let's test the case that nothing is given back. self.checker.subject = "example.org" self.checker.addressinfo_query_tool.get_info = lambda: None self.checker.try_to_query_status_from_netinfo() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) # Let's test the case that an answer is given back. self.checker.addressinfo_query_tool.get_info = lambda: ["192.168.1.1"] self.checker.try_to_query_status_from_netinfo() expected_status = "ACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_source = "NETINFO" actual_source = self.checker.status.status_source self.assertEqual(expected_source, actual_source) # Now the same test but with an IP. self.checker.subject = "192.168.1.1" self.checker.hostbyaddr_query_tool.get_info = lambda: None self.checker.try_to_query_status_from_netinfo() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) # Let's test the case that an answer is given back. self.checker.hostbyaddr_query_tool.get_info = lambda: ["example.org"] self.checker.try_to_query_status_from_netinfo() expected_status = "ACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_source = "NETINFO" actual_source = self.checker.status.status_source self.assertEqual(expected_source, actual_source) # Now a test with a digit string. # This test exists because we shouldn't produce false positive. self.checker.subject = "192" self.checker.try_to_query_status_from_netinfo() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) # Now the same test as before but for everything that may not exists # publicly but in the local network. # # Let's test the case that nothing is given back. self.checker.subject = "example" self.checker.addressinfo_query_tool.get_info = lambda: None self.checker.try_to_query_status_from_netinfo() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) # Let's test the case that an answer is given back. self.checker.addressinfo_query_tool.get_info = lambda: ["192.168.1.19"] self.checker.try_to_query_status_from_netinfo() expected_status = "ACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_source = "NETINFO" actual_source = self.checker.status.status_source self.assertEqual(expected_source, actual_source) def test_try_to_query_status_from_http_status_code(self) -> None: """ Tests of the method that tries to define a status from the HTTP status code. """ # Let's test the strange case that we meet mailto:xxx@yyy.de self.checker.subject = "mailto:hello@world.de" self.checker.http_status_code_query_tool.get_status_code = ( lambda: self.checker.http_status_code_query_tool.STD_UNKNOWN_STATUS_CODE ) self.checker.try_to_query_status_from_http_status_code() expected_subject = "http://mailto:hello@world.de:80" actual_subject = self.checker.http_status_code_query_tool.subject self.assertEqual(expected_subject, actual_subject) expected_status = None actual_status = None self.assertEqual(expected_status, actual_status) expected_status_code = None actual_status_code = self.checker.status.http_status_code self.assertEqual(expected_status_code, actual_status_code) # Now, let's test a normal domain. self.checker.subject = "example.org" self.checker.http_status_code_query_tool.get_status_code = lambda: 200 self.checker.try_to_query_status_from_http_status_code() expected_subject = "http://example.org:80" actual_subject = self.checker.http_status_code_query_tool.subject self.assertEqual(expected_subject, actual_subject) expected_status = "ACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_source = "HTTP CODE" actual_source = self.checker.status.status_source self.assertEqual(expected_source, actual_source) def test_try_to_query_status_from_syntax_lookup(self) -> None: """ Tests the method that tries to define the status from the syntax lookup. """ # Let's check the case that the subject is a valid domain. self.checker.subject = "example.com" self.checker.try_to_query_status_from_syntax_lookup() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) # Let's check the case that the subject is an invalid one. self.checker.subject = "102117110105108114121115" self.checker.try_to_query_status_from_syntax_lookup() expected_status = "INVALID" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_source = "SYNTAX" actual_source = self.checker.status.status_source self.assertEqual(expected_source, actual_source) @staticmethod def fake_pull_response(subject: str) -> dict: """ Provides a fake pull response to work with. :param subject: The subject to work with. """ return { "subject": subject, "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "status": { "syntax": { "latest": { "status": "INVALID", "status_source": "SYNTAX", "tested_at": "2021-09-28T19:32:07.167Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", }, "frequent": "VALID", "recommended": "VALID", }, "availability": { "latest": { "status": "INACTIVE", "status_source": "DNSLOOKUP", "tested_at": "2021-09-28T19:32:07.167Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", }, "frequent": "ACTIVE", "recommended": "ACTIVE", }, "reputation": { "latest": { "status": "MALICIOUS", "status_source": "REPUTATION", "tested_at": "2021-09-28T19:32:07.167Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", }, "frequent": "SANE", "recommended": "MALICIOUS", }, "whois": { "expiration_date": "2021-09-28T19:32:07.167Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "subject_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", }, }, } @staticmethod def fake_response_no_data(_: str) -> None: """ Provides an empty response. """ return None def test_try_to_query_status_from_platform(self) -> None: """ Tests the method that tries to define the status from the platform lookup. """ # Let's check the case that the subject is known. self.checker.subject = "example.com" self.checker.platform_query_tool.preferred_status_origin = "frequent" self.checker.platform_query_tool.pull = self.fake_pull_response self.checker.try_to_query_status_from_platform() expected_status = "ACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_status_source = "PLATFORM" actual_status_source = self.checker.status.status_source self.assertEqual(expected_status_source, actual_status_source) self.checker.platform_query_tool.preferred_status_origin = "latest" self.checker.try_to_query_status_from_platform() expected_status = "INACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_status_source = "PLATFORM" actual_status_source = self.checker.status.status_source self.assertEqual(expected_status_source, actual_status_source) self.checker.platform_query_tool.preferred_status_origin = "recommended" self.checker.try_to_query_status_from_platform() expected_status = "ACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_status_source = "PLATFORM" actual_status_source = self.checker.status.status_source self.assertEqual(expected_status_source, actual_status_source) # Let's check the case that the subject is unknown. self.checker.subject = "102117110105108114121115" self.checker.platform_query_tool.pull = self.fake_response_no_data self.checker.try_to_query_status_from_platform() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_status_source = None actual_status_source = self.checker.status.status_source self.assertEqual(expected_status_source, actual_status_source) def test_get_status(self) -> None: """ Tests the method that let us get the whole status object. """ self.test_try_to_query_status_from_syntax_lookup() actual = self.checker.get_status() self.assertIsInstance(actual, AvailabilityCheckerStatus) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/availability/test_domain.py000066400000000000000000000111311467462152100245260ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our domain availability checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest import unittest.mock from datetime import datetime, timezone from PyFunceble.checker.availability.domain import DomainAvailabilityChecker from PyFunceble.checker.reputation.domain import DomainReputationChecker from PyFunceble.checker.reputation.status import ReputationCheckerStatus class TestDomainAvailabilityChecker(unittest.TestCase): """ Tests of our domain availability checker. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.checker = DomainAvailabilityChecker() def tearDown(self) -> None: """ Destroys everything needed for the tests. """ del self.checker @unittest.mock.patch.object(DomainReputationChecker, "get_status") def test_try_to_query_status_from_reputation( self, reputation_checker_path: unittest.mock.MagicMock ) -> None: """ Tests of the method that tries to define the status from the reputation checker. """ self.checker.subject = "example.com" reputation_checker_path.return_value = ReputationCheckerStatus( subject="example.com", idna_subject="example.com", status="SANE", status_source="REPUTATION", tested_at=datetime.now(timezone.utc), ) self.checker.try_to_query_status_from_reputation() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) reputation_checker_path.return_value = ReputationCheckerStatus( subject="example.com", idna_subject="example.com", status="MALICIOUS", status_source="REPUTATION", tested_at=datetime.now(timezone.utc), ) self.checker.try_to_query_status_from_reputation() expected_status = "ACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_source = "REPUTATION" actual_source = self.checker.status.status_source self.assertEqual(expected_source, actual_source) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/availability/test_ip.py000066400000000000000000000110651467462152100236750ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our IP availability checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest import unittest.mock from datetime import datetime, timezone from PyFunceble.checker.availability.ip import IPAvailabilityChecker from PyFunceble.checker.reputation.ip import IPReputationChecker from PyFunceble.checker.reputation.status import ReputationCheckerStatus class TestIPAvailabilityChecker(unittest.TestCase): """ Tests of our IP availability checker. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.checker = IPAvailabilityChecker() def tearDown(self) -> None: """ Destroys everything needed for the tests. """ del self.checker @unittest.mock.patch.object(IPReputationChecker, "get_status") def test_try_to_query_status_from_reputation( self, reputation_checker_path: unittest.mock.MagicMock ) -> None: """ Tests of the method that tries to define the status from the reputation checker. """ self.checker.subject = "192.168.1.1" reputation_checker_path.return_value = ReputationCheckerStatus( subject="192.168.1.1", idna_subject="192.168.1.1", status="SANE", status_source="REPUTATION", tested_at=datetime.now(timezone.utc), ) self.checker.try_to_query_status_from_reputation() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) reputation_checker_path.return_value = ReputationCheckerStatus( subject="192.168.1.1", idna_subject="192.168.1.1", status="MALICIOUS", status_source="REPUTATION", tested_at=datetime.now(timezone.utc), ) self.checker.try_to_query_status_from_reputation() expected_status = "ACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_source = "REPUTATION" actual_source = self.checker.status.status_source self.assertEqual(expected_source, actual_source) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/availability/test_status.py000066400000000000000000000152231467462152100246100ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our availability checker status handler. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest import unittest.mock from PyFunceble.checker.availability.status import AvailabilityCheckerStatus class TestAvailabilityCheckerStatus(unittest.TestCase): """ Tests of our availability status handler. """ def setUp(self) -> None: """ Setups everything we need. """ self.status = AvailabilityCheckerStatus(subject="example.org") def tearDown(self) -> None: """ Destroys everything we need. """ del self.status def test_is_special(self) -> None: """ Tests the method which let us check if the current status is a special one. """ self.status.status_after_extra_rules = "ACTIVE" self.status.status_before_extra_rules = "INACTIVE" self.status.status = "ACTIVE" self.status.status_source = "SPECIAL" expected = True actual = self.status.is_special() self.assertEqual(expected, actual) def test_is_not_special(self) -> None: """ Tests the method which let us check if the current status is a not a special one. """ self.status.status = "ACTIVE" self.status.status_source = "DNSLOOKUP" expected = False actual = self.status.is_special() self.assertEqual(expected, actual) def test_is_available(self) -> None: """ Tests the method which let us check if the current status represent an available status. """ self.status.status = "ACTIVE" self.status.status_source = "HTTP CODE" expected = True actual = self.status.is_available() self.assertEqual(expected, actual) def test_is_not_available(self) -> None: """ Tests the method which let us check if the current represent a non- available status. """ self.status.status = "INACTIVE" self.status.status_source = "STDLOOKUP" expected = False actual = self.status.is_available() self.assertEqual(expected, actual) def test_is_active(self) -> None: """ Tests the method which let us check if the current status represent an active status. """ self.status.status = "ACTIVE" self.status.status_source = "DNSLOOKUP" expected = True actual = self.status.is_active() self.assertEqual(expected, actual) def test_is_not_active(self) -> None: """ Tests the method which let us check if the current represent a non- active status. """ self.status.status = "INACTIVE" self.status.status_source = "DNSLOOKUP" expected = False actual = self.status.is_active() self.assertEqual(expected, actual) def test_is_inactive(self) -> None: """ Tests the method which let us check if the current status represent an inactive status. """ self.status.status = "INACTIVE" self.status.status_source = "DNSLOOKUP" expected = True actual = self.status.is_inactive() self.assertEqual(expected, actual) def test_is_not_inactive(self) -> None: """ Tests the method which let us check if the current represent a non- inactive status. """ self.status.status = "ACTIVE" self.status.status_source = "NETINFO" expected = False actual = self.status.is_inactive() self.assertEqual(expected, actual) def test_is_invalid(self) -> None: """ Tests the method which let us check if the current status represent an invalid status. """ self.status.status = "INVALID" self.status.status_source = "SYNTAX" expected = True actual = self.status.is_invalid() self.assertEqual(expected, actual) def test_is_not_invalid(self) -> None: """ Tests the method which let us check if the current represent a non- invalid status. """ self.status.status = "ACTIVE" self.status.status_source = "DNSLOOKUP" expected = False actual = self.status.is_invalid() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/availability/test_url.py000066400000000000000000000205761467462152100240760ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our URL availability checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest import unittest.mock from datetime import datetime, timezone from PyFunceble.checker.availability.url import URLAvailabilityChecker from PyFunceble.checker.reputation.status import ReputationCheckerStatus from PyFunceble.checker.reputation.url import URLReputationChecker class TestURLAvailabilityChecker(unittest.TestCase): """ Tests our URL availability checker. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.checker = URLAvailabilityChecker() def tearDown(self) -> None: """ Destroys everything needed for the tests. """ del self.checker def test_subject_propagator(self) -> None: """ Tests that the subjects and its IDNA counterpart are correctly propagated. .. versionchanged:: 4.1.0b7.dev URL base propagation to allow DNS lookup. """ given = "http://รคxample.org" expected_subject = "http://รคxample.org" expected_idna_subject = "http://xn--xample-9ta.org" expected_base_url = "xn--xample-9ta.org" self.checker.subject = given actual_subject = self.checker.status.subject actual_idna_propagated = [ self.checker.domain_syntax_checker.subject, self.checker.ip_syntax_checker.subject, self.checker.url_syntax_checker.subject, ] self.assertEqual(expected_subject, actual_subject) self.assertEqual(expected_base_url, self.checker.dns_query_tool.subject) for actual in actual_idna_propagated: self.assertEqual(expected_idna_subject, actual) # Now, just make sure the the status get changed and propagated too. given = "http://รคxample.net" expected_subject = "http://รคxample.net" expected_idna_subject = "http://xn--xample-9ta.net" self.checker.subject = given actual = self.checker.status.subject actual_idna_propagated = [ self.checker.domain_syntax_checker.subject, self.checker.ip_syntax_checker.subject, self.checker.url_syntax_checker.subject, ] self.assertEqual(expected_subject, actual) for actual in actual_idna_propagated: self.assertEqual(expected_idna_subject, actual) def test_try_to_query_status_from_http_status_code(self) -> None: """ Tests the method that tries to define the status from the status code. """ self.checker.subject = "http://example.org" self.checker.http_status_code_query_tool.get_status_code = ( lambda: self.checker.http_status_code_query_tool.STD_UNKNOWN_STATUS_CODE ) self.checker.try_to_query_status_from_http_status_code() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) self.checker.http_status_code_query_tool.get_status_code = lambda: 200 self.checker.try_to_query_status_from_http_status_code() expected_status = "ACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_source = "HTTP CODE" actual_source = self.checker.status.status_source self.assertEqual(expected_source, actual_source) @unittest.mock.patch.object(URLReputationChecker, "get_status") def test_try_to_query_status_from_reputation( self, reputation_checker_path: unittest.mock.MagicMock ) -> None: """ Tests of the method that tries to define the status from the reputation checker. """ self.checker.subject = "http://example.com" reputation_checker_path.return_value = ReputationCheckerStatus( subject="http://example.com", idna_subject="http://example.com", status="SANE", status_source="REPUTATION", tested_at=datetime.now(timezone.utc), ) self.checker.try_to_query_status_from_reputation() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) reputation_checker_path.return_value = ReputationCheckerStatus( subject="http://example.com", idna_subject="http://example.com", status="MALICIOUS", status_source="REPUTATION", tested_at=datetime.now(timezone.utc), ) self.checker.try_to_query_status_from_reputation() expected_status = "ACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_source = "REPUTATION" actual_source = self.checker.status.status_source self.assertEqual(expected_source, actual_source) def test_try_to_query_status_from_dns(self) -> None: """ Tests the method that tries to define the status from the DNS lookup. .. versionadded:: 4.1.0b7.dev """ # Let's test the case that no answer is given back. # pylint: disable=unnecessary-lambda self.checker.subject = "http://example.org" self.checker.query_dns_record = ( lambda: dict() # pylint: disable=use-dict-literal ) self.checker.try_to_query_status_from_dns() expected_status = "INACTIVE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) # Let's test the case that an answer is given back. self.checker.query_dns_record = lambda: {"NS": ["ns1.example.org"]} self.checker.try_to_query_status_from_dns() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_source = None actual_source = self.checker.status.status_source self.assertEqual(expected_source, actual_source) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/reputation/000077500000000000000000000000001467462152100213715ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/checker/reputation/__init__.py000066400000000000000000000000001467462152100234700ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/checker/reputation/reputation_test_base.py000066400000000000000000000105121467462152100261650ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• A module that provides some abstract class for the reputation tests. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 os import tempfile import unittest from typing import List, Optional from PyFunceble.checker.reputation.base import ReputationCheckerBase class ReputationCheckerTestBase(unittest.TestCase): """ Tests of the base of all our reputation checker. """ def setUp(self) -> None: """ Setups everything we need. """ self.checker = ReputationCheckerBase() self.tempfile = tempfile.NamedTemporaryFile("wb", delete=False) self.our_dataset = """ 127.176.134.253#4#3#Malicious Host 127.34.113.192#4#2#Malicious Host 127.34.107.238#4#2#Malicious Host 127.166.193.125#4#2#Malicious Host 127.179.153.18#4#2#Malicious Host 127.89.243.30#4#2#Malicious Host 127.147.142.53#4#2#Malicious Host 127.35.150.233#4#3#Malicious Host 127.97.172.196#4#2#Malicious Host 127.24.78.18#4#2#Malicious Host """ self.tempfile.write(self.our_dataset.encode()) self.tempfile.seek(0) self.checker.ipv4_reputation_query_tool.source_file = self.tempfile.name def tearDown(self) -> None: """ Destroyes everything we don't need. """ self.tempfile.close() os.unlink(self.tempfile.name) del self.checker @staticmethod def fake_query_a_record(*args, **kwargs) -> Optional[List[str]]: """ A fake method which provides a fake IP for the testing. """ _ = args _ = kwargs return ["127.176.134.253"] @staticmethod def fake_query_a_record_none(*args, **kwargs) -> Optional[List[str]]: """ A fake method which provides a fake IP for the testing. """ _ = args _ = kwargs @staticmethod def fake_query_a_record_not_known(*args, **kwargs) -> Optional[List[str]]: """ A fake method which provides a fake IP for the testing. """ _ = args _ = kwargs return ["93.184.216.34"] PyFunceble-4.2.29.dev/tests/checker/reputation/test_base.py000066400000000000000000000500731467462152100237210ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our reputation checker base. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.reputation.base import ReputationCheckerStatus try: import pyf_test_dataset except (ModuleNotFoundError, ImportError): # pragma: no cover try: from .. import pyf_test_dataset except (ModuleNotFoundError, ImportError): from ... import pyf_test_dataset try: import reputation_test_base except ModuleNotFoundError: # pragma: no cover from . import reputation_test_base class TestReputationCheckerBase(reputation_test_base.ReputationCheckerTestBase): """ Tests of the base of all our reputation checker. """ def test_subject_propagator(self) -> None: """ Tests that the subject subjects and it's IDNA counterpart are correctly propagated. """ given = "รคxample.org" expected_subject = "รคxample.org" expected_idna_subject = "xn--xample-9ta.org" self.checker.subject = given actual_subject = self.checker.status.subject actual_idna_propagated = [ self.checker.status.idna_subject, self.checker.dns_query_tool.subject, self.checker.domain_syntax_checker.subject, self.checker.ip_syntax_checker.subject, self.checker.url_syntax_checker.subject, ] self.assertEqual(expected_subject, actual_subject) for actual in actual_idna_propagated: self.assertEqual(expected_idna_subject, actual) # Now, just make sure that when overwrite, the status get changed # propagated too. given = "รคxample.net" expected_subject = "รคxample.net" expected_idna_subject = "xn--xample-9ta.net" self.checker.subject = given actual_subject = self.checker.status.subject actual_idna_propagated = [ self.checker.status.idna_subject, self.checker.dns_query_tool.subject, self.checker.domain_syntax_checker.subject, self.checker.ip_syntax_checker.subject, self.checker.url_syntax_checker.subject, ] self.assertEqual(expected_subject, actual_subject) for actual in actual_idna_propagated: self.assertEqual(expected_idna_subject, actual) def test_should_we_continue_test_negative(self) -> None: """ Tests the method which let us know if we need to continue to the next test method. """ given = "VALID" self.checker.status.status = "INACTIVE" expected = False actual = self.checker.should_we_continue_test(given) self.assertEqual(expected, actual) def test_should_we_continue_test_positive(self) -> None: """ Tests the method which let us know if we need to continue to the next test method. """ given = "INVALID" self.checker.status.status = "INACTIVE" expected = True actual = self.checker.should_we_continue_test(given) self.assertEqual(expected, actual) def test_query_syntax_checker(self) -> None: """ Tests the method which check and share the syntax check. """ # We are just checking that the key are present and that they have a # plausible value. We actually don't really care about the value as # we completely test the syntax checker. for subject in pyf_test_dataset.VALID_SECOND_LVL_DOMAINS: self.checker.subject = subject self.checker.query_common_checker() # pylint: disable=line-too-long expected_true = { "status.second_level_domain_syntax": self.checker.status.second_level_domain_syntax, "status.domain_syntax": self.checker.status.domain_syntax, } expected_false = { "status.subdomain_syntax": self.checker.status.subdomain_syntax, "status.ipv4_syntax": self.checker.status.ipv4_syntax, "status.ipv6_syntax": self.checker.status.ipv6_syntax, "status.ipv4_range_syntax": self.checker.status.ipv4_range_syntax, "status.ipv6_range_syntax": self.checker.status.ipv6_range_syntax, "status.ip_syntax": self.checker.status.ip_syntax, "status.url_syntax": self.checker.status.url_syntax, } for key, value in expected_true.items(): self.assertTrue(value, key) for key, value in expected_false.items(): self.assertFalse(value, key) def test_try_to_query_from_dns_lookup(self) -> None: """ Tests the method which let us perform the test through the DNS method. In this case, we check what happens a malicious IP is given. """ self.checker.query_a_record = self.fake_query_a_record self.checker.subject = "127.24.78.18" self.checker.try_to_query_status_from_dns_lookup() expected_status = "MALICIOUS" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_try_to_query_from_dns_lookup_domain(self) -> None: """ Tests the method which let us perform the test through the DNS method. In this case, we check what happens a malicious domain is found. """ self.checker.query_a_record = self.fake_query_a_record self.checker.subject = "example.org" self.checker.try_to_query_status_from_dns_lookup() expected_status = "MALICIOUS" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_try_to_query_from_dns_lookup_no_dns_record(self) -> None: """ Tests the method which let us perform the test through the DNS method. In this case, we check what happens when no DNS record is found. """ self.checker.query_a_record = self.fake_query_a_record_none self.checker.subject = "example.org" self.checker.try_to_query_status_from_dns_lookup() # None is because nothing was actually changed by the current method. expected_status = None expected_source = None actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_try_to_query_from_syntax_lookup(self) -> None: """ Tests the method which let us perform the test through the syntax check method. """ self.checker.subject = "example.org" self.checker.status.domain_syntax = True self.checker.status.ip_syntax = False self.checker.status.url_syntax = False self.checker.try_to_query_status_from_syntax_lookup() # None is because nothing was actually changed by the current method. expected_status = None expected_source = None actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_try_to_query_from_syntax_lookup_only_ip_valid(self) -> None: """ Tests the method which let us perform the test through the syntax check method. """ self.checker.subject = "example.org" self.checker.status.domain_syntax = False self.checker.status.ip_syntax = True self.checker.status.url_syntax = False self.checker.try_to_query_status_from_syntax_lookup() # None is because nothing was actually changed by the current method. expected_status = None expected_source = None actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_try_to_query_from_syntax_lookup_only_url_valid(self) -> None: """ Tests the method which let us perform the test through the syntax check method. """ self.checker.subject = "example.org" self.checker.status.domain_syntax = False self.checker.status.ip_syntax = False self.checker.status.url_syntax = True self.checker.try_to_query_status_from_syntax_lookup() # None is because nothing was actually changed by the current method. expected_status = None expected_source = None actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_try_to_query_from_syntax_lookup_invalid(self) -> None: """ Tests the method which let us perform the test through the syntax check method. """ self.checker.subject = "example.org" self.checker.status.domain_syntax = False self.checker.status.ip_syntax = False self.checker.status.url_syntax = False self.checker.try_to_query_status_from_syntax_lookup() # None is because nothing was actually changed by the current method. expected_status = "INVALID" expected_source = "SYNTAX" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_from_syntax(self) -> None: """ Tests the method which let us query the status of the given subject. """ def fake_try_to_query_status_from_syntax_lookup(): self.checker.status.status = "INVALID" self.checker.status.status_source = "SYNTAX" def fake_try_to_query_status_from_dns_lookup(): ... self.checker.do_syntax_check_first = True self.checker.subject = pyf_test_dataset.NOT_VALID_DOMAINS[0] self.checker.query_a_record = self.fake_query_a_record self.checker.try_to_query_status_from_syntax_lookup = ( fake_try_to_query_status_from_syntax_lookup ) self.checker.try_to_query_status_from_dns_lookup = ( fake_try_to_query_status_from_dns_lookup ) self.checker.query_status() expected_status = "INVALID" expected_source = "SYNTAX" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_from_dns_lookup(self) -> None: """ Tests the method which let us query the status of the given subject. """ def fake_try_to_query_status_from_syntax_lookup(): ... def fake_try_to_query_status_from_dns_lookup(): self.checker.status.status = "MALICIOUS" self.checker.status.status_source = "REPUTATION" self.checker.do_syntax_check_first = True self.checker.subject = pyf_test_dataset.NOT_VALID_DOMAINS[0] self.checker.query_a_record = self.fake_query_a_record self.checker.try_to_query_status_from_syntax_lookup = ( fake_try_to_query_status_from_syntax_lookup ) self.checker.try_to_query_status_from_dns_lookup = ( fake_try_to_query_status_from_dns_lookup ) self.checker.query_status() expected_status = "MALICIOUS" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_negative(self) -> None: """ Tests the method which let us query the status of the given subject. """ def fake_try_to_query_status_from_syntax_lookup(): ... def fake_try_to_query_status_from_dns_lookup(): ... self.checker.do_syntax_check_first = True self.checker.subject = pyf_test_dataset.NOT_VALID_DOMAINS[0] self.checker.query_a_record = self.fake_query_a_record self.checker.try_to_query_status_from_syntax_lookup = ( fake_try_to_query_status_from_syntax_lookup ) self.checker.try_to_query_status_from_dns_lookup = ( fake_try_to_query_status_from_dns_lookup ) self.checker.query_status() expected_status = "SANE" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) @staticmethod def fake_pull_response(subject: str) -> dict: """ Provides a fake pull response to work with. :param subject: The subject to work with. """ return { "subject": subject, "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "status": { "syntax": { "latest": { "status": "VALID", "status_source": "SYNTAX", "tested_at": "2021-09-28T19:32:07.167Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", }, "frequent": "INVALID", "recommended": "VALID", }, "availability": { "latest": { "status": "ACTIVE", "status_source": "WHOIS", "tested_at": "2021-09-28T19:32:07.167Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", }, "frequent": "INACTIVE", "recommended": "ACTIVE", }, "reputation": { "latest": { "status": "SANE", "status_source": "REPUTATION", "tested_at": "2021-09-28T19:32:07.167Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", }, "frequent": "MALICIOUS", "recommended": "MALICIOUS", }, "whois": { "expiration_date": "2021-09-28T19:32:07.167Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "subject_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", }, }, } @staticmethod def fake_response_no_data(_: str) -> None: """ Provides an empty response. """ return None def test_try_to_query_status_from_platform(self) -> None: """ Tests the method that tries to define the status from the platform lookup. """ # Let's check the case that the subject is known. self.checker.subject = "example.com" self.checker.platform_query_tool.preferred_status_origin = "frequent" self.checker.platform_query_tool.pull = self.fake_pull_response self.checker.try_to_query_status_from_platform() expected_status = "MALICIOUS" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_status_source = "PLATFORM" actual_status_source = self.checker.status.status_source self.assertEqual(expected_status_source, actual_status_source) self.checker.platform_query_tool.preferred_status_origin = "latest" self.checker.try_to_query_status_from_platform() expected_status = "SANE" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_status_source = "PLATFORM" actual_status_source: str | None = self.checker.status.status_source self.assertEqual(expected_status_source, actual_status_source) self.checker.platform_query_tool.preferred_status_origin = "recommended" self.checker.try_to_query_status_from_platform() expected_status = "MALICIOUS" actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_status_source = "PLATFORM" actual_status_source = self.checker.status.status_source self.assertEqual(expected_status_source, actual_status_source) # Let's check the case that the subject is unknown. self.checker.subject = "102117110105108114121115" self.checker.platform_query_tool.pull = self.fake_response_no_data self.checker.try_to_query_status_from_platform() expected_status = None actual_status = self.checker.status.status self.assertEqual(expected_status, actual_status) expected_status_source = None actual_status_source = self.checker.status.status_source self.assertEqual(expected_status_source, actual_status_source) def test_get_status(self) -> None: """ Tests the method which let us query the status to interact with. """ self.test_query_status_negative() actual = self.checker.get_status() self.assertIsInstance(actual, ReputationCheckerStatus) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/reputation/test_domain.py000066400000000000000000000117631467462152100242610ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our domain reputation checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest import unittest.mock from PyFunceble.checker.reputation.domain import DomainReputationChecker from PyFunceble.query.dns.query_tool import DNSQueryTool try: import reputation_test_base except ModuleNotFoundError: # pragma: no cover from . import reputation_test_base class TestDomainReputationChecker(reputation_test_base.ReputationCheckerTestBase): """ Tests of the domain reputation checker. """ def setUp(self) -> None: """ Setups everything we need. """ upstream_result = super().setUp() self.checker = DomainReputationChecker() self.checker.ipv4_reputation_query_tool.source_file = self.tempfile.name self.dns_query_tool_path = unittest.mock.patch.object(DNSQueryTool, "query") self.mock_query_tool = self.dns_query_tool_path.start() # Not needed in this scope :-) self.checker.do_syntax_check_first = False return upstream_result def tearDown(self) -> None: """ Destroys everything previously initiated for the tests. """ upstream_result = super().tearDown() self.dns_query_tool_path.stop() del self.dns_query_tool_path del self.mock_query_tool return upstream_result def test_query_status_positive(self) -> None: """ Tests the method which let us query the status for the case that the resolved IP is known to be malicious. """ self.mock_query_tool.return_value = self.fake_query_a_record() self.checker.subject = "example.org" self.checker.query_status() expected_status = "MALICIOUS" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_negative(self) -> None: """ Tests the method which let us query the status for the case that the resolved IP is not known to be malicious. """ self.mock_query_tool.return_value = self.fake_query_a_record_not_known() self.checker.subject = "example.org" self.checker.query_status() expected_status = "SANE" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/reputation/test_domain_and_ip.py000066400000000000000000000117541467462152100255730ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our hybrid (domain & IP) reputation checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest import unittest.mock from PyFunceble.checker.reputation.domain_and_ip import DomainAndIPReputationChecker from PyFunceble.query.dns.query_tool import DNSQueryTool try: import reputation_test_base except ModuleNotFoundError: # pragma: no cover from . import reputation_test_base class TestDomainReputationChecker(reputation_test_base.ReputationCheckerTestBase): """ Tests of the hybrid (domain & IP) reputation checker. """ def setUp(self) -> None: """ Setups everything we need. """ upstream_result = super().setUp() self.checker = DomainAndIPReputationChecker() self.checker.ipv4_reputation_query_tool.source_file = self.tempfile.name self.dns_query_tool_path = unittest.mock.patch.object(DNSQueryTool, "query") self.mock_query_tool = self.dns_query_tool_path.start() # Not needed in this scope :-) self.checker.do_syntax_check_first = False return upstream_result def tearDown(self) -> None: """ Destroys everything previously initiated for the tests. """ upstream_result = super().tearDown() self.dns_query_tool_path.stop() del self.dns_query_tool_path del self.mock_query_tool return upstream_result def test_query_status_domain(self) -> None: """ Tests the method which let us query the status for the case that the inputted subject is a domain. """ self.mock_query_tool.return_value = self.fake_query_a_record() self.checker.subject = "example.org" self.checker.query_status() expected_status = "MALICIOUS" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_ip(self) -> None: """ Tests the method which let us query the status for the case that the inputted subject is an IP. """ self.mock_query_tool.return_value = ["192.168.1.1"] self.checker.subject = "192.168.1.1" self.checker.query_status() expected_status = "SANE" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/reputation/test_ip.py000066400000000000000000000144501467462152100234160ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our IP reputation checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest import unittest.mock from PyFunceble.checker.reputation.ip import IPReputationChecker from PyFunceble.query.dns.query_tool import DNSQueryTool try: import reputation_test_base except ModuleNotFoundError: # pragma: no cover from . import reputation_test_base class TestIPReputationChecker(reputation_test_base.ReputationCheckerTestBase): """ Tests of the IP reputation checker. """ def setUp(self) -> None: """ Setups everything we need. """ upstream_result = super().setUp() self.checker = IPReputationChecker() self.checker.ipv4_reputation_query_tool.source_file = self.tempfile.name self.dns_query_tool_path = unittest.mock.patch.object(DNSQueryTool, "query") self.mock_query_tool = self.dns_query_tool_path.start() # Not needed in this scope :-) self.checker.do_syntax_check_first = False return upstream_result def tearDown(self) -> None: """ Destroys everything previously initiated for the tests. """ upstream_result = super().tearDown() self.dns_query_tool_path.stop() del self.dns_query_tool_path del self.mock_query_tool return upstream_result def test_query_status_positive_ipv4(self) -> None: """ Tests the method which let us query the status for the case that the given IPv4 is known to be malicious. """ self.mock_query_tool.return_value = ["127.176.134.253"] self.checker.subject = "127.176.134.253" self.checker.query_status() expected_status = "MALICIOUS" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_positive_ipv6(self) -> None: """ Tests the method which let us query the status for the case that the given IPv6 is known to be malicious. """ self.mock_query_tool.return_value = self.fake_query_a_record() self.checker.subject = "2606:2800:220:1:248:1893:25c8:1946" self.checker.query_status() expected_status = "MALICIOUS" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_negative_ipv4(self) -> None: """ Tests the method which let us query the status for the case that the given IPv4 is not known to be malicious. """ self.mock_query_tool.return_value = ["192.168.1.1"] self.checker.subject = "192.168.1.1" self.checker.query_status() expected_status = "SANE" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_negative_ipv6(self) -> None: """ Tests the method which let us query the status for the case that the given IPv6 is not known to be malicious. """ self.mock_query_tool.return_value = self.fake_query_a_record_not_known() self.checker.subject = "2606:2800:220:1:248:1893:25c8:1946" self.checker.query_status() expected_status = "SANE" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/reputation/test_status.py000066400000000000000000000120331467462152100243240ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our reputation status handler. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest import unittest.mock from PyFunceble.checker.reputation.status import ReputationCheckerStatus class TestReputationCheckerStatus(unittest.TestCase): """ Tests of our reputation status handler. """ def setUp(self) -> None: """ Setups everything we need. """ self.status = ReputationCheckerStatus(subject="example.org") def tearDown(self) -> None: """ Destroys everything previously initiated for the tests. """ del self.status def test_is_malicious(self) -> None: """ Tests the method which let us check if the current status is a malicious one. """ self.status.status = "MALICIOUS" expected = True actual = self.status.is_malicious() self.assertEqual(expected, actual) def test_is_not_malicious(self) -> None: """ Tests the method which let us check if the current status is a malicious one. In this test we check the case that the status is actually not malicious. """ self.status.status = "SANE" expected = False actual = self.status.is_malicious() self.assertEqual(expected, actual) def test_is_sane(self) -> None: """ Tests the method which let us check if the current status is a sane one. """ self.status.status = "SANE" expected = True actual = self.status.is_sane() self.assertEqual(expected, actual) def test_is_not_sane(self) -> None: """ Tests the method which let us check if the current status is a sane one. In this test we check the case that the status is actually not sane. """ self.status.status = "MALICIOUS" expected = False actual = self.status.is_sane() self.assertEqual(expected, actual) def test_has_bad_reputation(self) -> None: """ Tests the method which let us check if the current status is a bad one. """ self.status.status = "MALICIOUS" expected = True actual = self.status.has_bad_reputation() self.assertEqual(expected, actual) def test_has_not_bad_reputation(self) -> None: """ Tests the method which let us check if the current status is a bad one. In this test we check the case that the status is actually a good one """ self.status.status = "SANE" expected = False actual = self.status.has_bad_reputation() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/reputation/test_url.py000066400000000000000000000173351467462152100236150ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our URL reputation checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest import unittest.mock from PyFunceble.checker.reputation.url import URLReputationChecker from PyFunceble.query.dns.query_tool import DNSQueryTool try: import reputation_test_base except ModuleNotFoundError: # pragma: no cover from . import reputation_test_base class TestURLReputationChecker(reputation_test_base.ReputationCheckerTestBase): """ Tests of the URL reputation checker. """ def setUp(self) -> None: """ Setups everything we need. """ upstream_result = super().setUp() self.checker = URLReputationChecker() self.checker.ipv4_reputation_query_tool.source_file = self.tempfile.name self.dns_query_tool_path = unittest.mock.patch.object(DNSQueryTool, "query") self.mock_query_tool = self.dns_query_tool_path.start() # Not needed in this scope :-) self.checker.do_syntax_check_first = False return upstream_result def tearDown(self) -> None: """ Destroys everything previously initiated for the tests. """ upstream_result = super().tearDown() self.dns_query_tool_path.stop() del self.dns_query_tool_path del self.mock_query_tool return upstream_result def test_query_status_positive_domain(self) -> None: """ Tests the method which let us query the status for the case that the resolved IP of the given URL is known to be malicious. """ self.mock_query_tool.return_value = self.fake_query_a_record() self.checker.subject = "https://example.org" self.checker.query_status() expected_status = "MALICIOUS" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_positive_ipv4(self) -> None: """ Tests the method which let us query the status for the case that the IP of the given URL is known to be malicious. """ self.mock_query_tool.return_value = ["127.176.134.253"] self.checker.subject = "https://127.176.134.253" self.checker.query_status() expected_status = "MALICIOUS" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_positive_ipv6(self) -> None: """ Tests the method which let us query the status for the case that the IP of the given URL is known to be malicious. """ self.mock_query_tool.return_value = self.fake_query_a_record() self.checker.subject = "https://[2606:2800:220:1:248:1893:25c8:1946]" self.checker.query_status() expected_status = "MALICIOUS" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_negative_domain(self) -> None: """ Tests the method which let us query the status for the case that the resolved IP of the given URL is not known to be malicious. """ self.mock_query_tool.return_value = self.fake_query_a_record_not_known() self.checker.subject = "https://example.org" self.checker.query_status() expected_status = "SANE" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_negative_ipv4(self) -> None: """ Tests the method which let us query the status for the case that the IP of the given URL is not known to be malicious. """ self.mock_query_tool.return_value = ["192.168.1.1"] self.checker.subject = "https://192.168.1.1" self.checker.query_status() expected_status = "SANE" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) def test_query_status_negative_ipv6(self) -> None: """ Tests the method which let us query the status for the case that the IP of the given URL is not known to be malicious. """ self.mock_query_tool.return_value = self.fake_query_a_record_not_known() self.checker.subject = "https://[2606:2800:220:1:248:1893:25c8:1946]" self.checker.query_status() expected_status = "SANE" expected_source = "REPUTATION" actual_status = self.checker.status.status actual_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_source, actual_source) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/syntax/000077500000000000000000000000001467462152100205255ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/checker/syntax/__init__.py000066400000000000000000000000001467462152100226240ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/checker/syntax/test_base.py000066400000000000000000000132071467462152100230530ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our syntax checker base. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.syntax.base import SyntaxCheckerBase class TestSyntaxCheckerBase(unittest.TestCase): """ Tests of the base of all our syntax checker. """ def setUp(self) -> None: """ Setups everything we need. """ self.checker = SyntaxCheckerBase() def tearDown(self) -> None: """ Destroyes everything we don't need. """ del self.checker def test_subject_propagator(self) -> None: """ Tests that the subject subjects and it's IDNA counterpart are correctly propagated. """ given = "รคxample.org" expected_subject = "รคxample.org" expected_idna_subject = "xn--xample-9ta.org" self.checker.subject = given actual_subject = self.checker.status.subject actual_idna_subject = self.checker.status.idna_subject self.assertEqual(expected_subject, actual_subject) self.assertEqual(expected_idna_subject, actual_idna_subject) # Now, just make sure that when overwrite, the status get changed # propagated too. given = "รคxample.net" expected_subject = "รคxample.net" expected_idna_subject = "xn--xample-9ta.net" self.checker.subject = given actual_subject = self.checker.status.subject actual_idna_subject = self.checker.status.idna_subject self.assertEqual(expected_subject, actual_subject) self.assertEqual(expected_idna_subject, actual_idna_subject) def test_query_status_invalid(self) -> None: """ Tests the method which let us query the status for the case that the given dataset is invalid. """ given = "รคxample.org" self.checker.subject = given # The validator always return False. self.checker.is_valid = lambda: False expected_default_status = None actual_status = self.checker.status.status self.assertEqual(expected_default_status, actual_status) self.checker.query_status() expected_status = "INVALID" expected_status_source = "SYNTAX" actual_status = self.checker.status.status actual_status_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_status_source, actual_status_source) def test_query_status_valid(self) -> None: """ Tests the method which let us query the status for the case that the given dataset is valid. """ given = "รคxample.org" self.checker.subject = given # The validator always return True. self.checker.is_valid = lambda: True expected_default_status = None actual_status = self.checker.status.status self.assertEqual(expected_default_status, actual_status) self.checker.query_status() expected_status = "VALID" expected_status_source = "SYNTAX" actual_status = self.checker.status.status actual_status_source = self.checker.status.status_source self.assertEqual(expected_status, actual_status) self.assertEqual(expected_status_source, actual_status_source) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/syntax/test_domain.py000066400000000000000000000147361467462152100234200ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our subdomain checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.syntax.domain import DomainSyntaxChecker try: import pyf_test_dataset except (ModuleNotFoundError, ImportError): # pragma: no cover try: from .. import pyf_test_dataset except (ModuleNotFoundError, ImportError): from ... import pyf_test_dataset class TestSubDomainSyntaxChecker(unittest.TestCase): """ Tests of our subdomain syntax checker. """ def test_is_valid(self) -> None: """ Tests the method which let us check if the given subject is valid. """ domain_checker = DomainSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_DOMAINS: domain_checker.subject = subject actual = domain_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_valid_subdomain(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that a subdomain is given. """ domain_checker = DomainSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_SUBDOMAINS: domain_checker.subject = subject actual = domain_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not valid. """ domain_checker = DomainSyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_VALID_DOMAINS: domain_checker.subject = subject actual = domain_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid_not_extension(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject has no valid extension. """ expected = False given = "example" actual = DomainSyntaxChecker(given).is_valid() self.assertEqual(expected, actual) def test_is_not_valid_not_rfc_compliant(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not RFC compliant. """ expected = False given = "example.hello_world.org" actual = DomainSyntaxChecker(given).is_valid() self.assertEqual(expected, actual, given) def test_is_valid_second_lvl_domain(self) -> None: """ Tests the method which let us check if the given subject is a valid second level domain. """ expected = True domain_checker = DomainSyntaxChecker() for subject in pyf_test_dataset.VALID_SECOND_LVL_DOMAINS: domain_checker.subject = subject actual = domain_checker.is_valid_second_level() self.assertEqual(expected, actual) def test_is_not_valid_second_lvl_domain(self) -> None: """ Tests the method which let us check if the given subject is a valid second level domain for the case the it is actually not a second level domain. """ expected = False domain_checker = DomainSyntaxChecker() for subject in pyf_test_dataset.NOT_VALID_SECOND_LVL_DOMAINS: domain_checker.subject = subject actual = domain_checker.is_valid_second_level() self.assertEqual(expected, actual) def test_is_not_valid_subdomain(self) -> None: """ Tests the method which let us check if the given subject is a valid subdomain for the case that it is actually not a valid subdomain. """ expected = False domain_checker = DomainSyntaxChecker() for subject in pyf_test_dataset.NOT_VALID_SUBDOMAINS: domain_checker.subject = subject actual = domain_checker.is_valid_subdomain() self.assertEqual(expected, actual, subject) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/syntax/test_domain_base.py000066400000000000000000000130511467462152100243770ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our domain checker base. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.syntax.domain_base import DomainSyntaxCheckerBase class TestSDomainSyntaxCheckerBase(unittest.TestCase): """ Tests of the base of all our domain syntax checker. """ def setUp(self) -> None: """ Setups everything we need. """ self.checker = DomainSyntaxCheckerBase() def tearDown(self) -> None: """ Destroyes everything we don't need. """ del self.checker def test_get_last_point_index(self) -> None: """ Tests the method which let us get the position of the last point of a given subject. In this test, we test for a normal subject. """ given = "example.org" # Just initizalize the whole this as usual. self.checker.subject = given expected = 7 actual = self.checker.get_last_point_index(given) self.assertEqual(expected, actual) def test_get_last_point_index_ends_with_point(self) -> None: """ Tests the method which let us get the position of the last point of a given subject. In this test, we test for a subject which ends with a point. """ given = "example.org." # Just initizalize the whole this as usual. self.checker.subject = given expected = 7 actual = self.checker.get_last_point_index(given) self.assertEqual(expected, actual) def test_get_last_point_index_no_point(self) -> None: """ Tests the method which let us get the position of the last point of a given subject. In this test, we test for an INVALID subject (no point at all). """ given = "example" # Just initizalize the whole this as usual. self.checker.subject = given expected = None actual = self.checker.get_last_point_index(given) self.assertEqual(expected, actual) def test_get_extension(self) -> None: """ Tests the method which let us get the extension of the currently loaded subject. """ given = "example.org" self.checker.subject = given expected = "org" actual = self.checker.get_extension() self.assertEqual(expected, actual) def test_get_extension_ends_with_point(self) -> None: """ Tests the method which let us get the extension of the currently loaded subject. In this test, we give a subject which ends with a point. """ given = "example.org." self.checker.subject = given expected = "org" actual = self.checker.get_extension() self.assertEqual(expected, actual) def test_get_extension_ends_no_point(self) -> None: """ Tests the method which let us get the extension of the currently loaded subject. In this test, we give a subject which in INVALID (no point). """ given = "example" self.checker.subject = given expected = None actual = self.checker.get_extension() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/syntax/test_ip.py000066400000000000000000000220011467462152100225410ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our IP (v4 and v6) syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.syntax.ip import IPSyntaxChecker try: import pyf_test_dataset except (ModuleNotFoundError, ImportError): # pragma: no cover try: from .. import pyf_test_dataset except (ModuleNotFoundError, ImportError): from ... import pyf_test_dataset class TestIPSyntaxChecker(unittest.TestCase): """ Tests of our IP (v4 and v6) syntax checker. """ def test_is_valid_v4(self) -> None: """ Tests the method which let us check if the given subject is valid. """ ip_checker = IPSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_IPV4: actual = ip_checker.set_subject(subject).is_valid() self.assertEqual(expected, actual, subject) def test_is_valid_v6(self) -> None: """ Tests the method which let us check if the given subject is valid. """ ip_checker = IPSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_IPV6: ip_checker.subject = subject actual = ip_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid_v4(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not valid. """ ip_checker = IPSyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_VALID_IPV4: ip_checker.subject = subject actual = ip_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid_v6(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not valid. """ ip_checker = IPSyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_VALID_IPV6: ip_checker.subject = subject actual = ip_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_valid_range_v4(self) -> None: """ Tests the method which let us check if the given subject is valid range. """ ip_checker = IPSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_IPV4_RANGES: ip_checker.subject = subject actual = ip_checker.is_valid_range() self.assertEqual(expected, actual, subject) def test_is_valid_range_v6(self) -> None: """ Tests the method which let us check if the given subject is valid range. """ ip_checker = IPSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_IPV6_RANGES: ip_checker.subject = subject actual = ip_checker.is_valid_range() self.assertEqual(expected, actual, subject) def test_is_not_valid_range_v4(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not a valid range. """ ip_checker = IPSyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_VALID_IPV4_RANGES: ip_checker.subject = subject actual = ip_checker.is_valid_range() self.assertEqual(expected, actual, subject) def test_is_not_valid_range(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not a valid range. """ ip_checker = IPSyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_VALID_IPV6_RANGES: ip_checker.subject = subject actual = ip_checker.is_valid_range() self.assertEqual(expected, actual, subject) def test_is_reserved_v4(self) -> None: """ Tests the method which let us check if the given subject is reserved. """ ip_checker = IPSyntaxChecker() expected = True for subject in pyf_test_dataset.RESERVED_IPV4: ip_checker.subject = subject actual = ip_checker.is_reserved() self.assertEqual(expected, actual, subject) def test_is_reserved_v6(self) -> None: """ Tests the method which let us check if the given subject is reserved. """ ip_checker = IPSyntaxChecker() expected = True for subject in pyf_test_dataset.RESERVED_IPV6: ip_checker.subject = subject actual = ip_checker.is_reserved() self.assertEqual(expected, actual, subject) def test_is_not_reserved_v4(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not reserved. """ ip_checker = IPSyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_RESERVED_IPV4: ip_checker.subject = subject actual = ip_checker.is_reserved() self.assertEqual(expected, actual, subject) def test_is_not_reserved_v6(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not reserved. """ ip_checker = IPSyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_RESERVED_IPV6: ip_checker.subject = subject actual = ip_checker.is_reserved() self.assertEqual(expected, actual, subject) def test_is_valid(self) -> None: """ Tests the method which let us check if the given subject is valid IPv4 or IPv6. """ ip_checker = IPSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_IPV4 + pyf_test_dataset.VALID_IPV6: ip_checker.subject = subject actual = ip_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid(self) -> None: """ Tests the method which let us check if the given subject is valid IPv4 or IPv6 for the case that is not a valid IPv4 or IPv6. """ ip_checker = IPSyntaxChecker() expected = False for subject in ( pyf_test_dataset.NOT_VALID_IPV4 + pyf_test_dataset.NOT_VALID_IPV6 ): ip_checker.subject = subject actual = ip_checker.is_valid() self.assertEqual(expected, actual, subject) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/syntax/test_ipv4.py000066400000000000000000000125471467462152100230310ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our IPv4 syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.syntax.ipv4 import IPv4SyntaxChecker try: import pyf_test_dataset except (ModuleNotFoundError, ImportError): # pragma: no cover try: from .. import pyf_test_dataset except (ModuleNotFoundError, ImportError): from ... import pyf_test_dataset class TestIPv4SyntaxChecker(unittest.TestCase): """ Tests of our IPv4 syntax checker. """ def test_is_valid(self) -> None: """ Tests the method which let us check if the given subject is valid. """ ipv4_checker = IPv4SyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_IPV4: actual = ipv4_checker.set_subject(subject).is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not valid. """ ipv4_checker = IPv4SyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_VALID_IPV4: actual = ipv4_checker.set_subject(subject).is_valid() self.assertEqual(expected, actual, subject) def test_is_valid_range(self) -> None: """ Tests the method which let us check if the given subject is valid range. """ ipv4_checker = IPv4SyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_IPV4_RANGES: actual = ipv4_checker.set_subject(subject).is_valid_range() self.assertEqual(expected, actual, subject) def test_is_not_valid_range(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not a valid range. """ ipv4_checker = IPv4SyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_VALID_IPV4_RANGES: actual = ipv4_checker.set_subject(subject).is_valid_range() self.assertEqual(expected, actual, subject) def test_is_reserved(self) -> None: """ Tests the method which let us check if the given subject is reserved. """ ipv4_checker = IPv4SyntaxChecker() expected = True for subject in pyf_test_dataset.RESERVED_IPV4: actual = ipv4_checker.set_subject(subject).is_reserved() self.assertEqual(expected, actual, subject) def test_is_not_reserved(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not reserved. """ ipv4_checker = IPv4SyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_RESERVED_IPV4: actual = ipv4_checker.set_subject(subject).is_reserved() self.assertEqual(expected, actual, subject) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/syntax/test_ipv6.py000066400000000000000000000127251467462152100230310ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our IPv6 syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.syntax.ipv6 import IPv6SyntaxChecker try: import pyf_test_dataset except (ModuleNotFoundError, ImportError): # pragma: no cover try: from .. import pyf_test_dataset except (ModuleNotFoundError, ImportError): from ... import pyf_test_dataset class TestIPv6SyntaxChecker(unittest.TestCase): """ Tests of our IPv6 syntax checker. """ def test_is_valid(self) -> None: """ Tests the method which let us check if the given subject is valid. """ ipv6_checker = IPv6SyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_IPV6: actual = ipv6_checker.set_subject(subject).is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not valid. """ ipv6_checker = IPv6SyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_VALID_IPV6: ipv6_checker.subject = subject actual = ipv6_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_valid_range(self) -> None: """ Tests the method which let us check if the given subject is valid range. """ ipv6_checker = IPv6SyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_IPV6_RANGES: ipv6_checker.subject = subject actual = ipv6_checker.is_valid_range() self.assertEqual(expected, actual, subject) def test_is_not_valid_range(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not a valid range. """ ipv6_checker = IPv6SyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_VALID_IPV6_RANGES: ipv6_checker.subject = subject actual = ipv6_checker.is_valid_range() self.assertEqual(expected, actual, subject) def test_is_reserved(self) -> None: """ Tests the method which let us check if the given subject is reserved. """ ipv6_checker = IPv6SyntaxChecker() expected = True for subject in pyf_test_dataset.RESERVED_IPV6: ipv6_checker.subject = subject actual = ipv6_checker.is_reserved() self.assertEqual(expected, actual, subject) def test_is_not_reserved(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not reserved. """ ipv6_checker = IPv6SyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_RESERVED_IPV6: ipv6_checker.subject = subject actual = ipv6_checker.is_reserved() self.assertEqual(expected, actual, subject) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/syntax/test_second_lvl_domain.py000066400000000000000000000120041467462152100256120ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our second level domain checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.syntax.second_lvl_domain import SecondLvlDomainSyntaxChecker try: import pyf_test_dataset except (ModuleNotFoundError, ImportError): # pragma: no cover try: from .. import pyf_test_dataset except (ModuleNotFoundError, ImportError): from ... import pyf_test_dataset class TestSecondLvlDomainSyntaxChecker(unittest.TestCase): """ Tests of our second level domain syntax checker. """ def test_is_valid(self) -> None: """ Tests the method which let us check if the given subject is valid. """ snd_lvl_checker = SecondLvlDomainSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_SECOND_LVL_DOMAINS: actual = snd_lvl_checker.set_subject(subject).is_valid() self.assertEqual(expected, actual, subject) def test_is_valid_ends_with_point(self) -> None: """ Tests the method which let us check if the given subject is valid. """ snd_lvl_checker = SecondLvlDomainSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_SECOND_LVL_DOMAINS: snd_lvl_checker.subject = f"{subject}." actual = snd_lvl_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not valid. """ snd_lvl_checker = SecondLvlDomainSyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_VALID_SECOND_LVL_DOMAINS: snd_lvl_checker.subject = subject actual = snd_lvl_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid_not_extension(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject has no valid extension. """ expected = False given = "example" actual = SecondLvlDomainSyntaxChecker(given).is_valid() self.assertEqual(expected, actual) def test_is_not_valid_not_rfc_compliant(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not RFC compliant. """ expected = False given = "hello_world.org" actual = SecondLvlDomainSyntaxChecker(given).is_valid() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/syntax/test_status.py000066400000000000000000000103661467462152100234670ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our status syntax status handler. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.syntax.status import SyntaxCheckerStatus class TestSyntaxCheckerStatus(unittest.TestCase): """ Tests of our status handler. """ def setUp(self) -> None: """ Setups everything we need. """ self.status = SyntaxCheckerStatus(subject="example.org") def tearDown(self) -> None: """ Destroyes everything we don't need. """ del self.status def test_is_valid(self) -> None: """ Tests the status method which let us fast check if it is describing a valid subject. """ expected = True self.status.status = "VALID" actual = self.status.is_valid() self.assertEqual(expected, actual) def test_is_not_valid(self) -> None: """ Tests the status method which let us fast check if it is describing a valid subject. But, for the case that it is not actually VALID. """ expected = False self.status.status = "ACTIVE" actual = self.status.is_valid() self.assertEqual(expected, actual) def test_is_invalid(self) -> None: """ Tests the status method which let us fast check if it is describing an invalid subject. """ expected = True self.status.status = "INVALID" actual = self.status.is_invalid() self.assertEqual(expected, actual) def test_is_not_invalid(self) -> None: """ Tests the status method which let us fast check if it is describing a valid subject. But, for the case that it is not actually INVALID. """ expected = False self.status.status = "MALICIOUS" actual = self.status.is_invalid() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/syntax/test_subdomain.py000066400000000000000000000117011467462152100241170ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our subdomain checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.syntax.subdomain import SubDomainSyntaxChecker try: import pyf_test_dataset except (ModuleNotFoundError, ImportError): # pragma: no cover try: from .. import pyf_test_dataset except (ModuleNotFoundError, ImportError): from ... import pyf_test_dataset class TestSubSubDomainSyntaxChecker(unittest.TestCase): """ Tests of our subdomain syntax checker. """ def test_is_valid(self) -> None: """ Tests the method which let us check if the given subject is valid. """ subdomain_checker = SubDomainSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_SUBDOMAINS: actual = subdomain_checker.set_subject(subject).is_valid() self.assertEqual(expected, actual, subject) def test_is_valid_ends_with_point(self) -> None: """ Tests the method which let us check if the given subject is valid. """ subdomain_checker = SubDomainSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_SUBDOMAINS: subdomain_checker.subject = f"{subject}." actual = subdomain_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not valid. """ subdomain_checker = SubDomainSyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_VALID_SUBDOMAINS: subdomain_checker.subject = subject actual = subdomain_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid_not_extension(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject has no valid extension. """ expected = False given = "example" actual = SubDomainSyntaxChecker(given).is_valid() self.assertEqual(expected, actual) def test_is_not_valid_not_rfc_compliant(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not RFC compliant. """ expected = False given = "example.hello_world.org" actual = SubDomainSyntaxChecker(given).is_valid() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/syntax/test_url.py000066400000000000000000000155671467462152100227560ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our url syntax checker. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.syntax.url import URLSyntaxChecker try: import pyf_test_dataset except (ModuleNotFoundError, ImportError): # pragma: no cover try: from .. import pyf_test_dataset except (ModuleNotFoundError, ImportError): from ... import pyf_test_dataset class TestURLSyntaxChecker(unittest.TestCase): """ Tests of our URL syntax checker. """ def test_is_valid(self) -> None: """ Tests the method which let us check if the given subject is valid. """ url_checker = URLSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_DOMAINS: url_checker.subject = f"https://{subject}/?is_admin=true" actual = url_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_valid_in_url_context(self) -> None: """ Tests the syntax checker against some special use cases that are VALID in URL context. """ url_checker = URLSyntaxChecker() expected = True given = [ "https://example.org:8080", "https://github.com:9999", "http://example.org:8099/hello/world", "http://example.org:8939?hello=world", ] for subject in given: url_checker.subject = subject actual = url_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_valid_subdomain(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that a subdomain is given. """ url_checker = URLSyntaxChecker() expected = True for subject in pyf_test_dataset.VALID_SUBDOMAINS: url_checker.subject = f"https://{subject}/?is_admin=true" actual = url_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not valid. """ url_checker = URLSyntaxChecker() expected = False for subject in pyf_test_dataset.NOT_VALID_DOMAINS: url_checker.subject = f"{subject}/?is_admin=true" actual = url_checker.is_valid() self.assertEqual(expected, actual, subject) def test_is_not_valid_not_extension(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject has no valid extension. """ expected = False given = "http://example" actual = URLSyntaxChecker(given).is_valid() self.assertEqual(expected, actual) def test_is_not_valid_not_rfc_compliant(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that the given subject is not RFC compliant. """ expected = False given = "http://example.hello_world.org" actual = URLSyntaxChecker(given).is_valid() self.assertEqual(expected, actual) def test_is_not_valid_no_scheme(self) -> None: """ Tests the method which let us check if the given subject is valid for the case that no scheme is given. """ url_checker = URLSyntaxChecker() expected = False for subject in pyf_test_dataset.VALID_DOMAINS: subject = f"{subject}/?is_admin=true" actual = url_checker.set_subject(subject).is_valid() self.assertEqual(expected, actual, subject) def test_get_hostname_from_url(self) -> None: """ Tests the method that let us get the hostname (or url base if you prefer) of a given URL. .. versionadded:: 4.1.0b7. """ url_checker = URLSyntaxChecker() given2expected = { "https://example.org/hello-world": "example.org", "example.org": None, "://example.org/hello-world": None, "https://example.org:8888/hello-world": "example.org", "example.org:8080": None, "http:///hello-world": None, "http://10.3.0.1/hello-world": "10.3.0.1", } for given, expected in given2expected.items(): actual = url_checker.get_hostname_from_url(given) self.assertEqual(expected, actual, given) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/test_base.py000066400000000000000000000303711467462152100215260ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our checker base. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.base import CheckerBase, CheckerStatusBase from PyFunceble.config.loader import ConfigLoader class TestCheckerBase(unittest.TestCase): """ Tests of the base of all our checker. """ def setUp(self) -> None: """ Setups everything we need. """ self.checker = CheckerBase() def tearDown(self) -> None: """ Destroyes everything we don't need. """ del self.checker def test_set_subject_return(self) -> None: """ Tests the response of the method which let us set the subject to work with. """ given = "example.org" actual = self.checker.set_subject(given) self.assertIsInstance(actual, CheckerBase) def test_set_subject_method(self) -> None: """ Tests the method which let us set the subject to work with. """ given = "example.org" expected = "example.org" self.checker.set_subject(given) actual = self.checker.subject self.assertEqual(expected, actual) def test_set_subject_idna(self) -> None: """ Tests the initilization of the :code:`idna_subject` attribute when we overwrite the subject. """ given = "รคxample.org" expected_subject = "รคxample.org" expected_idna_subject = "xn--xample-9ta.org" self.checker.subject = given actual_subject = expected_subject actual_idna_subject = expected_idna_subject self.assertEqual(expected_subject, actual_subject) self.assertEqual(expected_idna_subject, actual_idna_subject) def test_set_subject_idna_url(self) -> None: """ Tests the initilization of the :code:`idna_subject` attribute when we overwrite the subject. In this case we check the conversion when a URL is given. """ given = "http://รคxample.org/?is_admin=true" expected_subject = "http://รคxample.org/?is_admin=true" expected_idna_subject = "http://xn--xample-9ta.org/?is_admin=true" self.checker.subject = given actual_subject = expected_subject actual_idna_subject = expected_idna_subject self.assertEqual(expected_subject, actual_subject) self.assertEqual(expected_idna_subject, actual_idna_subject) def test_set_subject_idna_not_wrong_ipv6_format(self) -> None: """ Tests the initilization of the :code:`idna_subject` attribute when we overwrite the subject. In this case we check the case the wrongly formatted "IPv6" issue. """ given = 'http://example.org."]' expected_subject = 'http://example.org."]' expected_idna_subject = 'http://example.org."]' self.checker.subject = given actual_subject = expected_subject actual_idna_subject = expected_idna_subject self.assertEqual(expected_subject, actual_subject) self.assertEqual(expected_idna_subject, actual_idna_subject) def test_set_subject_through_init(self) -> None: """ Tests the overwritting of the subjct through the class constructor. """ given = "example.org" expected = "example.org" checker = CheckerBase(given) actual = checker.subject self.assertEqual(expected, actual) def test_set_subject_not_str(self) -> None: """ Tests the case that we want to set a non-string subject. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.checker.set_subject(given)) def test_set_subject_empty_str(self) -> None: """ Tests the case that we want to set an empty string as subject. """ given = "" self.assertRaises(ValueError, lambda: self.checker.set_subject(given)) def test_set_idna_subject(self) -> None: """ Tests the case that we want to overwrite the :code:`idna_subject` attribute. """ given = "xn--xample-9ta.org" expected = "xn--xample-9ta.org" self.checker.idna_subject = given actual = self.checker.idna_subject self.assertEqual(expected, actual) def test_set_idna_subject_method(self) -> None: """ Tests the method that let us overwrite the :code:`idna_subject` attribute. """ given = "xn--xample-9ta.org" expected = "xn--xample-9ta.org" actual = self.checker.set_idna_subject(given) self.assertIsInstance(actual, CheckerBase) actual = self.checker.idna_subject self.assertEqual(expected, actual) def test_set_idna_subject_not_str(self) -> None: """ Tests the case that we want to overwrite the :code:`idna_subject` attribute with a non-string value. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.checker.set_idna_subject(given)) def test_set_idna_subject_empty_str(self) -> None: """ Tests the case that we want to overwrite the :code:`idna_subject` attribute with an empty string value. """ given = "" self.assertRaises(ValueError, lambda: self.checker.set_idna_subject(given)) def test_set_do_syntax_check_first_return(self) -> None: """ Tests the response of the method which let us define that we want the syntax to be tested first. """ given = True actual = self.checker.set_do_syntax_check_first(given) self.assertIsInstance(actual, CheckerBase) def test_set_do_syntax_check_first_method(self) -> None: """ Tests the method which let us define that we want the syntax to be tested first. """ given = False expected = False self.checker.set_do_syntax_check_first(given) actual = self.checker.do_syntax_check_first self.assertEqual(expected, actual) def test_set_do_syntax_check_first_init(self) -> None: """ Tests the definition of the :code:`do_syntax_check_first` attribute through the class constructor. """ given = True expected = True checker = CheckerBase(do_syntax_check_first=given) actual = checker.do_syntax_check_first self.assertEqual(expected, actual) def test_set_do_syntax_check_first_not_bool(self) -> None: """ Tests the case that we want to overwrite the :code:`do_syntax_check_first` attribute with a non-boolean value. """ given = ["Hello", "World!"] self.assertRaises( TypeError, lambda: self.checker.set_do_syntax_check_first(given) ) def test_set_use_platform_return(self) -> None: """ Tests the response of the method which let us define that we want to interact with the platform. """ given = True actual = self.checker.set_use_platform(given) self.assertIsInstance(actual, CheckerBase) def test_set_use_platform_method(self) -> None: """ Tests the method which let us define that we want ti interact with the platform. """ given = False expected = False self.checker.set_use_platform(given) actual = self.checker.use_platform self.assertEqual(expected, actual) def test_set_use_platform_init(self) -> None: """ Tests the definition of the :code:`use_platform` attribute through the class constructor. """ given = True expected = True checker = CheckerBase(use_platform=given) actual = checker.use_platform self.assertEqual(expected, actual) def test_set_use_platform_not_bool(self) -> None: """ Tests the case that we want to overwrite the :code:`use_platform` attribute with a non-boolean value. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.checker.set_use_platform(given)) def test_guess_and_set_use_platform(self) -> None: """ Tests the method that let us guess and set the platform from the configuration. """ config_loader = ConfigLoader() config_loader.set_custom_config({"lookup": {"platform": True}}).start() self.checker.guess_and_set_use_platform() actual = self.checker.use_platform expected = True self.assertEqual(expected, actual) def test_guess_and_set_use_platform_not_boolean(self) -> None: """ Tests the method that let us guess and set the platform from the configuration. In this case, we test the case that the given value is not a boolean. """ config_loader = ConfigLoader() config_loader.set_custom_config({"lookup": {"platform": None}}).start() self.checker.guess_and_set_use_platform() actual = self.checker.use_platform expected = False self.assertEqual(expected, actual) del config_loader def test_guess_and_set_use_platform_no_configuration(self) -> None: """ Tests the method that let us guess and set the platform from the configuration. In this case, we test the case that no configuration is loaded. """ self.checker.guess_and_set_use_platform() actual = self.checker.use_platform expected = False self.assertEqual(expected, actual) def test_get_status(self) -> None: """ Tests the method which let us get the status. """ given = "example.org" # This is an abstract method. So we need to define it. self.checker.query_status = lambda: None self.checker.subject = given actual = self.checker.get_status() self.assertIsInstance(actual, CheckerStatusBase) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/test_params_base.py000066400000000000000000000073401467462152100230710ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our checker parameters base. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.params_base import CheckerParamsBase class TestCheckerParamsBase(unittest.TestCase): """ Tests of the base of all our checker parameters. """ def setUp(self) -> None: """ Setups everything we need. """ self.params = CheckerParamsBase() def tearDown(self) -> None: """ Destroyes everything we don't need. """ del self.params def test_to_dict(self) -> None: """ Tests the method which let us get the :py:class:`dict` representation of the current parameters. """ self.params.do_syntax_check_first = True self.params.use_platform = False expected = {"do_syntax_check_first": True, "use_platform": False} actual = self.params.to_dict() self.assertEqual(expected, actual) def test_to_json(self) -> None: """ Tests the method which let us get the JSON representation of the current parameters. """ self.params.do_syntax_check_first = True self.params.use_platform = False expected = """{ "do_syntax_check_first": true, "use_platform": false }""" actual = self.params.to_json() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/test_status_base.py000066400000000000000000000111361467462152100231270ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the base of all our status handlers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from datetime import datetime, timezone from PyFunceble.checker.status_base import CheckerStatusBase try: import pyf_test_helpers except ModuleNotFoundError: from .. import pyf_test_helpers class TestCheckerStatusBase(unittest.TestCase): """ Tests of the base of all our status handler. """ def setUp(self) -> None: """ Setups everything we need. """ self.status = CheckerStatusBase( subject="example.org", idna_subject="example.org", netloc="example.org" ) def tearDown(self) -> None: """ Destroyes everything we don't need. """ del self.status def test_to_dict(self) -> None: """ Tests of the method which gives us the :py:class:`dict` representation of the current status object. """ test_datetime = datetime.now(timezone.utc) self.status.status = "ACTIVE" self.status.status_source = "Funilrys" self.status.tested_at = test_datetime expected = { "subject": "example.org", "subject_kind": None, "idna_subject": "example.org", "netloc": "example.org", "status": "ACTIVE", "status_source": "Funilrys", "tested_at": test_datetime, "params": None, } actual = self.status.to_dict() self.assertEqual(expected, actual) def test_to_json(self) -> None: """ Tests the method which let us get the JSON representation of the current status object. """ test_datetime = datetime.fromtimestamp(0, tz=pyf_test_helpers.get_timezone()) self.status.status = "ACTIVE" self.status.status_source = "Funilrys" self.status.tested_at = test_datetime expected = """{ "idna_subject": "example.org", "netloc": "example.org", "params": null, "status": "ACTIVE", "status_source": "Funilrys", "subject": "example.org", "subject_kind": null, "tested_at": "1970-01-01T00:00:00+00:00" }""" actual = self.status.to_json() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/checker/utils/000077500000000000000000000000001467462152100203375ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/checker/utils/__init__.py000066400000000000000000000000001467462152100224360ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/checker/utils/test_whois.py000066400000000000000000000131671467462152100231110ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our checker WHOIS utilities. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.checker.utils import whois from PyFunceble.config.loader import ConfigLoader from PyFunceble.dataset.whois.csv import CSVWhoisDataset from PyFunceble.dataset.whois.sql import SQLDBWhoisDataset # pylint: disable=unnecessary-lambda class TestCheckerWhoisUtils(unittest.TestCase): """ Tests of the WHOIS utilities. """ def setUp(self) -> None: """ Setup everything needed for the tests. """ self.config_loader = ConfigLoader() def tearDown(self) -> None: """ Destroys everything needed for the tests. """ del self.config_loader def test_get_whois_dataset_obj_no_config(self) -> None: """ Tests of the function which let us get a new WHOIS dataset object. """ self.assertRaises(RuntimeError, lambda: whois.get_whois_dataset_object()) def test_get_whois_dataset_obj_csv(self) -> None: """ Tests of the function which let us get a new WHOIS dataset object. In this case, we check the case that the CSV was declared. """ self.config_loader.set_custom_config( {"cli_testing": {"db_type": "csv"}} ).start() expected = CSVWhoisDataset actual = whois.get_whois_dataset_object() self.assertIsInstance(actual, expected) def test_get_whois_dataset_obj_mariadb(self) -> None: """ Tests of the function which let us get a new WHOIS dataset object. In this case, we check the case that the MariaDb was declared. """ self.config_loader.set_custom_config( {"cli_testing": {"db_type": "mariadb"}} ).start() expected = SQLDBWhoisDataset actual = whois.get_whois_dataset_object() self.assertIsInstance(actual, expected) def test_get_whois_dataset_obj_mysql(self) -> None: """ Tests of the function which let us get a new WHOIS dataset object. In this case, we check the case that the MySQL was declared. """ self.config_loader.set_custom_config( {"cli_testing": {"db_type": "mysql"}} ).start() expected = SQLDBWhoisDataset actual = whois.get_whois_dataset_object() self.assertIsInstance(actual, expected) def test_get_whois_dataset_obj_postgresql(self) -> None: """ Tests of the function which let us get a new WHOIS dataset object. In this case, we check the case that the PostgreSQL was declared. """ self.config_loader.set_custom_config( {"cli_testing": {"db_type": "postgresql"}} ).start() expected = SQLDBWhoisDataset actual = whois.get_whois_dataset_object() self.assertIsInstance(actual, expected) def test_get_whois_dataset_obj_unknown(self) -> None: """ Tests of the function which let us get a new WHOIS dataset object. In this case, we check the case that an unknown db type was declared. """ self.config_loader.set_custom_config( {"cli_testing": {"db_type": "hello"}} ).start() self.assertRaises(ValueError, lambda: whois.get_whois_dataset_object()) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/config/000077500000000000000000000000001467462152100170405ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/config/__init__.py000066400000000000000000000000001467462152100211370ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/config/test_compare.py000066400000000000000000000476431467462152100221150ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our configuration comparison tool. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy import unittest from PyFunceble.config.compare import ConfigComparison try: import pyf_test_dataset except ModuleNotFoundError: # pragma: no cover from .. import pyf_test_dataset class TestConfigCompare(unittest.TestCase): """ Tests our configuration comparison tool. """ def setUp(self) -> None: """ Setups everything needed by the tests. """ self.our_config = copy.deepcopy(pyf_test_dataset.DEFAULT_CONFIG) def tearDown(self) -> None: """ Destroys everything initiated by the tests. """ del self.our_config def test_set_local_config_return(self) -> None: """ Tests the response of the method which let us set the local configuration to work with. """ given = self.our_config config_comparison = ConfigComparison() actual = config_comparison.set_local_config(given) self.assertIsInstance(actual, ConfigComparison) def test_set_local_config_method(self) -> None: """ Tests the method which let us set the local configuration to work with. """ given = self.our_config expected = self.our_config config_comparison = ConfigComparison() config_comparison.set_local_config(given) actual = config_comparison.local_config self.assertEqual(expected, actual) def test_set_local_config_attribute(self) -> None: """ Tests the method which let us set the local configuraiton to work with. In this case, we try to overwrite the attribute. """ given = self.our_config expected = self.our_config config_comparison = ConfigComparison() config_comparison.local_config = given actual = config_comparison.local_config self.assertEqual(expected, actual) def test_set_local_config_through_init(self) -> None: """ Tests the method which let us set the local configuraiton to work with. In this case, we try to overwrite the attribute through the constructor. """ given = self.our_config expected = self.our_config config_comparison = ConfigComparison(local_config=given) actual = config_comparison.local_config self.assertEqual(expected, actual) def test_set_local_config_not_dict(self) -> None: """ Tests the method which let us set the local configuration to work with for the case that the given local configuration is not a dict. """ given = ["Hello", "World"] config_comparison = ConfigComparison() self.assertRaises(TypeError, lambda: config_comparison.set_local_config(given)) def test_set_upstream_config_return(self) -> None: """ Tests the response of the method which let us set the upstream configuration to work with. """ given = copy.deepcopy(self.our_config) config_comparison = ConfigComparison() actual = config_comparison.set_upstream_config(given) self.assertIsInstance(actual, ConfigComparison) def test_set_upstream_config_method(self) -> None: """ Tests the method which let us set the upstream configuration to work with. """ given = self.our_config expected = self.our_config config_comparison = ConfigComparison() config_comparison.set_upstream_config(given) actual = config_comparison.upstream_config self.assertEqual(expected, actual) def test_set_upstream_config_attribute(self) -> None: """ Tests the method which let us set the upstream configuraiton to work with. In this case, we try to overwrite the attribute. """ given = self.our_config expected = self.our_config config_comparison = ConfigComparison() config_comparison.upstream_config = given actual = config_comparison.upstream_config self.assertEqual(expected, actual) def test_set_upstream_config_through_init(self) -> None: """ Tests the method which let us set the upstream configuraiton to work with. In this case, we try to overwrite the attribute through the constructor. """ given = self.our_config expected = self.our_config config_comparison = ConfigComparison(upstream_config=given) actual = config_comparison.upstream_config self.assertEqual(expected, actual) def test_set_upstream_config_not_dict(self) -> None: """ Tests the method which let us set the upstream configuration to work with for the case that the given upstream configuration is not a dict. """ given = ["Hello", "World"] config_comparison = ConfigComparison() self.assertRaises( TypeError, lambda: config_comparison.set_upstream_config(given) ) def test_is_local_identical(self) -> None: """ Tests the method which let us check if the given local configuration is identical to the upstream one. """ given_local = copy.deepcopy(self.our_config) given_upstream = copy.deepcopy(self.our_config) config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = True actual = config_comparison.is_local_identical() self.assertEqual(expected, actual) def test_is_local_identical_missing_key(self) -> None: """ Tests the method which let us check if the given local configuration is identical to the upstream one for the case that a key is missing. """ given_upstream = copy.deepcopy(self.our_config) to_delete = ["links", "http_codes", "user_agent"] for index in to_delete: given_local = copy.deepcopy(self.our_config) del given_local[index] config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = False actual = config_comparison.is_local_identical() self.assertEqual(expected, actual) def test_is_local_identical_uneeded_links_key(self) -> None: """ Tests the method which let us check if the given local configuration is identical to the upstream one for the case that a unneeded key inside the list of links is given. """ given_upstream = copy.deepcopy(self.our_config) given_local = copy.deepcopy(self.our_config) given_local["links"].update( { "config": "https://example.org/PyFunceble_config.yaml", "iana": "https://example.org/iana-db.json", } ) config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = False actual = config_comparison.is_local_identical() self.assertEqual(expected, actual) def test_get_merged_no_changed(self) -> None: """ Tests the method which let us get the (clean) merged configuration. """ given_local = copy.deepcopy(self.our_config) given_upstream = copy.deepcopy(self.our_config) config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = self.our_config actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_key_renamed(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that we renamed some keys. """ old2new = { "hello_world": "cli_testing", } given_local = copy.deepcopy(self.our_config) given_upstream = copy.deepcopy(self.our_config) for old, new in old2new.items(): given_local[old] = copy.deepcopy(given_local[new]) del given_local[new] config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = self.our_config expected["hello_world"] = self.our_config["cli_testing"] actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_undeeded_links(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that we have some uneeded links. """ uneeded_links = { "config": "https://example.org/PyFunceble_config.yaml", "iana": "https://example.org/iana-db.json", } given_local = copy.deepcopy(self.our_config) given_upstream = copy.deepcopy(self.our_config) given_local["links"].update(uneeded_links) config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = self.our_config actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_wrong_user_agent(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that we still have the old user agent format. """ given_local = copy.deepcopy(self.our_config) given_upstream = copy.deepcopy(self.our_config) given_local["user_agent"] = "Hello, World!" config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = self.our_config actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_3_x_http_codes(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that we still have some of the old http_codes indexes. """ given_local = copy.deepcopy(self.our_config) given_upstream = copy.deepcopy(self.our_config) given_local["http_codes"]["active"] = True given_local["http_codes"]["not_found_default"] = "XXXX" config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = self.our_config actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_3_x_dns_over_tcp(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that we still have the old dns_over_tcp index. """ given_local = copy.deepcopy(self.our_config) given_upstream = copy.deepcopy(self.our_config) given_local["dns_lookup_over_tcp"] = True config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = self.our_config expected["dns"]["protocol"] = "TCP" actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_3_x_cooldown_time(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that we still have the old cooldown_time index. """ given_local = copy.deepcopy(self.our_config) given_upstream = copy.deepcopy(self.our_config) # Just to trigger the merge. given_local["http_codes"]["not_found_default"] = "XXXX" given_local["cli_testing"]["cooldown_time"] = None config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = self.our_config actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_3_x_json2csv(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that we still have the old db type index. """ given_local = copy.deepcopy(self.our_config) given_upstream = copy.deepcopy(self.our_config) # Just to trigger the merge. given_local["http_codes"]["not_found_default"] = "XXXX" given_local["cli_testing"]["db_type"] = "json" config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = self.our_config actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_3_x_old_to_new(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that we want to convert old keys to the new layout. """ given_local = copy.deepcopy(self.our_config) given_upstream = copy.deepcopy(self.our_config) # Just to trigger the merge. given_local["http_codes"]["not_found_default"] = "XXXX" given_local["adblock"] = True config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = self.our_config expected["cli_decoding"]["adblock"] = True actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_3_x_old_to_new_nagated(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that we want to convert old keys to the new layout. """ given_local = copy.deepcopy(self.our_config) given_upstream = copy.deepcopy(self.our_config) # Just to trigger the merge. given_local["http_codes"]["not_found_default"] = "XXXX" given_local["no_special"] = True config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = self.our_config expected["lookup"]["special"] = False actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_http_code_not_self_managed(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that the end-user is not managing the status code. """ given_local = copy.deepcopy(self.our_config) given_upstream = copy.deepcopy(self.our_config) # Just to trigger the merge. given_local["http_codes"]["list"]["up"] = copy.deepcopy( self.our_config["http_codes"]["list"]["up"] ) # Assume end-user added this before getting away from self management. given_local["http_codes"]["list"]["up"].append(403) config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = self.our_config actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_empty_local(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that the given local configuration is empty -- which should never happens. """ given_local = dict() # pylint: disable=use-dict-literal given_upstream = copy.deepcopy(self.our_config) config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) expected = self.our_config actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_nested_old2new(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that one of the given migration path is nested. """ given_local = { "cli_decoding": {"aggressive_test": False} } # pylint: disable=use-dict-literal given_upstream = copy.deepcopy(self.our_config) given_upstream["cli_decoding"]["aggressive_world"] = True config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) config_comparison.OLD_TO_NEW = { "cli_decoding.aggressive_test": "cli_decoding.aggressive_world" } config_comparison.OLD_TO_NEW_NEGATE = {} expected = self.our_config expected["cli_decoding"]["aggressive_world"] = False actual = config_comparison.get_merged() self.assertEqual(expected, actual) def test_get_merged_nested_old2newnegate(self) -> None: """ Tests the method which let us get the (clean) merged configuration for the case that one of the given migration path is nested and negated. """ given_local = { "cli_decoding": {"aggressive_test": False} } # pylint: disable=use-dict-literal given_upstream = copy.deepcopy(self.our_config) given_upstream["cli_decoding"]["aggressive_world"] = True config_comparison = ConfigComparison( local_config=given_local, upstream_config=given_upstream ) config_comparison.OLD_TO_NEW = {} config_comparison.OLD_TO_NEW_NEGATE = { "cli_decoding.aggressive_test": "cli_decoding.aggressive_world" } expected = self.our_config expected["cli_decoding"]["aggressive_world"] = True actual = config_comparison.get_merged() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/config/test_loader.py000066400000000000000000000505671467462152100217340ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our configuration loader. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 copy import os import tempfile import unittest import yaml from box import Box from PyFunceble.config.loader import ConfigLoader try: import pyf_test_dataset except ModuleNotFoundError: # pragma: no cover from .. import pyf_test_dataset import PyFunceble.storage class TestConfigLoader(unittest.TestCase): """ Provides the test of our configuration loader. """ def setUp(self) -> None: """ Setups everything needed by the tests. """ self.our_config = Box(copy.deepcopy(pyf_test_dataset.DEFAULT_CONFIG)) self.default_config_file = tempfile.NamedTemporaryFile(delete=False) self.overwrite_config_file = tempfile.NamedTemporaryFile(delete=False) self.config_file = tempfile.NamedTemporaryFile(delete=False) self.merge_upstream = False self.config_loader = ConfigLoader() self.config_loader.merge_upstream = self.merge_upstream self.config_loader.path_to_default_config = self.default_config_file.name self.config_loader.path_to_overwrite_config = self.overwrite_config_file.name self.config_loader.path_to_config = self.config_file.name def tearDown(self) -> None: """ Destroys everything initiated by the tests. """ self.config_file.close() self.default_config_file.close() self.overwrite_config_file.close() os.unlink(self.config_file.name) os.unlink(self.default_config_file.name) os.unlink(self.overwrite_config_file.name) del self.our_config del self.default_config_file del self.config_file del self.merge_upstream del self.config_loader def test_is_already_loader(self) -> None: """ Tests the method which let us know if the configuration was already loaded. """ PyFunceble.storage.CONFIGURATION = self.our_config expected = True actual = self.config_loader.is_already_loaded() self.assertEqual(expected, actual) def test_is_not_already_loaded(self) -> None: """ Tests the method which let us know if the configuration was already loaded for the case that it was not loaded yet. """ expected = False actual = self.config_loader.is_already_loaded() self.assertEqual(expected, actual) def test_set_custom_config(self) -> None: """ Tests the method which let us set the custom configuration to work with. """ given = {"hello": "world"} expected = {"hello": "world"} self.config_loader.custom_config = given actual = self.config_loader.custom_config self.assertEqual(expected, actual) def test_set_custom_config_config_already_loaded(self) -> None: """ Tests the method which let us set the custom configuration to work with. In this case, we want the loader to reload (itself). So we basically tests that the reload occurs. """ self.default_config_file.write(yaml.dump(self.our_config.to_dict()).encode()) self.default_config_file.seek(0) self.config_file.write(yaml.dump(self.our_config).encode()) self.config_file.seek(0) PyFunceble.storage.CONFIGURATION = self.our_config given = {"hello": "world"} expected = {"hello": "world"} self.config_loader.custom_config = given actual = self.config_loader.custom_config self.assertEqual(expected, actual) expected = "world" actual = PyFunceble.storage.CONFIGURATION["hello"] self.assertEqual(expected, actual) def test_set_custom_config_config_already_loaded_merging_active(self) -> None: """ Tests the method which let us set the custom configuration to work with. In this case, we want the loader to reload (itself). So we basically tests that the reload occurs. And that nothing has changed if the merging is authorized """ self.default_config_file.write(yaml.dump(self.our_config.to_dict()).encode()) self.default_config_file.seek(0) self.config_file.write(yaml.dump(self.our_config).encode()) self.config_file.seek(0) self.config_loader.merge_upstream = True PyFunceble.storage.CONFIGURATION = copy.deepcopy(self.our_config) PyFunceble.storage.CONFIGURATION["cli_testing"]["display_mode"]["dots"] = True given = {"hello": "world"} expected = {"hello": "world"} self.config_loader.custom_config = given actual = self.config_loader.custom_config self.assertEqual(expected, actual) expected = "world" actual = PyFunceble.storage.CONFIGURATION["hello"] self.assertEqual(expected, actual) self.config_file.seek(0) expected = copy.deepcopy(self.our_config.to_dict()) actual = yaml.safe_load(self.config_file) self.assertEqual(expected, actual) def test_set_custom_config_not_dict(self) -> None: """ Tests the method which let us set the custom configuration to work with for the case that the given custom configuration is not a :py:class:`dict`. """ given = "Hello, World!" self.assertRaises( TypeError, lambda: self.config_loader.set_custom_config(given) ) def test_set_custom_config_previously_given(self) -> None: """ Tests the method which let us set the custom configuration to work with for the case that the given custom configuration is not a :py:class:`dict`. """ given = {"Hello": "World!"} given2 = {"World!": "Hello"} self.config_loader.set_custom_config(given) self.config_loader.set_custom_config(given2) expected = {"Hello": "World!", "World!": "Hello"} actual = self.config_loader.custom_config self.assertEqual(expected, actual) def test_set_merge_upstream(self) -> None: """ Tests the method which let us authorize the merging of upstream inside the local one. """ given = True expected = True self.config_loader.merge_upstream = given actual = self.config_loader.merge_upstream self.assertEqual(expected, actual) def test_set_merge_upstream_return(self) -> None: """ Tests the method which let us authorize the merging of upstream inside the local one. In this case, we just want to be sure that the response is correct. """ given = True actual = self.config_loader.set_merge_upstream(given) self.assertIsInstance(actual, ConfigLoader) def test_set_merge_upstream_not_bool(self) -> None: """ Tests the method which let us authorize the merging of upstream inside the local one for the case that the given value is not a boolean. """ given = "Hello, World!" self.assertRaises( TypeError, lambda: self.config_loader.set_merge_upstream(given), ) def test_get_config_file_content(self) -> None: """ Tests the method which let us get the content of the configuration file. """ self.config_file.write(yaml.dump(self.our_config.to_dict()).encode()) self.config_file.seek(0) expected = self.our_config.to_dict() actual = self.config_loader.get_config_file_content() self.assertEqual(expected, actual) def test_get_config_file_content_yaml_issue(self) -> None: """ Tests the method which let us get the content of the configuration file. This case try to reproduce the issue we met because of my inattention. """ self.default_config_file.write(yaml.dump(self.our_config.to_dict()).encode()) self.default_config_file.seek(0) self.config_file.write(yaml.dump(self.our_config).encode()) self.config_file.seek(0) expected = self.our_config.to_dict() actual = self.config_loader.get_config_file_content() self.assertEqual(expected, actual) def test_get_config_file_already_exists(self) -> None: """ Tests the method which let us get the content of the configuration file for the case that the configuration was already loaded. """ self.config_file.write(yaml.dump(self.our_config.to_dict()).encode()) self.config_file.seek(0) PyFunceble.storage.CONFIGURATION = Box({"hello": "world"}) expected = self.our_config.to_dict() actual = self.config_loader.get_config_file_content() self.assertEqual(expected, actual) def test_get_config_file_but_empty(self) -> None: """ Tests the method which let us get the content of the configuration file for the case it is empty. """ self.default_config_file.write(yaml.dump(self.our_config.to_dict()).encode()) self.default_config_file.seek(0) self.config_file.write("".encode()) self.config_file.seek(0) expected = self.our_config actual = self.config_loader.get_config_file_content() self.assertEqual(expected, actual) def test_get_configured_value_not_loaded(self) -> None: """ Tests the method which let us get the configured value. In this test, we check for the case that configuration is not loaded yet. """ given = "cli_testing.display_mode.colour" self.assertRaises( RuntimeError, lambda: self.config_loader.get_configured_value(given) ) def test_get_configured_value_not_found(self) -> None: """ Tests the method which let us get the configured value. In this test, we check for the case that the wanted index does not exists. """ PyFunceble.storage.CONFIGURATION = self.our_config given = "hello_world_hello" self.assertRaises( ValueError, lambda: self.config_loader.get_configured_value(given) ) def test_get_configured_value(self) -> None: """ Tests the method which let us get the configured value. In this test, we check for the case that configuration is not loaded yet. """ self.config_loader.set_custom_config(self.our_config).start() given = "cli_testing.testing_mode.syntax" actual = self.config_loader.get_configured_value(given) self.assertIsInstance(actual, bool) def test_start_and_destroy(self) -> None: """ Tests the methods which loads, put everything together and destroy the configuration. """ self.config_file.write(yaml.dump(self.our_config.to_dict()).encode()) self.config_file.seek(0) given_custom = {"this_is_a_custom": "test"} self.config_loader.set_custom_config(given_custom) response = self.config_loader.start() self.assertIsInstance(response, ConfigLoader) expected_with_custom = dict( copy.deepcopy(self.our_config.to_dict()), **given_custom ) self.assertEqual( expected_with_custom, PyFunceble.storage.CONFIGURATION, ) expected_indexes = ["http_codes", "links"] for index in expected_indexes: # Tests if correctly stored. expected = copy.deepcopy(self.our_config[index]) actual = getattr(PyFunceble.storage, index.upper()) self.assertEqual(expected, actual) response = self.config_loader.destroy() self.assertIsInstance(response, ConfigLoader) expected_custom = dict() # pylint: disable=use-dict-literal actual = self.config_loader.custom_config self.assertEqual(expected_custom, actual) expected_indexes = ["http_codes", "links"] expected = dict() # pylint: disable=use-dict-literal for index in expected_indexes: actual = getattr(PyFunceble.storage, index.upper()) self.assertEqual(expected, actual) def test_conditional_switch_autocontinue_ci_active(self) -> None: """ Tests the method which let us switch some of our values based on some assumption. In this test, we check the the autocontinue is getting activated if we are under CI. """ given = copy.deepcopy(self.our_config) given["cli_testing"]["ci"]["active"] = True given["cli_testing"]["autocontinue"] = False expected = copy.deepcopy(given) expected["cli_testing"]["autocontinue"] = True actual = self.config_loader.conditional_switch(given) self.assertEqual(expected, actual) def test_conditional_switch_autocontinue_ci_not_active(self) -> None: """ Tests the method which let us switch some of our values based on some assumption. In this test, we check the the autocontinue is getting activated if we are under CI. """ given = copy.deepcopy(self.our_config) given["cli_testing"]["ci"]["active"] = False given["cli_testing"]["autocontinue"] = False expected = copy.deepcopy(given) actual = self.config_loader.conditional_switch(given) self.assertEqual(expected, actual) def test_conditional_switch_lookup_timeout_less_than_zero(self) -> None: """ Tests the method which let us switch some of our values based on some assumption. In this test, we check the the lookup timeout is getting switched to 5 when the given value is lower than 0. """ given = copy.deepcopy(self.our_config) given["lookup"]["timeout"] = -1.34 expected = copy.deepcopy(given) expected["lookup"]["timeout"] = 5 actual = self.config_loader.conditional_switch(given) self.assertEqual(expected, actual) def test_conditional_switch_platform_testing_mode(self) -> None: """ Tests the method which let us switch some of our values based on some assumption. In this test, we check that no files is being generated if we are under such testing mode. """ given = copy.deepcopy(self.our_config) given["cli_testing"]["testing_mode"]["platform_contribution"] = True given["cli_testing"]["file_generation"]["no_file"] = False given["cli_testing"]["display_mode"]["dots"] = False given["cli_testing"]["autocontinue"] = True given["cli_testing"]["inactive_db"] = True given["cli_testing"]["mining"] = True given["cli_testing"]["local_network"] = True given["cli_testing"]["preload_file"] = True given["cli_testing"]["display_mode"]["percentage"] = True expected = copy.deepcopy(given) expected["cli_testing"]["file_generation"]["no_file"] = True expected["cli_testing"]["file_generation"]["no_file"] = True expected["cli_testing"]["display_mode"]["dots"] = True expected["cli_testing"]["autocontinue"] = False expected["cli_testing"]["inactive_db"] = False expected["cli_testing"]["mining"] = False expected["cli_testing"]["local_network"] = False expected["cli_testing"]["preload_file"] = False expected["cli_testing"]["display_mode"]["percentage"] = False actual = self.config_loader.conditional_switch(given) self.assertEqual(expected, actual) def test_overwite_file_found(self) -> None: """ Tests the loading of the configuration file for the case the an overwrite file is given. """ given = {"Hello": "World!"} self.overwrite_config_file.write(yaml.dump(given).encode()) self.overwrite_config_file.seek(0) self.config_file.write(yaml.dump(self.our_config.to_dict()).encode()) self.config_file.seek(0) response = self.config_loader.start() self.assertIsInstance(response, ConfigLoader) expected_with_overwrite = dict( copy.deepcopy(self.our_config.to_dict()), **given ) self.assertEqual( expected_with_overwrite, PyFunceble.storage.CONFIGURATION, ) self.assertTrue("Hello" in PyFunceble.storage.CONFIGURATION) def test_overwite_file_found_but_empty(self) -> None: """ Tests the loading of the configuration file for the case the an overwrite file is given but is empty. """ given = {} self.overwrite_config_file.write(yaml.dump(given).encode()) self.overwrite_config_file.seek(0) self.config_file.write(yaml.dump(self.our_config.to_dict()).encode()) self.config_file.seek(0) response = self.config_loader.start() self.assertIsInstance(response, ConfigLoader) expected = self.our_config.to_dict() self.assertEqual( expected, PyFunceble.storage.CONFIGURATION, ) def test_overwite_file_found_but_overwrote_by_custom(self) -> None: """ Tests the loading of the configuration file for the case the an overwrite file is given, but the custom configuration is also given. When the custom configuration is given, it overwrites everything, including the overwrites file. """ given = {"Hello": "World"} self.overwrite_config_file.write(yaml.dump(given).encode()) self.overwrite_config_file.seek(0) given_custom = {"Hello": "Funilrys!"} self.config_loader.set_custom_config(given_custom) self.config_file.write(yaml.dump(self.our_config.to_dict()).encode()) self.config_file.seek(0) response = self.config_loader.start() self.assertIsInstance(response, ConfigLoader) expected_with_custom = dict( copy.deepcopy(self.our_config.to_dict()), **given_custom ) self.assertEqual( expected_with_custom, PyFunceble.storage.CONFIGURATION, ) self.assertTrue(PyFunceble.storage.CONFIGURATION["Hello"] == "Funilrys!") if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/converter/000077500000000000000000000000001467462152100176025ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/converter/__init__.py000066400000000000000000000000001467462152100217010ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/converter/test_adblock_input_line2subject.py000066400000000000000000000360741467462152100265140ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our adblock 2 subject converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from typing import List from PyFunceble.converter.adblock_input_line2subject import AdblockInputLine2Subject from PyFunceble.helpers.regex import RegexHelper class TestAdblockInputLine2Subject(unittest.TestCase): """ Tests our adblock 2 subject converter. """ EXTENDED_TEST_SUBJECT: List[dict] = [ { "subject": '##[href^="https://funceble.funilrys.com/"]', "expected": { "aggressive": ["funceble.funilrys.com"], "standard": [], }, }, { "subject": "||test.hello.world^$domain=hello.world", "expected": { "aggressive": ["hello.world", "test.hello.world"], "standard": ["test.hello.world"], }, }, { "subject": '##div[href^="http://funilrys.com/"]', "expected": {"aggressive": ["funilrys.com"], "standard": []}, }, { "subject": 'com##[href^="ftp://funceble.funilrys-funceble.com/"]', "expected": { "aggressive": ["funceble.funilrys-funceble.com"], "standard": [], }, }, { "subject": "!@@||funceble.world/js", "expected": {"aggressive": [], "standard": []}, }, { "subject": "!||world.hello/*ad.xml", "expected": {"aggressive": [], "standard": []}, }, { "subject": "!funilrys.com##body", "expected": {"aggressive": [], "standard": []}, }, { "subject": "[AdBlock Plus 2.0]", "expected": {"aggressive": [], "standard": []}, }, { "subject": "@@||ads.example.com/notbanner^$~script", "expected": {"aggressive": ["ads.example.com"], "standard": []}, }, {"subject": "/banner/*/img^", "expected": {"aggressive": [], "standard": []}}, { "subject": "||ad.example.co.uk^", "expected": { "aggressive": ["ad.example.co.uk"], "standard": ["ad.example.co.uk"], }, }, { "subject": "||ad.example.fr^$image,test", "expected": { "aggressive": ["ad.example.fr"], "standard": ["ad.example.fr"], }, }, { "subject": "||api.funilrys.com/widget/$", "expected": { "aggressive": ["api.funilrys.com"], "standard": ["api.funilrys.com"], }, }, { "subject": "||api.example.com/papi/action$popup", "expected": { "aggressive": ["api.example.com"], "standard": ["api.example.com"], }, }, { "subject": "||funilrys.github.io$script,image", "expected": { "aggressive": ["funilrys.github.io"], "standard": ["funilrys.github.io"], }, }, { "subject": "||example.net^$script,image", "expected": {"aggressive": ["example.net"], "standard": ["example.net"]}, }, { "subject": "||static.hello.world.examoke.org/*/exit-banner.js", "expected": { "aggressive": ["static.hello.world.examoke.org"], "standard": ["static.hello.world.examoke.org"], }, }, { "subject": "$domain=exam.pl|elpmaxe.pl|example.pl", "expected": { "aggressive": ["elpmaxe.pl", "exam.pl", "example.pl"], "standard": [], }, }, { "subject": "||example.de^helloworld.com", "expected": { "aggressive": ["example.de"], "standard": ["example.de"], }, }, { "subject": "|github.io|", "expected": {"aggressive": ["github.io"], "standard": ["github.io"]}, }, { "subject": "~github.com,hello.world##.wrapper", "expected": {"aggressive": ["github.com", "hello.world"], "standard": []}, }, { "subject": "bing.com,bingo.com#@##adBanner", "expected": {"aggressive": ["bing.com", "bingo.com"], "standard": []}, }, { "subject": "example.org#@##test", "expected": {"aggressive": ["example.org"], "standard": []}, }, { "subject": "hubgit.com|oohay.com|ipa.elloh.dlorw#@#awesomeWorld", "expected": { "aggressive": ["hubgit.com|oohay.com|ipa.elloh.dlorw"], "standard": [], }, }, {"subject": ".com", "expected": {"aggressive": [], "standard": []}}, { "subject": "||ggggggggggg.gq^$all", "expected": { "aggressive": ["ggggggggggg.gq"], "standard": ["ggggggggggg.gq"], }, }, { "subject": "facebook.com##.search", "expected": {"aggressive": ["facebook.com"], "standard": []}, }, { "subject": "||test.hello.world^$domain=hello.world", "expected": { "aggressive": ["hello.world", "test.hello.world"], "standard": ["test.hello.world"], }, }, { "subject": "||examplae.com", "expected": {"aggressive": ["examplae.com"], "standard": ["examplae.com"]}, }, { "subject": "||examplbe.com^", "expected": {"aggressive": ["examplbe.com"], "standard": ["examplbe.com"]}, }, { "subject": "||examplce.com$third-party", "expected": {"aggressive": ["examplce.com"], "standard": ["examplce.com"]}, }, { "subject": "||examplde.com^$third-party", "expected": {"aggressive": ["examplde.com"], "standard": ["examplde.com"]}, }, { "subject": '##[href^="https://examplee.com/"]', "expected": {"aggressive": ["examplee.com"], "standard": []}, }, { "subject": "||examplfe.com^examplge.com", "expected": {"aggressive": ["examplfe.com"], "standard": ["examplfe.com"]}, }, { "subject": "||examplhe.com$script,image", "expected": {"aggressive": ["examplhe.com"], "standard": ["examplhe.com"]}, }, { "subject": "||examplie.com^$domain=domain1.com|domain2.com", "expected": { "aggressive": [ "domain1.com", "domain2.com", "examplie.com", ], "standard": ["examplie.com"], }, }, { "subject": 'examlple.com##[href^="http://hello.world."], ' '[href^="http://example.net/"]', "expected": { "aggressive": ["examlple.com", "example.net", "hello.world."], "standard": [], }, }, {"subject": "##.ad-href1", "expected": {"aggressive": [], "standard": []}}, { "subject": "^hello^$domain=example.com", "expected": {"standard": [], "aggressive": ["example.com"]}, }, { "subject": "hello$domain=example.net|example.com", "expected": {"standard": [], "aggressive": ["example.com", "example.net"]}, }, { "subject": "hello^$domain=example.org|example.com|example.net", "expected": { "standard": [], "aggressive": ["example.com", "example.net", "example.org"], }, }, ] def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = AdblockInputLine2Subject() def tearDown(self) -> None: """ Destroys everything previously created for the tests. """ del self.converter def test_init_with_helper(self) -> None: """ Tests the initialization with our own helpers. """ regex_helper = RegexHelper() self.converter = AdblockInputLine2Subject(regex_helper=regex_helper) # pylint: disable=protected-access self.assertIsInstance(self.converter._regex_helper, RegexHelper) self.assertEqual(id(regex_helper), id(self.converter._regex_helper)) def test_set_data_to_convert_no_string(self) -> None: """ Tests the method which let us set the data to work with for the case that a non-string value is given. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_data_to_convert(given)) def test_set_aggressive_return(self) -> None: """ Tests the response from the method which let us activate the aggressive mode. """ given = True actual = self.converter.set_aggressive(given) self.assertIsInstance(actual, AdblockInputLine2Subject) def test_set_aggressive_method(self) -> None: """ Tests the method which let us set activate the aggressive mode. """ given = True expected = True self.converter.set_aggressive(given) actual = self.converter.aggressive self.assertEqual(expected, actual) def test_set_aggressive_attribute(self) -> None: """ Tests overwritting of the :code:`aggressive` attribute. """ given = True expected = True self.converter.aggressive = given actual = self.converter.aggressive self.assertEqual(expected, actual) def test_set_aggressive_through_init(self) -> None: """ Tests the activation of the aggressive mode through the class constructor. """ given = True expected = True converter = AdblockInputLine2Subject(aggressive=given) actual = converter.aggressive self.assertEqual(expected, actual) def test_set_aggressive_not_bool(self) -> None: """ Tests the response from the method which let us set the activate the aggressive mode for the case that the given value is not a bool. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_aggressive(given)) def test_get_converted(self) -> None: """ Tests the method which let us get the converted data. """ for test_dataset in self.EXTENDED_TEST_SUBJECT: given = test_dataset["subject"] expected_std = test_dataset["expected"]["standard"] expected_aggressive = test_dataset["expected"]["aggressive"] self.converter.data_to_convert = given self.converter.aggressive = True actual = self.converter.get_converted() self.assertEqual( expected_aggressive, actual, f"Aggressive: {self.converter.aggressive} | {given}", ) self.converter.aggressive = False actual = self.converter.get_converted() self.assertEqual( expected_std, actual, f"Aggressive: {self.converter.aggressive} | {given}", ) def test_convert(self) -> None: """ Tests the method which let us convert some data. """ for test_dataset in self.EXTENDED_TEST_SUBJECT: given = test_dataset["subject"] expected_std = test_dataset["expected"]["standard"] expected_aggressive = test_dataset["expected"]["aggressive"] actual = self.converter.convert(given, aggressive=True) self.assertEqual( expected_aggressive, actual, f"Aggressive: yes | {given}", ) actual = self.converter.convert(given, aggressive=False) self.assertEqual( expected_std, actual, f"Aggressive: No | {given}", ) def test_extract_base(self) -> None: """ Tests the method which let us get the base fo a given URL (or dataset.) """ test_map = { "example.org": "example.org/?is=beautiful", "example.de": "://example.de/", "example.net": "example.net", } for expected, given in test_map.items(): actual = self.converter.extract_base(given) self.assertEqual(expected, actual) expected = "" given = "" actual = self.converter.extract_base(given) self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/converter/test_base.py000066400000000000000000000103331467462152100221250ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the base of all our converters. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.converter.base import ConverterBase class TestConverterBase(unittest.TestCase): """ Tests the base of all our converters. """ def setUp(self) -> None: """ Setups everything needed. """ self.converter = ConverterBase() def tearDown(self) -> None: """ Destroys everything that was needed. """ del self.converter def test_set_data_to_convert_return(self) -> None: """ Tests the response from the method which let us set the data to work with. """ given = "example.com" actual = self.converter.set_data_to_convert(given) self.assertIsInstance(actual, ConverterBase) def test_set_data_to_convert_method(self) -> None: """ Tests the method which let us set the data to work with. """ given = "example.com" expected = "example.com" self.converter.set_data_to_convert(given) actual = self.converter.data_to_convert self.assertEqual(expected, actual) def test_set_data_to_convert_attribute(self) -> None: """ Tests overwritting of the :code:`data_to_convert` attribute. """ given = "example.com" expected = "example.com" self.converter.data_to_convert = given actual = self.converter.data_to_convert self.assertEqual(expected, actual) def test_set_data_to_convert_through_init(self) -> None: """ Tests the overwritting of the data to work through the class constructor. """ given = "example.com" expected = "example.com" converter = ConverterBase(given) actual = converter.data_to_convert self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/converter/test_cidr2subject.py000066400000000000000000000142151467462152100236010ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our CIDR to subject converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from collections import Counter from PyFunceble.checker.syntax.ip import IPSyntaxChecker from PyFunceble.converter.cidr2subject import CIDR2Subject class TestCIDR2Subject(unittest.TestCase): """ Tests our CIDR 2 subject converter. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = CIDR2Subject() def tearDown(self) -> None: """ Destroys everything previously created for the tests. """ del self.converter def test_init_with_helper(self) -> None: """ Tests the initialization with our own helpers. """ ip_syntax_checker = IPSyntaxChecker() self.converter = CIDR2Subject(ip_syntax_checker=ip_syntax_checker) self.assertIsInstance(self.converter.ip_syntax_checker, IPSyntaxChecker) self.assertEqual(id(ip_syntax_checker), id(self.converter.ip_syntax_checker)) def test_set_data_to_convert_no_string(self) -> None: """ Tests the method which let us set the data to work with for the case that a non-string value is given. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_data_to_convert(given)) def test_get_converted_empty(self) -> None: """ Tests the method which let us get the converted data for the case that it's an empty string is given. """ given = "" expected = [] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted(self) -> None: """ Tests the method which let us get the converted data. """ given = "127.0.30.0/28" expected = [f"127.0.30.{x}" for x in range(0, 15 + 1)] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertTrue(Counter(expected) == Counter(actual)) def test_get_converted_not_cidr(self) -> None: """ Tests the method which let us get the converted data for the case that the given subject is not a CIDR address. """ given = "example.org" expected = ["example.org"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_not_cidr_bis(self) -> None: """ Tests the method which let us get the converted data for the case that the given subject is not a CIDR address (bis). """ given = "127.0.0.1" expected = ["127.0.0.1"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_not_correct(self) -> None: """ Tests the method which let us get the converted data for the case that the given subject is not a correct CIDR address. """ given = "127.0.0.0/3" expected = ["127.0.0.0/3"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_ipv6(self) -> None: """ Tests the method which let us get the converted data for the case that the given subject is an IPv6. In this case, we check that no conversion is actually made. """ given = "2001:4860:4860::/64" expected = ["2001:4860:4860::/64"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/converter/test_input_line2subject.py000066400000000000000000000210431467462152100250230ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the input line 2 subject converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.converter.input_line2subject import InputLine2Subject class TestInputLine2Subject(unittest.TestCase): """ Tests our input line 2 subject converter. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = InputLine2Subject() def tearDown(self) -> None: """ Destroys everything previously created for the tests. """ del self.converter def test_set_data_to_convert_no_string(self) -> None: """ Tests the method which let us set the data to work with for the case that a non-string value is given. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_data_to_convert(given)) def test_get_converted_simple_line(self) -> None: """ Tests the method which let us get the converted data for the case that a simple line is given. """ given = "example.org" expected = [given] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_comment(self) -> None: """ Tests the method which let us get the converted data for the case that a commented line is given. """ given = "# example.org" expected = list() # pylint: disable=use-list-literal self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_end_with_comment(self) -> None: """ Tests the method which let us get the converted data for the case that a comment at the end of a line is given. """ given = "example.org # Hello, World!" expected = ["example.org"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_hosts_line(self) -> None: """ Tests the method which let us get the converted data for the case that a hosts (file) line is given. """ given = "0.0.0.0 example.org" expected = ["example.org"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_hosts_line_multiple_subject(self) -> None: """ Tests the method which let us get the converted data for the case that a compressed hosts (file) line is given. """ given = "0.0.0.0 example.org example.net example.de example.co.uk" expected = ["example.org", "example.net", "example.de", "example.co.uk"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_hosts_line_spaces(self) -> None: """ Tests the method which let us get the converted data for the case that a hosts (file) line with spaces as separator is given. """ given = "0.0.0.0 example.org" expected = ["example.org"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_hosts_line_tab(self) -> None: """ Tests the method which let us get the converted data for the case that a hosts (file) line with tab as separator is given. """ given = "0.0.0.0\texample.org" expected = ["example.org"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_hosts_line_tabs(self) -> None: """ Tests the method which let us get the converted data for the case that a hosts (file) line with tabs as separator is given. """ given = "0.0.0.0\t\t\t\t\texample.org" expected = ["example.org"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_multiple_entries(self) -> None: """ Tests the method which let us get the converted data for the case that a line with multiple entries (not hosts file format) are given. """ given = "example.org example.net example.de example.co.uk" expected = ["example.org", "example.net", "example.de", "example.co.uk"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_rfc_6367(self) -> None: """ Tests the method which let us get the converted data for the case that a line with :code:`\032` as separator is given. """ given = "0.0.0.0\t\t\t\t\texample.org\\032example.net" expected = ["example.org", "example.net"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_startswith_exclamation_char_as_comment(self) -> None: """ Tests the method which let us get the converted data for the case that a line starts with the :code:`!` character. """ given = "! example.org" expected = [] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_exclamation_char_as_comment(self) -> None: """ Tests the method which let us get the converted data for the case that contains a :code:`!` character as comment separator. """ given = "example.org ! DO NOT VISIT" expected = ["example.org", "!", "DO", "NOT", "VISIT"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/converter/test_internal_url.py000066400000000000000000000130071467462152100237120ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our internal URL converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest import unittest.mock import PyFunceble.storage from PyFunceble.converter.internal_url import InternalUrlConverter class TestInternalUrlConverter(unittest.TestCase): """ Tests our internal URL converter. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = InternalUrlConverter() def tearDown(self) -> None: """ Destroys everything previously created for the tests. """ del self.converter def test_set_data_to_convert_no_string(self) -> None: """ Tests the method which let us set the data to work with for the case that a non-string value is given. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_data_to_convert(given)) def test_get_converted_nothing_to_decode(self) -> None: """ Tests the method which let us convert our internal url for the case that no conversion is needed.. """ original_version = PyFunceble.storage.PROJECT_VERSION PyFunceble.storage.PROJECT_VERSION = "1.0.0.dev (Hello, World)" given = "https://raw.githubusercontent.com/funilrys/hello_world/dev/test.json" expected = ( "https://raw.githubusercontent.com/funilrys/hello_world/dev/test.json" ) self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) PyFunceble.storage.PROJECT_VERSION = original_version def test_get_converted_dev_to_master(self) -> None: """ Tests the method which let us convert our internal url for the case that we want to get the master version of the url. """ original_version = PyFunceble.storage.PROJECT_VERSION PyFunceble.storage.PROJECT_VERSION = "1.0.0. (Hello, World)" given = "https://raw.githubusercontent.com/funilrys/hello_world/dev/test.json" expected = ( "https://raw.githubusercontent.com/funilrys/hello_world/master/test.json" ) self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) PyFunceble.storage.PROJECT_VERSION = original_version def test_get_converted_master_to_dev(self) -> None: """ Tests the method which let us convert our internal url for the case that we want to get the dev version of the url. """ original_version = PyFunceble.storage.PROJECT_VERSION PyFunceble.storage.PROJECT_VERSION = "1.0.0.dev (Hello, World)" given = ( "https://raw.githubusercontent.com/funilrys/hello_world/master/test.json" ) expected = ( "https://raw.githubusercontent.com/funilrys/hello_world/dev/test.json" ) self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) PyFunceble.storage.PROJECT_VERSION = original_version if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/converter/test_rpz_input_line2subject.py000066400000000000000000000136601467462152100257240ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the RPZ input line 2 subject converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from typing import List, Optional, Tuple from PyFunceble.converter.rpz_input_line2subject import RPZInputLine2Subject class TestRPZInputLine2Subject(unittest.TestCase): """ Tests of our RPZ line 2 subject(s). """ TEST_SUBJECT_SIMPLE: List[Tuple[Optional[List[str]], str]] = [ ( ["32.53.0.0.127.rpz-ip"], " 32.53.0.0.127.rpz-ip CNAME rpz-drop. ", ), ( ["24.0.0.0.127.rpz-client-ip"], " 24.0.0.0.127.rpz-client-ip CNAME rpz-drop. ", ), (["32.2.3.4.10.rpz-ip"], " 32.2.3.4.10.rpz-ip CNAME . "), ( ["48.zz.101.db8.2001.rpz-client-ip"], " 48.zz.101.db8.2001.rpz-client-ip CNAME rpz-passthru. ", ), ( ["rpz.example.org."], "rpz.example.org. 3600 IN SOA " "hello.world.example.world. knock.knock.knock.knock. " "2020091304 3600 60 604800 60", ), ([], "$TTL 3600"), ([], "@ IN SOA exampledns.mydns. root.mydns. ("), ([], "2020091801 ; serial number"), ([], "3600 ; refresh 1 hour"), ([], "600 ; retry 10 minutes"), ([], "86400 ; expiry 1 week"), ([], "600 ) ; min ttl 10 minutes"), ([], "@ IN NS exampledns.mydns."), ] TEST_SUBJEC_COMMENTED_LINES: List[str] = [ " ; Hello, World!", "; World, Hello! ", " ; Hello, World!", ] def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = RPZInputLine2Subject() def tearDown(self) -> None: """ Destroys everything previously created for the tests. """ del self.converter def test_get_converted_comment(self) -> None: """ Tests the method which let us get the converted data for the case that the given data is a comment line. """ expected = [] for line in self.TEST_SUBJEC_COMMENTED_LINES: self.converter.data_to_convert = line actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_simple_line(self) -> None: """ Tests the method which let us get the converted data for the case that the given data is a simple understandable line. """ for expected, line in self.TEST_SUBJECT_SIMPLE: self.converter.data_to_convert = line actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_simple_line_with_commend(self) -> None: """ Tests the method which let us get the converted data for the case that the given data is a simple line which ends with a commment. """ for expected, line in self.TEST_SUBJECT_SIMPLE: self.converter.data_to_convert = f"{line} ; Hello, World!" actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_simple_domain(self) -> None: """ Tests the method which let get the converted data for the case that the given data is a simple domain. """ given = "example.com" expected = ["example.com"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/converter/test_rpz_policy2subject.py000066400000000000000000000360061467462152100250540ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the RPZ Policy 2 subject converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.converter.rpz_policy2subject import RPZPolicy2Subject from PyFunceble.converter.wildcard2subject import Wildcard2Subject try: import pyf_test_dataset import pyf_test_helpers except ModuleNotFoundError: # pragma: no cover from .. import pyf_test_dataset, pyf_test_helpers class TestRPZPolicy2Subject(unittest.TestCase): """ Tests of our RPZ Policy 2 subject converter. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = RPZPolicy2Subject() def tearDown(self) -> None: """ Destroys everything previously created for the tests. """ del self.converter def test_init_with_helper(self) -> None: """ Tests the initialization with our own helpers. """ wildcard2subject = Wildcard2Subject() self.converter = RPZPolicy2Subject(wildcard2subject=wildcard2subject) self.assertIsInstance(self.converter.wilcard2subject, Wildcard2Subject) self.assertEqual(id(wildcard2subject), id(self.converter.wilcard2subject)) def test_remove_marker(self) -> None: """ Tests the method which let us remove everything up to a given marker. """ given = "example.org.rpz-nsdname" given_marker = ".rpz-nsdname" expected = "example.org" actual = self.converter.remove_marker(given, given_marker) self.assertEqual(expected, actual) def test_remove_not_marker(self) -> None: """ Tests the method which let us remove everything up to a given marker for the case that the given marker does not exists in the givne subject. """ given = "example.org" given_marker = ".rpz-nsdname" expected = "example.org" actual = self.converter.remove_marker(given, given_marker) self.assertEqual(expected, actual) def test_get_matching_cleanup_marker(self) -> None: """ Tests the method which let us get the cleanup marker that matches the in the given subject. """ given = "example.org.rpz-nsdname" expected = ".rpz-nsdname" actual = self.converter.get_matching_cleanup_marker(given) self.assertEqual(expected, actual) def test_get_not_matching_cleanup_marker(self) -> None: """ Tests the method which let us get the cleanup marker that matches the in the given subject for the case that no marker can be found in the given string. """ given = "example.org.rpz-funilrys" expected = None actual = self.converter.get_matching_cleanup_marker(given) self.assertEqual(expected, actual) def test_get_matching_ip_marker(self) -> None: """ Tests the method which let us get the ip marker that matches the in the given subject. """ given_map = { ".rpz-client-ip": "example.org.rpz-client-ip", ".rpz-ip": "example.org.rpz-ip", ".rpz-nsip": "example.org.rpz-nsip", } for expected, given in given_map.items(): actual = self.converter.get_matching_ip_marker(given) self.assertEqual(expected, actual) def test_get_not_matching_ip_marker(self) -> None: """ Tests the method which let us get the ip marker that matches the in the given subject for the case that no marker can be found in the given string. """ given = "example.org.rpz-ip-funilrys" expected = None actual = self.converter.get_matching_ip_marker(given) self.assertEqual(expected, actual) def test_get_subject_from_ip_marker_with_ipv4(self) -> None: """ Tests the method which let us get the real subject from the given ip marker. """ for given_ip in pyf_test_dataset.VALID_IPV4: marker = ".rpz-client-ip" given = f"{pyf_test_helpers.convert_ipv4_to_rpz(given_ip)}{marker}" expected = given_ip actual = self.converter.get_subject_from_ip_marker(given, marker) self.assertEqual(expected, actual) def test_get_subject_from_ip_marker_with_ipv6(self) -> None: """ Tests the method which let us get the real subject from the given ip marker. """ for given_ip in pyf_test_dataset.VALID_IPV6: marker = ".rpz-client-ips" given = f"{pyf_test_helpers.convert_ipv6_to_rpz(given_ip)}{marker}" expected = given_ip actual = self.converter.get_subject_from_ip_marker(given, marker) self.assertEqual(expected, actual) def test_get_converted_simple_domain(self) -> None: """ Tests the method which let us get the converted data for the case that a simple domain is given. """ given = "example.org" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_comment(self) -> None: """ Tests the method which let us get the converted data for the case that a simple domain is given. """ given = "; Hello, World" expected = None self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_simple_commented_domain(self) -> None: """ Tests the method which let us get the converted data for the case that a simple but commented domain is given. """ given = "example.org. ; Hello, World!" expected = "example.org." self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_wildcard(self) -> None: """ Tests the method which let us get the converted data for the case that a wildcard domain is given. """ given = "*.example.org" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_nsdname(self) -> None: """ Tests the method which let us get the converted data for the case that a subjec with the :code:`.rpz-nsdname` policy is given. """ given = "example.org.rpz-nsdname" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_wildcard_nsdname(self) -> None: """ Tests the method which let us get the converted data for the case that a wildcard subjec with the :code:`.rpz-nsdname` policy is given. """ given = "*.example.org.rpz-nsdname" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_rpz_ip_ipv4(self) -> None: """ Tests the method which let us get the converted data for the case that a wildcard subjec with the :code:`.rpz-ip` policy is given. """ given = ( f"{pyf_test_helpers.convert_ipv4_to_rpz(pyf_test_dataset.VALID_IPV4[0])}" ".rpz-ip" ) expected = pyf_test_dataset.VALID_IPV4[0] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_rpz_ip_ipv6(self) -> None: """ Tests the method which let us get the converted data for the case that a wildcard subjec with the :code:`.rpz-ip` policy is given. """ given = ( f"{pyf_test_helpers.convert_ipv6_to_rpz(pyf_test_dataset.VALID_IPV6[0])}" ".rpz-ip" ) expected = pyf_test_dataset.VALID_IPV6[0] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_set_soa_return(self) -> None: """ Tests the response from the method which let us set the SOA to work with. """ given = "example.com." actual = self.converter.set_soa(given) self.assertIsInstance(actual, RPZPolicy2Subject) def test_set_soa_method(self) -> None: """ Tests the method which let us set the SOA to work with. """ given = "example.com." expected = "example.com." self.converter.set_soa(given) actual = self.converter.soa self.assertEqual(expected, actual) self.assertTrue(given in self.converter.soas) def test_set_soa_attribute(self) -> None: """ Tests overwritting of the :code:`soa` attribute. """ given = "example.com." expected = "example.com." self.converter.soa = given actual = self.converter.soa self.assertEqual(expected, actual) self.assertTrue(given in self.converter.soas) def test_set_soa_no_str(self) -> None: """ Tests overwritting of the :code:`soa` attribute. In this test we test the case that we give a non-string value. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.converter.set_soa(given)) def test_set_soa_empty_str(self) -> None: """ Tests overwritting of the :code:`soa` attribute. In this test we test the case that we give an empty string value. """ given = "" self.assertRaises(ValueError, lambda: self.converter.set_soa(given)) def test_set_soa_through_init(self) -> None: """ Tests the overwritting of the SOA to work with through the class constructor. """ given = "example.com." expected = "example.com." converter = RPZPolicy2Subject(soa=given) actual = converter.soa self.assertEqual(expected, actual) self.assertTrue(given in converter.soas) def test_set_soas_return(self) -> None: """ Tests the response from the method which let us set the SOAs to work with. """ given = ["example.com."] actual = self.converter.set_soas(given) self.assertIsInstance(actual, RPZPolicy2Subject) def test_set_soas_method(self) -> None: """ Tests the method which let us set the SOA to work with. """ given = ["example.com."] expected = ["example.com."] self.converter.set_soas(given) actual = self.converter.soas self.assertEqual(expected, actual) def test_set_soas_attribute(self) -> None: """ Tests overwritting of the :code:`soas` attribute. """ given = ["example.com."] expected = ["example.com."] self.converter.soas = given actual = self.converter.soas self.assertEqual(expected, actual) def test_set_soas_no_list(self) -> None: """ Tests overwritting of the :code:`soas` attribute. In this test we test the case that we give a non-list value. """ given = "Hello, World!" self.assertRaises(TypeError, lambda: self.converter.set_soas(given)) def test_set_soas_non_list_of_str(self) -> None: """ Tests overwritting of the :code:`soas` attribute. In this test we test the case that we give a non string value. """ given = [".example.org.", None, ".example.net."] self.assertRaises(ValueError, lambda: self.converter.set_soas(given)) def test_set_soas_through_init(self) -> None: """ Tests the overwritting of the SOA to work with through the class constructor. """ given = ["example.com."] expected = ["example.com."] converter = RPZPolicy2Subject(soas=given) actual = converter.soas self.assertEqual(expected, actual) def test_get_converted_soa(self) -> None: """ Tests the method which let us get the converted data for the case that a subjec with the SOA given. """ given = "example.org.example.net" given_soa = "example.net" expected = "example.org" self.converter.data_to_convert = given self.converter.soa = given_soa actual = self.converter.get_converted() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/converter/test_subject2complements.py000066400000000000000000000144111467462152100252040ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of subject to complements converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.converter.subject2complements import Subject2Complements class TestRPZInputLine2Subject(unittest.TestCase): """ Tests of our RPZ line 2 subject(s). """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = Subject2Complements() def tearDown(self) -> None: """ Destroys everything previously created for the tests. """ del self.converter def test_set_data_to_convert_no_string(self) -> None: """ Tests the method which let us set the data to work with for the case that a non-string value is given. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_data_to_convert(given)) def test_set_include_given_return(self) -> None: """ Tests the response from the method which let us activate the inclusion of the given subject into the result. """ given = True actual = self.converter.set_include_given(given) self.assertIsInstance(actual, Subject2Complements) def test_set_include_given_method(self) -> None: """ Tests the method which let us set activate the inclusion of the given subject into the result. """ given = True expected = True self.converter.set_include_given(given) actual = self.converter.include_given self.assertEqual(expected, actual) def test_set_include_given_attribute(self) -> None: """ Tests overwritting of the :code:`include_given` attribute. """ given = True expected = True self.converter.include_given = given actual = self.converter.include_given self.assertEqual(expected, actual) def test_set_include_given_through_init(self) -> None: """ Tests the activation of the inclusion of the given subject into the result through the class constructor. """ given = True expected = True converter = Subject2Complements(include_given=given) actual = converter.include_given self.assertEqual(expected, actual) def test_set_include_given_not_bool(self) -> None: """ Tests the response from the method which let us activate the inclusion of the given subject into the result for the case that the given value is not a boolean. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_include_given(given)) def test_get_converted(self) -> None: """ Tests the conversion for the case that a non-www subdomain is given. """ given = "example.org" expected = ["www.example.org"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_starts_with_www(self) -> None: """ Tests the conversion for the case that a www subdomain is given. """ given = "www.example.org" expected = ["example.org"] self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_include_given(self) -> None: """ Tests the conversion for the case that we want the given subject to be included in the result. """ given = "www.example.org" # We expect the given to always be the first index. expected = ["www.example.org", "example.org"] self.converter.include_given = True self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/converter/test_url2netloc.py000066400000000000000000000213501467462152100233050ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of URL 2 Network Location converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest import unittest.mock from urllib.parse import ParseResult from PyFunceble.converter.url2netloc import Url2Netloc class TestUrl2Netloc(unittest.TestCase): """ Tests our internal URL converter. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = Url2Netloc() def tearDown(self) -> None: """ Destroys everything previously created for the tests. """ del self.converter def test_set_data_to_convert_no_string(self) -> None: """ Tests the method which let us set the data to work with for the case that a non-string value is given. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_data_to_convert(given)) def test_set_data_to_convert_empty_string(self) -> None: """ Tests the method which let us set the data to work with for the case that an empty-string value is given. """ given = "" self.assertRaises(ValueError, lambda: self.converter.set_data_to_convert(given)) def test_get_converted_nothing_to_decode(self) -> None: """ Tests the method which let us extracts the netloc from a given URL for the case that no conversion is needed. """ given = "example.org" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_full_url(self) -> None: """ Tests the method which let us extracts the netloc from a given URL for the case that a full URL is given. """ given = "https://example.org/hello/world/this/is/a/test" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_full_url_with_port(self) -> None: """ Tests the method which let us extracts the netloc from a given URL for the case that a full URL (with explicit port) is given. """ given = "https://example.org:8080/hello/world/this/is/a/test" expected = "example.org:8080" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_full_url_with_params(self) -> None: """ Tests the method which let us extracts the netloc from a given URL for the case that a full URL (with params) is given. """ given = "https://example.org/?is_admin=true" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_url_without_scheme(self) -> None: """ Tests the method which let us extracts the netloc from a given URL for the case that no scheme is given. """ given = "example.org/hello/world/this/is/a/test" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_url_without_scheme_and_with_params(self) -> None: """ Tests the method which let us extracts the netloc from a given URL for the case that no scheme (but with params) is given. """ given = "example.org/?is_admin=true" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_url_without_protocol(self) -> None: """ Tests the method which let us extracts the netloc from a given URL for the case that no protocol is given. """ given = "://example.org/hello/world/this/is/a/test" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_url_without_protocol_and_with_params(self) -> None: """ Tests the method which let us extracts the netloc from a given URL for the case that no protocol (but params) is given. """ given = "://example.org/?is_admin=true" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_url_without_protocol_and_path(self) -> None: """ Tests the method which let us extracts the netloc from a given URL for the case that no protocol and path is given. """ given = "://example.org/" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_url_startswith_2_slashes(self) -> None: """ Tests the method which let us extracts the netloc from a given URL for the case that the given url starts with 2 slashes. """ given = "//example.org/hello/world/this/is/a/test" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_url_startswith_1_slash(self) -> None: """ Tests the method which let us extracts the netloc from a given URL for the case that the given url starts with 1 slash. """ given = "/example.org/hello/world/this/is/a/test" expected = "" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_parse_single_url(self) -> None: """ Tests the method which let us "quickly" parse a URL. """ actual = self.converter.parse_single_url("http://example.org/hello/world") self.assertIsInstance(actual, ParseResult) self.assertEqual(self.converter.parse_single_url(None), None) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/converter/test_wildcard2subject.py000066400000000000000000000122341467462152100244500ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our wildcard to subject converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.converter.wildcard2subject import Wildcard2Subject class TestWildcard2Subject(unittest.TestCase): """ Tests our wildcard 2 subject converter. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = Wildcard2Subject() def tearDown(self) -> None: """ Destroys everything previously created for the tests. """ del self.converter def test_set_data_to_convert_no_string(self) -> None: """ Tests the method which let us set the data to work with for the case that a non-string value is given. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_data_to_convert(given)) def test_get_converted_empty(self) -> None: """ Tests the method which let us get the converted data for the case that it's an empty string is given. """ given = "" expected = None self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted(self) -> None: """ Tests the method which let us get the converted data. """ given = "*.example.org" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_not_wildcard(self) -> None: """ Tests the method which let us get the converted data for the case that the given subject is not a wildcard. """ given = "example.org" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_wildcard_at_end(self) -> None: """ Tests the method which let us get the converted data for the case that the wildcard is located at the end. """ given = "example.org.*" expected = "example.org.*" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_wildcard_both_end(self) -> None: """ Tests the method which let us get the converted data for the case that the wildcard is located at the both end. """ given = "*.example.org.*" expected = "example.org.*" self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/dataset/000077500000000000000000000000001467462152100172205ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/dataset/__init__.py000066400000000000000000000000001467462152100213170ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/dataset/test_base.py000066400000000000000000000104261467462152100215460ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the base of all our dataset. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 tempfile import unittest import unittest.mock from PyFunceble.dataset.base import DatasetBase class TestDatasetBase(unittest.TestCase): """ Tests the base of all dataset. """ def setUp(self) -> None: """ Setups everything needed by the tests. """ self.tempfile = tempfile.NamedTemporaryFile() self.our_dataset = [ "127.176.134.253", "127.34.113.192", "127.34.107.238", "127.166.193.125", "127.179.153.18", "127.89.243.30", "127.147.142.53", "127.35.150.233", "127.97.172.196", "127.24.78.18", ] self.tempfile.write("\n".join(self.our_dataset).encode()) self.tempfile.seek(0) self.dataset = DatasetBase() self.dataset.source_file = self.tempfile.name def tearDown(self) -> None: """ Destroys everything needed by the tests. """ del self.tempfile del self.our_dataset del self.dataset def test_get_content_not_str(self) -> None: """ Tests our decorator which checks if the source file is given. In this test, we check the case that the given source file is not a string. """ self.dataset.source_file = ["Hello", "World!"] # pylint: disable=unnecessary-lambda self.assertRaises(TypeError, lambda: self.dataset.get_content()) def test_get_content_empty_str(self) -> None: """ Tests our decorator which checks if the source file is given. In this test, we check the case that the given source file is an empty string. """ self.dataset.source_file = "" # pylint: disable=unnecessary-lambda self.assertRaises(ValueError, lambda: self.dataset.get_content()) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/dataset/test_db_base.py000066400000000000000000000236021467462152100222130ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the base of all our database dataset. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 unittest import unittest.mock from typing import Generator, Optional from PyFunceble.dataset.db_base import DBDatasetBase class TestDBDatasetBase(unittest.TestCase): """ Tests the base of all database dataset. """ def setUp(self) -> None: """ Setups everything needed by the tests. """ self.dataset = DBDatasetBase() def tearDown(self) -> None: """ Destroys everything needed by the tests. """ del self.dataset def test_set_authorized_return(self) -> None: """ Tests the response from the method which let us set the authorization to operate. """ given = True actual = self.dataset.set_authorized(given) self.assertIsInstance(actual, DBDatasetBase) def test_set_authorized_method(self) -> None: """ Tests the method which let us set the authorization to operate. """ given = True expected = True self.dataset.set_authorized(given) actual = self.dataset.authorized self.assertEqual(expected, actual) def test_set_authorized_attribute(self) -> None: """ Tests overwritting of the :code:`authorized` attribute. """ given = True expected = True self.dataset.authorized = given actual = self.dataset.authorized self.assertEqual(expected, actual) def test_set_authorized_through_init(self) -> None: """ Tests the overwritting of the authorization to operate through the class constructor. """ given = True expected = True dataset = DBDatasetBase(authorized=given) actual = dataset.authorized self.assertEqual(expected, actual) def test_set_authorized_no_string(self) -> None: """ Tests the method which let us set the authorization to operate for the case that the given value is not a boolean. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.dataset.set_authorized(given)) def test_set_remove_unneeded_fields_return(self) -> None: """ Tests the response from the method which let us authorize the deletion of unneeded fields """ given = True actual = self.dataset.set_remove_unneeded_fields(given) self.assertIsInstance(actual, DBDatasetBase) def test_set_remove_unneeded_fields_method(self) -> None: """ Tests the method which let us authorize the deletion of unneeded fields. """ given = True expected = True self.dataset.set_remove_unneeded_fields(given) actual = self.dataset.remove_unneeded_fields self.assertEqual(expected, actual) def test_set_remove_unneeded_fields_attribute(self) -> None: """ Tests overwritting of the :code:`remove_unneeded_fields` attribute. """ given = True expected = True self.dataset.remove_unneeded_fields = given actual = self.dataset.remove_unneeded_fields self.assertEqual(expected, actual) def test_set_remove_unneeded_fields_through_init(self) -> None: """ Tests the overwritting of the :code:`remove_unneeded_fields` attribute through the class constructor. """ given = True expected = True dataset = DBDatasetBase(remove_unneeded_fields=given) actual = dataset.remove_unneeded_fields self.assertEqual(expected, actual) def test_set_remove_unneeded_fields_no_string(self) -> None: """ Tests the method which let us authorizes the deletion of unneeded fields for the case that the given value is not a boolean. """ given = ["Hello", "World"] self.assertRaises( TypeError, lambda: self.dataset.set_remove_unneeded_fields(given) ) def test_get_filtered_row(self) -> None: """ Tests the method which let us filter a given row to the only minimum. """ self.dataset.authorized = True # pylint: disable=invalid-name self.dataset.FIELDS = ["hello", "world", "fun", "state"] self.dataset.COMPARISON_FIELDS = ["hello"] given = { "my_key": "key_my", "world": "hello", "fun": "ilrys", "state": "sleeping", "sleeping": None, } expected = {"hello": "", "world": "hello", "state": "sleeping", "fun": "ilrys"} actual = self.dataset.get_filtered_row(given) self.assertEqual(expected, actual) def test_get_filtered_row_not_authorized(self) -> None: """ Tests the method which let us filter a given row to the only minimum. In this case we check what should happen when the dataset interface is not authorized to operate. """ self.dataset.authorized = False self.dataset.FIELDS = ["hello", "world", "fun", "state"] self.dataset.COMPARISON_FIELDS = ["hello"] given = { "my_key": "key_my", "world": "hello", "fun": "ilrys", "state": "sleeping", "sleeping": None, } expected = {} actual = self.dataset.get_filtered_row(given) self.assertEqual(expected, actual) def test_get_filtered_content(self) -> None: """ Tests the method which let us get a filter content. """ def our_get_content() -> Generator[Optional[dict], None, None]: """ Provides our very own content provider. """ dataset = [ {"user": "funilrys", "state": "sleeping"}, {"user": "fun.ilrys", "state": "coding"}, {"user": "ilrys.fun", "state": "eating"}, {"user": "anonymous", "state": "coding"}, {"user": "foo.bar", "state": "sleeping"}, {"user": "bar.foo", "state": "coding"}, ] yield from dataset self.dataset.authorized = True with unittest.mock.patch.object( DBDatasetBase, "get_content" ) as get_content_patch: get_content_patch.return_value = our_get_content() to_filter = {"state": "coding"} expected = [ {"user": "fun.ilrys", "state": "coding"}, {"user": "anonymous", "state": "coding"}, {"user": "bar.foo", "state": "coding"}, ] actual = list(self.dataset.get_filtered_content(to_filter)) self.assertEqual(expected, actual) # Now we test the case that we give a key that is not into the dataset. with unittest.mock.patch.object( DBDatasetBase, "get_content" ) as get_content_patch: get_content_patch.return_value = our_get_content() to_filter = {"sleeping": True} expected = [] actual = list(self.dataset.get_filtered_content(to_filter)) self.assertEqual(expected, actual) def test_get_filtered_content_not_dict(self) -> None: """ Tests the method which let us get a filter content for the case that the given filter is not a :py:class:`dict`. """ self.dataset.authorized = True to_filter = ["Hello", "World!"] self.assertRaises( TypeError, lambda: list(self.dataset.get_filtered_content(to_filter)) ) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/dataset/test_iana.py000066400000000000000000000175661467462152100215600ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of iana dataset interaction. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 copy import json import tempfile import unittest import unittest.mock from PyFunceble.dataset.base import DatasetBase from PyFunceble.dataset.iana import IanaDataset class TestIanaDataset(unittest.TestCase): """ Tests the iana dataset interaction. """ def setUp(self) -> None: """ Setups everything needed by the tests. """ self.tempfile = tempfile.NamedTemporaryFile() self.our_dataset = { "aaa": "whois.nic.aaa", "aarp": "whois.nic.aarp", "abarth": "whois.afilias-srs.net", "abb": "whois.nic.abb", "abbott": "whois.afilias-srs.net", "abbvie": "whois.afilias-srs.net", "abc": "whois.nic.abc", "able": "whois.nic.able", "abogado": "whois.nic.abogado", "abudhabi": "whois.nic.abudhabi", "ac": "whois.nic.ac", } self.tempfile.write(json.dumps(self.our_dataset).encode()) self.tempfile.seek(0) self.iana_dataset = IanaDataset() self.iana_dataset.source_file = self.tempfile.name self.get_content_patch = unittest.mock.patch.object(DatasetBase, "get_content") self.mock_get_content = self.get_content_patch.start() self.mock_get_content.return_value = copy.deepcopy(self.our_dataset) def tearDown(self) -> None: """ Destroys everything needed by the tests. """ self.get_content_patch.stop() del self.mock_get_content del self.tempfile del self.our_dataset del self.iana_dataset def test_contains(self) -> None: """ Tests of the method which let us check if a given extension is into the dataset. """ given = "aaa" expected = True actual = given in self.iana_dataset self.assertEqual(expected, actual) def test_contains_extension_starts_with_point(self) -> None: """ Tests of the method which let us check if a given extension is into the dataset for the case that the extension starts with a point. """ given = ".aaa" expected = True actual = given in self.iana_dataset self.assertEqual(expected, actual) def test_does_not_contain(self) -> None: """ Tests of the method which let us check if a given extension is into the dataset. """ given = "com" expected = False actual = given in self.iana_dataset self.assertEqual(expected, actual) def test_getitem(self) -> None: """ Tests the method which let us (indirectly) get the whois server. """ expected = "whois.nic.aarp" actual = self.iana_dataset["aarp"] self.assertEqual(expected, actual) def test_getitem_extension_starts_with_point(self) -> None: """ Tests the method which let us (indirectly) get the whois server. """ expected = "whois.nic.aarp" actual = self.iana_dataset[".aarp"] self.assertEqual(expected, actual) def test_getitem_not_exist(self) -> None: """ Tests the method which let us (indirectly) get the whois server for the case that the given extension does not exists. """ expected = None actual = self.iana_dataset["hehehe"] self.assertEqual(expected, actual) def test_getattr(self) -> None: """ Tests the method which let us (indirectly) get the whois server. """ expected = "whois.nic.aarp" actual = self.iana_dataset.aarp self.assertEqual(expected, actual) def test_getattr_not_exist(self) -> None: """ Tests the method which let us (indirectly) get the whois server for the case that the given extension does not exists. """ expected = None actual = self.iana_dataset.hehehe self.assertEqual(expected, actual) def test_is_extension(self) -> None: """ Tests the method which let us check if the given extension is known. """ expected = True actual = self.iana_dataset.is_extension("aarp") self.assertEqual(expected, actual) def test_is_not_extension(self) -> None: """ Tests the method which let us check if the given extension is known for the case tha the given extension does not exists. """ expected = False actual = self.iana_dataset.is_extension("heheh") self.assertEqual(expected, actual) def test_is_extension_not_str(self) -> None: """ Tests the method which let us check if the given extension is known for the case that the given extension """ self.assertRaises(TypeError, lambda: self.iana_dataset.is_extension(["test"])) def test_get_whois_server(self) -> None: """ Tests the method which let us get the whois server of a given extension. """ expected = "whois.nic.aarp" actual = self.iana_dataset.get_whois_server("aarp") self.assertEqual(expected, actual) def test_get_whois_server_not_extension(self) -> None: """ Tests the method which let us get the whois server of a given extension for the case that the given extension is not known. """ expected = None actual = self.iana_dataset.get_whois_server("hehehehehe") self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/dataset/test_ipv4_reputation.py000066400000000000000000000104541467462152100237710ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of ipv4 reputation dataset. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 tempfile import unittest import unittest.mock from PyFunceble.dataset.ipv4_reputation import IPV4ReputationDataset class TestIPV4ReputationDataset(unittest.TestCase): """ Tests the reputation dataset interaction. """ def setUp(self) -> None: """ Setups everything needed by the tests. """ self.tempfile = tempfile.NamedTemporaryFile("wb", delete=False) self.our_dataset = """ 127.176.134.253#4#3#Malicious Host 127.34.113.192#4#2#Malicious Host 127.34.107.238#4#2#Malicious Host 127.166.193.125#4#2#Malicious Host 127.179.153.18#4#2#Malicious Host 127.89.243.30#4#2#Malicious Host 127.147.142.53#4#2#Malicious Host 127.35.150.233#4#3#Malicious Host 127.97.172.196#4#2#Malicious Host 127.24.78.18#4#2#Malicious Host """ self.tempfile.write(self.our_dataset.encode()) self.tempfile.seek(0) self.ipv4_reputation_dataset = IPV4ReputationDataset() self.ipv4_reputation_dataset.source_file = self.tempfile.name def tearDown(self) -> None: """ Destroys everything needed by the tests. """ del self.tempfile del self.our_dataset del self.ipv4_reputation_dataset def test_contains(self) -> None: """ Tests of the method which let us check if a given IP is into the dataset. """ given = "127.24.78.18" expected = True actual = given in self.ipv4_reputation_dataset self.assertEqual(expected, actual) def test_not_contains(self) -> None: """ Tests of the method which let us check if a given IP is into the dataset. In this case, we check against something which does not exists. """ given = "192.168.78.1" expected = False actual = given in self.ipv4_reputation_dataset self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/dataset/test_public_suffix.py000066400000000000000000000175461467462152100235100ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of public suffic dataset interaction. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 copy import json import tempfile import unittest import unittest.mock from PyFunceble.dataset.base import DatasetBase from PyFunceble.dataset.public_suffix import PublicSuffixDataset class TestPublicSuffixDataset(unittest.TestCase): """ Tests the public suffix dataset interaction. """ def setUp(self) -> None: """ Setups everything needed by the tests. """ self.tempfile = tempfile.NamedTemporaryFile() self.our_dataset = { "ac": ["com.ac", "edu.ac", "gov.ac", "mil.ac", "net.ac", "org.ac"], "academy": ["official.academy"], "ad": ["nom.ad"], } self.tempfile.write(json.dumps(self.our_dataset).encode()) self.tempfile.seek(0) self.ps_dataset = PublicSuffixDataset() self.ps_dataset.source_file = self.tempfile.name self.get_content_patch = unittest.mock.patch.object(DatasetBase, "get_content") self.mock_get_content = self.get_content_patch.start() self.mock_get_content.return_value = copy.deepcopy(self.our_dataset) def tearDown(self) -> None: """ Destroys everything needed by the tests. """ del self.tempfile del self.our_dataset del self.ps_dataset self.get_content_patch.stop() del self.get_content_patch def test_contains(self) -> None: """ Tests of the method which let us check if a given extension is into the dataset. """ given = "ac" expected = True actual = given in self.ps_dataset self.assertEqual(expected, actual) def test_contains_extension_starts_with_point(self) -> None: """ Tests of the method which let us check if a given extension is into the dataset for the case that the extension starts with a point. """ given = ".ac" expected = True actual = given in self.ps_dataset self.assertEqual(expected, actual) def test_does_not_contain(self) -> None: """ Tests of the method which let us check if a given extension is into the dataset. """ given = "com" expected = False actual = given in self.ps_dataset self.assertEqual(expected, actual) def test_getitem(self) -> None: """ Tests the method which let us (indirectly) get the available subdataset. """ expected = copy.deepcopy(self.our_dataset["ad"]) actual = self.ps_dataset["ad"] self.assertEqual(expected, actual) def test_getitem_extension_starts_with_point(self) -> None: """ Tests the method which let us (indirectly) get the available subdataset. """ expected = copy.deepcopy(self.our_dataset["ad"]) actual = self.ps_dataset[".ad"] self.assertEqual(expected, actual) def test_getitem_not_exist(self) -> None: """ Tests the method which let us (indirectly) get the available subdataset for the case that the given extension does not exists. """ expected = list() # pylint: disable=use-list-literal actual = self.ps_dataset["hehehe"] self.assertEqual(expected, actual) def test_getattr(self) -> None: """ Tests the method which let us (indirectly) get the available subdataset. """ expected = copy.deepcopy(self.our_dataset["ad"]) actual = self.ps_dataset.ad self.assertEqual(expected, actual) def test_getattr_not_exist(self) -> None: """ Tests the method which let us (indirectly) get the available subdataset for the case that the given extension does not exists. """ expected = list() # pylint: disable=use-list-literal actual = self.ps_dataset.hehehe self.assertEqual(expected, actual) def test_is_extension(self) -> None: """ Tests the method which let us check if the given extension is known. """ expected = True actual = self.ps_dataset.is_extension("ad") self.assertEqual(expected, actual) def test_is_not_extension(self) -> None: """ Tests the method which let us check if the given extension is known for the case tha the given extension does not exists. """ expected = False actual = self.ps_dataset.is_extension("heheh") self.assertEqual(expected, actual) def test_is_extension_not_str(self) -> None: """ Tests the method which let us check if the given extension is known for the case that the given extension """ self.assertRaises(TypeError, lambda: self.ps_dataset.is_extension(["test"])) def test_get_available_suffix(self) -> None: """ Tests the method which let us get the available suffixes of a given extension. """ expected = copy.deepcopy(self.our_dataset["ad"]) actual = self.ps_dataset.get_available_suffix("ad") self.assertEqual(expected, actual) def test_get_available_suffix_not_extension(self) -> None: """ Tests the method which let us get the whois server of a given extension for the case that the given extension is not known. """ expected = list() # pylint: disable=use-list-literal actual = self.ps_dataset.get_available_suffix("hehehehehe") self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/dataset/test_user_agent.py000066400000000000000000000445541467462152100230010ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the user agent dataset interaction. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 copy import json import tempfile import unittest import unittest.mock from PyFunceble.config.loader import ConfigLoader from PyFunceble.dataset.base import DatasetBase from PyFunceble.dataset.user_agent import UserAgentDataset class TestUserAgentDataset(unittest.TestCase): """ Tests the user agent dataset interaction. """ def setUp(self) -> None: """ Setups everything needed by the tests. """ self.config_loader = ConfigLoader() self.tempfile = tempfile.NamedTemporaryFile() self.modern_tempfile = tempfile.NamedTemporaryFile() self.our_dataset = { "@modern": { "chrome": { "linux": [ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/77.0.3865.116 " "Safari/537.36 Edg/77.11.4.5118" ], "macosx": [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) " "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4364.0 " "Safari/537.36" ], "win10": [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4361.0 " "Safari/537.36" ], }, "edge": { "linux": [], "macosx": [], "win10": [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 " "Safari/537.36 Edge/18.17763/5.9.7 (Linux;Android 10) " "ExoPlayerLib/2.9.6" ], }, "firefox": { "linux": [ "Mozilla/5.0 (Linux x86_64; en-US) Gecko/20130401 " "Firefox/82.4" ], "macosx": [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0; " "en-US) Gecko/20100101 Firefox/74.7" ], "win10": [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) " "Gecko/20100101 Firefox/84.0/8mqDiPuL-36" ], }, "ie": { "linux": [], "macosx": [], "win10": [ "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; " "Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR " "2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Tablet " "PC 2.0; wbx 1.0.0; wbxapp 1.0.0)" ], }, "opera": { "linux": [ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 " "OPR/73.0.3856.284" ], "macosx": [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) " "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 " "Safari/537.36 OPR/72.0.3815.400" ], "win10": [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 " "Safari/537.36 OPR/73.0.3856.284 (Edition avira-2)" ], }, "safari": { "linux": [ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " "(KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 " "Safari/537.36 SputnikBrowser/1.2.5.158" ], "macosx": [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) " "AppleWebKit/600.8.9 (KHTML, like Gecko) Version/9.0.3 " "Safari/601.4.4" ], "win10": [], }, }, "chrome": { "linux": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/77.0.3865.116 " "Safari/537.36 Edg/77.11.4.5118", "macosx": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) " "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4364.0 " "Safari/537.36", "win10": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4361.0 " "Safari/537.36", }, "edge": { "linux": None, "macosx": None, "win10": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 " "Safari/537.36 Edge/18.17763/5.9.7 (Linux;Android 10) " "ExoPlayerLib/2.9.6", }, "firefox": { "linux": "Mozilla/5.0 (Linux x86_64; en-US) Gecko/20130401 " "Firefox/82.4", "macosx": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0; " "en-US) Gecko/20100101 Firefox/74.7", "win10": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) " "Gecko/20100101 Firefox/84.0/8mqDiPuL-36", }, "ie": { "linux": None, "macosx": None, "win10": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; " "Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR " "2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Tablet " "PC 2.0; wbx 1.0.0; wbxapp 1.0.0)", }, "opera": { "linux": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 " "OPR/73.0.3856.284", "macosx": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) " "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 " "Safari/537.36 OPR/72.0.3815.400", "win10": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 " "Safari/537.36 OPR/73.0.3856.284 (Edition avira-2)", }, "safari": { "linux": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " "(KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 " "Safari/537.36 SputnikBrowser/1.2.5.158", "macosx": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) " "AppleWebKit/600.8.9 (KHTML, like Gecko) Version/9.0.3 " "Safari/601.4.4", "win10": None, }, } self.tempfile.write(json.dumps(self.our_dataset).encode()) self.tempfile.seek(0) self.user_agent_dataset = UserAgentDataset() self.user_agent_dataset.source_file = self.tempfile.name self.get_content_patch = unittest.mock.patch.object(DatasetBase, "get_content") self.mock_get_content = self.get_content_patch.start() self.mock_get_content.return_value = copy.deepcopy(self.our_dataset) def tearDown(self) -> None: """ Destroys everything needed by the tests. """ self.get_content_patch.stop() del self.mock_get_content del self.tempfile del self.our_dataset del self.config_loader del self.user_agent_dataset def test_contains(self) -> None: """ Tests of the method which let us check if a given browser is into the dataset. """ given = "chrome" expected = True actual = given in self.user_agent_dataset self.assertEqual(expected, actual) def test_not_contains(self) -> None: """ Tests the method which let us check if a given platform is into the dataset. """ given = "vivaldi" expected = False actual = given in self.user_agent_dataset self.assertEqual(expected, actual) def test_get_all_from_browser(self) -> None: """ Tests the way to get every information of a given browser. """ given = "chrome" expected = copy.deepcopy(self.our_dataset["@modern"][given]) actual = self.user_agent_dataset[given] self.assertEqual(expected, actual) def test_get_all_from_unknown_browser(self) -> None: """ Tests the way to get every information of a given browser. In this test, we try to get from something that does not exists. """ given = "vivaldi" expected = dict() # pylint: disable=use-dict-literal actual = self.user_agent_dataset[given] self.assertEqual(expected, actual) def test_is_supported_browser(self) -> None: """ Tests the method which let us check if a browser is supported. """ given = "chrome" expected = True actual = self.user_agent_dataset.is_supported_browser(given) self.assertEqual(expected, actual) def test_is_not_supported_browser(self) -> None: """ Tests teh method which let us check if a browser is supported for the case that the given browser is not supported. """ given = "vivaldi" expected = False actual = self.user_agent_dataset.is_supported_browser(given) self.assertEqual(expected, actual) def test_is_supported_browser_not_str(self) -> None: """ Tests the method which let us check if a browser is supported for the case the given browser not is not a string. """ given = ["Hello", "World"] self.assertRaises( TypeError, lambda: self.user_agent_dataset.is_supported_browser(given) ) def test_is_supported(self) -> None: """ Tests the method which let us check if a browser and platform is supported. """ given_browser = "chrome" given_platform = "linux" expected = True actual = self.user_agent_dataset.is_supported(given_browser, given_platform) self.assertEqual(expected, actual) def test_is_supported_not_str_browser(self) -> None: """ Tests the method which let us check if a browser and platform is supported. In this test, we check the case that the given browser is not a string. """ given_browser = ["Hello", "World"] given_platform = "linux" self.assertRaises( TypeError, lambda: self.user_agent_dataset.is_supported(given_browser, given_platform), ) def test_is_supported_not_str_platform(self) -> None: """ Tests the method which let us check if a browser and platform is supported. In this test, we check the case that the given platform is not a string. """ given_browser = "chrome" given_platform = ["Hello", "Worl"] self.assertRaises( TypeError, lambda: self.user_agent_dataset.is_supported(given_browser, given_platform), ) def test_is_supported_unknown_browser(self) -> None: """ Tests the method which let us check if a browser and platform is supported. In this test, we check the case that the given browser is not known. """ given_browser = "vivaldi" given_platform = "linux" expected = False actual = self.user_agent_dataset.is_supported(given_browser, given_platform) self.assertEqual(expected, actual) def test_is_supported_unknown_platform(self) -> None: """ Tests the method which let us check if a browser and platform is supported. In this test, we check the case that the given platform is not known. """ given_browser = "chrome" given_platform = "bsd" expected = False actual = self.user_agent_dataset.is_supported(given_browser, given_platform) self.assertEqual(expected, actual) def test_is_supported_unknown_platform_and_browser(self) -> None: """ Tests the method which let us check if a browser and platform is supported. In this test, we check the case that the given platform and browser are not known. """ given_browser = "vivaldi" given_platform = "bsd" expected = False actual = self.user_agent_dataset.is_supported(given_browser, given_platform) self.assertEqual(expected, actual) def test_set_preferred(self) -> None: """ Tests the method which let us set our preferred browser and platform. """ given_browser = "chrome" given_platform = "win10" actual = self.user_agent_dataset.set_preferred(given_browser, given_platform) self.assertIsInstance(actual, UserAgentDataset) expected_platform = "win10" expected_browser = "chrome" actual_platform = self.user_agent_dataset.preferred_platform actual_browser = self.user_agent_dataset.preferred_browser self.assertEqual(expected_platform, actual_platform) self.assertEqual(expected_browser, actual_browser) def test_set_preferred_not_supported(self) -> None: """ Tests the method which let us set our preferred browser and platform. In this test, we check that an exception is correctly raised when the platform or browser is not supported. """ given_browser = "vivaldi" given_platform = "win10" self.assertRaises( ValueError, lambda: self.user_agent_dataset.set_preferred( given_browser, given_platform ), ) given_browser = "vivaldi" given_platform = "bsd" self.assertRaises( ValueError, lambda: self.user_agent_dataset.set_preferred( given_browser, given_platform ), ) def test_get_latest(self) -> None: """ Tests the method which let us get the latest user agent known. """ given_browser = "chrome" given_platform = "win10" expected = self.our_dataset[given_browser][given_platform] self.user_agent_dataset.set_preferred(given_browser, given_platform) actual = self.user_agent_dataset.get_latest() self.assertEqual(expected, actual) def test_get_latest_from_config(self) -> None: """ Tests the method which let us get the latest user agent known based on the settings from the configuration file. """ given_browser = "firefox" given_platform = "win10" self.config_loader.custom_config = { "user_agent": {"platform": given_platform, "browser": given_browser} } self.config_loader.start() expected = self.our_dataset[given_browser][given_platform] actual = self.user_agent_dataset.get_latest() self.assertEqual(expected, actual) def test_get_latest_from_config_custom(self) -> None: """ Tests the method which let us get the latest user agent known based on the settings from the configuration file. """ self.config_loader.custom_config = {"user_agent": {"custom": "Hello, World!"}} self.config_loader.start() expected = "Hello, World!" actual = self.user_agent_dataset.get_latest() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/helpers/000077500000000000000000000000001467462152100172355ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/helpers/__init__.py000066400000000000000000000000001467462152100213340ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/helpers/test_command.py000066400000000000000000000223721467462152100222720ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the tests of our command helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 sys import unittest import unittest.mock from subprocess import Popen from PyFunceble.helpers.command import CommandHelper from PyFunceble.utils.platform import PlatformUtility try: from stdout_base import StdoutBase except ModuleNotFoundError: # pragma: no cover from ..stdout_base import StdoutBase class TestCommandHelper(StdoutBase): """ Tests of the command helper. """ def setUp(self): """ Setups everything needed for the test. """ self.helper = CommandHelper() return super().setUp() def tearDown(self): """ Destroys everything needed for the test. """ del self.helper return super().tearDown() def test_set_command_return(self) -> None: """ Tests the response from the method which let us set the command to work with. """ given = "echo 'Hello, World'" actual = self.helper.set_command(given) self.assertIsInstance(actual, CommandHelper) def test_set_command_method(self) -> None: """ Tests the method which let us set the command to work with. """ given = "echo 'Hello, World'" expected = "echo 'Hello, World'" self.helper.set_command(given) actual = self.helper.command self.assertEqual(expected, actual) def test_set_command_attribute(self) -> None: """ Tests overwritting of the :code:`command` attribute. """ given = "echo 'Hello, World'" expected = "echo 'Hello, World'" self.helper.command = given actual = self.helper.command self.assertEqual(expected, actual) def test_set_command_through_init(self) -> None: """ Tests the overwritting of the command to work through the class constructor. """ given = "echo 'Hello, World'" expected = "echo 'Hello, World'" helper = CommandHelper(given) actual = helper.command self.assertEqual(expected, actual) def test_set_command_list_given(self) -> None: """ Tests the method which let us set the command to execute for the case that a list is given. """ given = ["echo", "'Hello, World'"] expected = "echo 'Hello, World'" self.helper.set_command(given) actual = self.helper.command self.assertEqual(expected, actual) def test_set_command_not_list_or_str(self) -> None: """ Tests the method which let us set the command to execute for the case that a list nor a str is given. """ given = True self.assertRaises(TypeError, lambda: self.helper.set_command(given)) def test_set_encoding_return(self) -> None: """ Tests the response from the method which let us set the encoding to use. """ given = "latin-1" actual = self.helper.set_encoding(given) self.assertIsInstance(actual, CommandHelper) def test_set_encoding_method(self) -> None: """ Tests the method which let us set the encoding to use. """ given = "latin-1" expected = "latin-1" self.helper.set_encoding(given) actual = self.helper.encoding self.assertEqual(expected, actual) def test_set_encoding_attribute(self) -> None: """ Tests overwritting of the :code:`encoding` attribute. """ given = "latin-1" expected = "latin-1" self.helper.encoding = given actual = self.helper.encoding self.assertEqual(expected, actual) def test_set_encoding_through_init(self) -> None: """ Tests the overwritting of the encoding to use through the class constructor. """ given = "latin-1" expected = "latin-1" helper = CommandHelper(encoding=given) actual = helper.encoding self.assertEqual(expected, actual) def test_set_encoding_not_str(self) -> None: """ Tests the method which let us set the encoding to use for the case that the given encoding is a string. """ given = ["hello", "world"] self.assertRaises(TypeError, lambda: self.helper.set_encoding(given)) def test_execute(self) -> None: """ Tests the method which executes a command. """ if PlatformUtility.is_unix(): given = "echo 'Hello, World!'" expected = "Hello, World!\n" actual = self.helper.set_command(given).execute() self.assertEqual(expected, actual) def test_execute_empty_output(self) -> None: """ Tests the method which executes a command for the case that the given command is empty. """ if PlatformUtility.is_unix(): expected = "" actual = self.helper.set_command("printf ''").execute() self.assertEqual(expected, actual) @unittest.mock.patch.object(Popen, "communicate") def test_execute_error(self, communicate_patch) -> None: """ Tests the method which executes a command for the case that an error is produced by the command. """ if PlatformUtility.is_unix(): expected = "This is an error." communicate_patch.return_value = (b"", b"This is an error.") given = "echo 'This is an error.' 1>&2" actual = CommandHelper(given).execute() self.assertEqual(expected, actual) @unittest.mock.patch.object(Popen, "communicate") def test_execute_error_exception(self, communicate_patch) -> None: """ Tests the method which executes a command for the case that an error is produced by the command and the end-user want an exception when such cases happen. """ if PlatformUtility.is_unix(): communicate_patch.return_value = (b"", b"This is an error.") given = "echo 'This is an error.' 1>&2" self.helper.set_command(given) self.assertRaises( RuntimeError, lambda: self.helper.execute(raise_on_error=True) ) def test_run(self) -> None: """ Tests the method which let us run a command. """ if PlatformUtility.is_unix(): expected = ["Hello, World!"] actual = list(CommandHelper("echo 'Hello, World!'").run()) self.assertEqual(expected, actual[:1]) def test_run_to_stdout(self) -> None: """ Tests the method which let us run a command an output to stdout. """ if PlatformUtility.is_unix(): expected = "Hello, World!\n" CommandHelper("echo 'Hello, World!'").run_to_stdout() actual = sys.stdout.getvalue() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/helpers/test_dict.py000066400000000000000000000376011467462152100216000ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our dictionnary helper. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 copy import os import tempfile import unittest from PyFunceble.helpers.dict import DictHelper class TestDictHelper(unittest.TestCase): """ Provides the test of our dictionnary helper. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.test_subject = { "Hello": "world", "World": {"world": "hello"}, "funilrys": ["Fun", "Ilrys"], "Py": "Funceble", "pyfunceble": ["funilrys"], } self.helper = DictHelper() def tearDown(self) -> None: """ Destroy everything needed by the tests. """ del self.test_subject del self.helper def test_set_subject_return(self) -> None: """ Tests the response from the method which let us set the subject to work with. """ actual = self.helper.set_subject(self.test_subject) self.assertIsInstance(actual, DictHelper) def test_set_subject_method(self) -> None: """ Tests the method which let us set the subject to work with. """ given = self.test_subject expected = dict(self.test_subject) self.helper.set_subject(given) actual = self.helper.subject self.assertEqual(expected, actual) def test_set_subject_attribute(self) -> None: """ Tests overwritting of the :code:`subject` attribute. """ given = self.test_subject expected = dict(self.test_subject) self.helper.subject = given actual = self.helper.subject self.assertEqual(expected, actual) def test_set_subject_through_init(self) -> None: """ Tests the overwritting of the subject to work through the class constructor. """ given = self.test_subject expected = dict(self.test_subject) helper = DictHelper(given) actual = helper.subject self.assertEqual(expected, actual) def test_has_same_key_as(self) -> None: """ Tests the method which let us know if the keys of 2 dicts are the same. """ origin = {"a": 1, "b": 1} target = {"a": 1, "b": 2, "c": {"a": 1, "b": 3, "c": {"x": "x"}}} expected = True actual = self.helper.set_subject(target).has_same_keys_as(origin) self.assertEqual(expected, actual) expected = False actual = self.helper.set_subject(origin).has_same_keys_as(target) self.assertEqual(expected, actual) origin["c"] = {"a": 1, "b": 3, "c": {"x": "x"}} expected = True actual = self.helper.set_subject(target).has_same_keys_as(origin) self.assertEqual(expected, actual) actual = self.helper.set_subject(origin).has_same_keys_as(target) self.assertEqual(expected, actual) del origin["c"]["c"] expected = False actual = self.helper.set_subject(origin).has_same_keys_as(target) self.assertEqual(expected, actual) def test_remove_key_not_dict(self) -> None: """ Tests the method which let us remove a key from a given dict for the case that the given subject is not a dict. """ given = "Hello" expected = "Hello" actual = self.helper.set_subject(given).remove_key("Py") self.assertEqual(expected, actual) def test_remove_key(self) -> None: """ Test the method which let us remove a key from a given dict. """ given = copy.deepcopy(self.test_subject) expected = { "Hello": "world", "World": {"world": "hello"}, "funilrys": ["Fun", "Ilrys"], "pyfunceble": ["funilrys"], } actual = self.helper.set_subject(given).remove_key("Py") self.assertEqual(expected, actual) actual = self.helper.set_subject(given).remove_key(["Py", "test"]) self.assertEqual(expected, actual) def test_remove_multiple_key(self) -> None: """ Tests the method which let us remove a key with multiple key to remove. """ given = copy.deepcopy(self.test_subject) expected = { "Hello": "world", "World": {"world": "hello"}, "pyfunceble": ["funilrys"], } actual = self.helper.set_subject(given).remove_key(["funilrys", "Py"]) self.assertEqual(expected, actual) def test_remove_key_not_exists(self) -> None: """ Tests the method which let us remove a key for the cas that the key to remove does not exists. """ given = copy.deepcopy(self.test_subject) expected = copy.deepcopy(self.test_subject) actual = self.helper.set_subject(given).remove_key("xxx.") self.assertEqual(expected, actual) def test_rename_key_not_dict(self) -> None: """ Tests the method which let us rename a key of a dict for the case that the given subject is not a dict. """ given = "Hello, World!" expected = "Hello, World!" actual = self.helper.set_subject(given).rename_key({"Py": "PyFunceble"}) self.assertEqual(expected, actual) def test_rename_key_strict_single(self) -> None: """ Tests the method which let us rename a key for the case that we only want to strictly rename one key. """ given = copy.deepcopy(self.test_subject) expected = { "Hello": "world", "World": {"world": "hello"}, "funilrys": ["Fun", "Ilrys"], "PyFunceble": "Funceble", "pyfunceble": ["funilrys"], } actual = self.helper.set_subject(given).rename_key( {"Py": "PyFunceble"}, strict=True ) self.assertEqual(expected, actual) def test_rename_key_not_strict_single(self) -> None: """ Tests the method which let us rename a key for the case that we only want to rename all occurrences of the given key. """ given = copy.deepcopy(self.test_subject) expected = { "Hello": "world", "World": {"world": "hello"}, "nuilrys": ["Fun", "Ilrys"], "Py": "Funceble", "nuceble": ["funilrys"], } actual = self.helper.set_subject(given).rename_key({"fun": "nuf"}, strict=False) self.assertEqual(expected, actual) def test_to_and_from_json_file(self) -> None: """ Tests the method which let us save and load a dict into/from a JSON file. """ output_file = tempfile.NamedTemporaryFile("w", delete=False) given = copy.deepcopy(self.test_subject) expected = copy.deepcopy(self.test_subject) self.helper.set_subject(given).to_json_file(output_file.name) output_file.seek(0) actual = self.helper.from_json_file(output_file.name) self.assertEqual(expected, actual) output_file.close() os.remove(output_file.name) def test_from_json_file_not_json(self) -> None: """ Tests the method which let us load a JSON file for the case that no JSON file is given. """ output_file = tempfile.NamedTemporaryFile("wb", delete=False) output_file.write(b"Hello, World!") output_file.seek(0) expected = dict() # pylint: disable=use-dict-literal actual = self.helper.from_json_file(output_file.name) self.assertEqual(expected, actual) output_file.close() os.remove(output_file.name) def test_to_json(self) -> None: """ Tests the method which let us convert a dict to a JSON and vice-versa. """ given = copy.deepcopy(self.test_subject) expected = """{ "Hello": "world", "Py": "Funceble", "World": { "world": "hello" }, "funilrys": [ "Fun", "Ilrys" ], "pyfunceble": [ "funilrys" ] }""" actual = self.helper.set_subject(given).to_json() self.assertIsInstance(actual, str) self.assertEqual(expected, actual) actual = self.helper.from_json(expected) expected = copy.deepcopy(self.test_subject) self.assertEqual(expected, actual) def test_from_json_not_json(self) -> None: """ Tests the method which let us convert a JSON to a JSON for the case that no JSON is given. """ given = "Hello, World!" expected = dict() # pylint: disable=use-dict-literal actual = self.helper.from_json(given) self.assertEqual(expected, actual) def test_from_yaml_file(self) -> None: """ Tests the method which let us save and load a dict into/from a YAML file. """ output_file = tempfile.NamedTemporaryFile("w", delete=False) given = copy.deepcopy(self.test_subject) expected = copy.deepcopy(self.test_subject) self.helper.set_subject(given).to_yaml_file(output_file.name) output_file.seek(0) actual = self.helper.from_yaml_file(output_file.name) self.assertEqual(expected, actual) output_file.close() os.remove(output_file.name) def test_to_yaml(self) -> None: """ Tests the method which let us convert a dict into a YAML and vice-versa. """ expected = """Hello: world Py: Funceble World: world: hello funilrys: - Fun - Ilrys pyfunceble: - funilrys """ given = copy.deepcopy(self.test_subject) actual = self.helper.set_subject(given).to_yaml() self.assertEqual(expected, actual) actual = self.helper.from_yaml(expected) expected = copy.deepcopy(self.test_subject) self.assertEqual(expected, actual) def test_flatten(self) -> None: """ Tests the method which let us flatten a dict. """ expected = { "Hello": "world", "World.world": "hello", "funilrys": ["Fun", "Ilrys"], "Py": "Funceble", "pyfunceble": ["funilrys"], } actual = self.helper.set_subject(self.test_subject).flatten() self.assertEqual(expected, actual) def test_deeper_flatten(self) -> None: """ Tests the method which let us flatten a dict with more level. """ given = { "Hello": "world", "World": {"world": "hello"}, "funilrys": ["Fun", "Ilrys"], "Py": "Funceble", "pyfunceble": ["funilrys"], "this": { "is": { "a": { "test": { "id": 1, "deep": {"hello": {"world": ["Hello!"]}}, "response": "World", } }, "b": 1, "c": [{"hello": {"this": {"is": "a test"}}}], } }, "": {"hello-fun": "world", "": "hehe"}, } expected = { "Hello": "world", "World.world": "hello", "funilrys": ["Fun", "Ilrys"], "Py": "Funceble", "pyfunceble": ["funilrys"], "this.is.a.test.deep.hello.world": ["Hello!"], "this.is.a.test.id": 1, "this.is.a.test.response": "World", "this.is.b": 1, "this.is.c": [{"hello": {"this": {"is": "a test"}}}], "..": "hehe", ".hello-fun": "world", } actual = self.helper.set_subject(given).flatten() self.assertEqual(expected, actual) def test_unflatten(self) -> None: """ Tests the method which let us unflatten a dict. """ given = { "Hello": "world", "World.world": "hello", "funilrys": ["Fun", "Ilrys"], "Py": "Funceble", "pyfunceble": ["funilrys"], } expected = dict(self.test_subject) actual = self.helper.set_subject(given).unflatten() self.assertEqual(expected, actual) def test_deeper_unflatten(self) -> None: """ Tests the method which let us unflatten a dict with more level. """ given = { "Hello": "world", "World.world": "hello", "funilrys": ["Fun", "Ilrys"], "Py": "Funceble", "pyfunceble": ["funilrys"], "this.is.a.test.deep.hello.world": ["Hello!"], "this.is.a.test.id": 1, "this.is.a.test.response": "World", "this.is.b": 1, "this.is.c": [{"hello": {"this": {"is": "a test"}}}], "..": "hehe", ".hello-fun": "world", } expected = { "Hello": "world", "World": {"world": "hello"}, "funilrys": ["Fun", "Ilrys"], "Py": "Funceble", "pyfunceble": ["funilrys"], "this": { "is": { "a": { "test": { "id": 1, "deep": {"hello": {"world": ["Hello!"]}}, "response": "World", } }, "b": 1, "c": [{"hello": {"this": {"is": "a test"}}}], } }, "": {"hello-fun": "world", "": "hehe"}, } actual = self.helper.set_subject(given).unflatten() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/helpers/test_directory.py000066400000000000000000000242401467462152100226540ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the directory helper. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 os import secrets import tempfile import unittest import unittest.mock from PyFunceble.helpers.directory import DirectoryHelper from PyFunceble.helpers.list import ListHelper from PyFunceble.utils.platform import PlatformUtility class TestDirectoryHelper(unittest.TestCase): """ Tests of the directory helper. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.temp_path = tempfile.TemporaryDirectory() self.helper = DirectoryHelper(path=self.temp_path.name) def tearDown(self) -> None: """ Destroys everything needed for the tests. """ del self.helper self.temp_path.cleanup() del self.temp_path def test_set_path_return(self) -> None: """ Tests the response from the method which let us set the path to work with. """ actual = self.helper.set_path(self.temp_path.name) self.assertIsInstance(actual, DirectoryHelper) def test_set_path_method(self) -> None: """ Tests the method which let us set the path to work with. """ given = self.temp_path.name expected = self.temp_path.name self.helper.set_path(given) actual = self.helper.path self.assertEqual(expected, actual) def test_set_path_attribute(self) -> None: """ Tests overwritting of the :code:`path` attribute. """ given = self.temp_path.name expected = self.temp_path.name self.helper.path = given actual = self.helper.path self.assertEqual(expected, actual) def test_set_path_through_init(self) -> None: """ Tests the overwritting of the path to work through the class constructor. """ given = self.temp_path.name expected = self.temp_path.name helper = DirectoryHelper(given) actual = helper.path self.assertEqual(expected, actual) def test_set_path_not_str(self) -> None: """ Tests the method which let us set the path to work with for the case that it's not a string. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.helper.set_path(given)) def test_realpath(self) -> None: """ Tests the method which let us get the real path to the currently set path. """ expected = os.path.realpath(self.temp_path.name) actual = self.helper.realpath self.assertEqual(expected, actual) @unittest.mock.patch.object(os, "getcwd") def test_get_current(self, getcwd_path: unittest.mock.MagicMock) -> None: """ Tests the method which let us get the current directory. """ getcwd_path.return_value = "/hello/world" expected = "/hello/world" actual = self.helper.get_current() self.assertEqual(expected, actual) @unittest.mock.patch.object(os, "getcwd") def test_get_current_with_sep(self, getcwd_path: unittest.mock.MagicMock) -> None: """ Tests the method which let us get the current directory for the case that we want to have the directory separator at the end. """ getcwd_path.return_value = "/hello/world" if PlatformUtility.is_windows(): expected = "/hello/world\\" else: expected = "/hello/world/" actual = self.helper.get_current(with_end_sep=True) self.assertEqual(expected, actual) def test_join_path(self) -> None: """ Tests the method which let us join paths. """ if PlatformUtility.is_windows(): given = "\\hello\\world" expected = "\\hello\\world\\hello\\world" else: given = "/hello/world" expected = "/hello/world/hello/world" actual = DirectoryHelper(given).join_path("hello", "world") self.assertEqual(expected, actual) def test_exists(self) -> None: """ Tests the method which let check if a directory exists. """ self.helper.set_path(self.helper.join_path(secrets.token_urlsafe(8))) expected = False actual = self.helper.exists() self.assertEqual(expected, actual) expected = True os.makedirs(self.helper.path) actual = self.helper.exists() self.assertEqual(expected, actual) def test_create_and_delete(self) -> None: """ Tests the methods which let us create and delete a directory. """ self.helper.set_path(self.helper.join_path(secrets.token_urlsafe(8))) expected = False actual = self.helper.exists() self.assertEqual(expected, actual) expected = True actual = self.helper.create().exists() self.assertEqual(expected, actual) expected = False actual = self.helper.delete().exists() self.assertEqual(expected, actual) def test_list_all_subdirectories(self) -> None: """ Tests the method which let us list all subdirectories. """ dirname = [secrets.token_hex(6) for _ in range(10)] for directory in dirname: self.helper.set_path(os.path.join(self.temp_path.name, directory)).create() self.helper.set_path( os.path.join(self.temp_path.name, directory, directory) ).create() self.helper.set_path( os.path.join(self.temp_path.name, directory, directory, directory) ).create() self.helper.set_path(self.temp_path.name) expected = ( ListHelper( [os.path.join(self.temp_path.name, x) for x in dirname] + [os.path.join(self.temp_path.name, x, x) for x in dirname] + [os.path.join(self.temp_path.name, x, x, x) for x in dirname] ) .remove_duplicates() .sort() .subject ) actual = self.helper.list_all_subdirectories() self.assertEqual(expected, actual) def test_list_all_files(self) -> None: """ Tests the method which let us list all subdirectories. """ dirname = [secrets.token_hex(6) for _ in range(10)] filename = secrets.token_hex(6) for directory in dirname: self.helper.set_path(os.path.join(self.temp_path.name, directory)).create() with open( os.path.join(self.helper.path, filename), "w", encoding="utf-8" ) as file_stream: file_stream.write("Hello") self.helper.set_path( os.path.join(self.temp_path.name, directory, directory) ).create() with open( os.path.join(self.helper.path, filename), "w", encoding="utf-8" ) as file_stream: file_stream.write("Hello") self.helper.set_path( os.path.join(self.temp_path.name, directory, directory, directory) ).create() with open( os.path.join(self.helper.path, filename), "w", encoding="utf-8" ) as file_stream: file_stream.write("Hello") self.helper.set_path(self.temp_path.name) expected = ( ListHelper( [os.path.join(self.temp_path.name, x, filename) for x in dirname] + [os.path.join(self.temp_path.name, x, x, filename) for x in dirname] + [ os.path.join(self.temp_path.name, x, x, x, filename) for x in dirname ] ) .sort() .subject ) actual = self.helper.list_all_files() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/helpers/test_download.py000066400000000000000000000213701467462152100224600ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the download helper. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 tempfile import unittest import unittest.mock import requests import PyFunceble.helpers.exceptions from PyFunceble.helpers.download import DownloadHelper class TestDownloadHelper(unittest.TestCase): """ Tests of the download helper. """ def test_set_url_return(self) -> None: """ Tests the response of the method which let us set the url to work with. """ given = "https://example.org" download_helper = DownloadHelper() actual = download_helper.set_url(given) self.assertIsInstance(actual, DownloadHelper) def test_set_url(self) -> None: """ Tests the method which let us set the url to work with. """ given = "https://example.org" expected = "https://example.org" download_helper = DownloadHelper() download_helper.set_url(given) actual = download_helper.url self.assertEqual(expected, actual) download_helper = DownloadHelper(given) actual = download_helper.url self.assertEqual(expected, actual) def test_set_url_not_str(self) -> None: """ Tests the method which let us set the url to work with for the case that the given url is not a string. """ given = ["Hello", "World"] download_helper = DownloadHelper() self.assertRaises(TypeError, lambda: download_helper.set_url(given)) def test_set_certificate_validation_return(self) -> None: """ Tests the response of the method which let us authorize the certificate validation. """ given = True download_helper = DownloadHelper() actual = download_helper.set_certificate_validation(given) self.assertIsInstance(actual, DownloadHelper) def test_set_certificate_validation(self) -> None: """ Tests the method which let us authorize the certificate validation. """ given = True expected = True download_helper = DownloadHelper() download_helper.set_certificate_validation(given) actual = download_helper.certificate_validation self.assertEqual(expected, actual) download_helper = DownloadHelper(certificate_validation=given) actual = download_helper.certificate_validation self.assertEqual(expected, actual) def test_set_certificate_validation_not_bool(self) -> None: """ Tests the method which let us authorize the certificate validation for the case that the given value is not a boolean. """ given = ["Hello", "World"] download_helper = DownloadHelper() self.assertRaises( TypeError, lambda: download_helper.set_certificate_validation(given) ) def test_set_retries_return(self) -> None: """ Tests the response of the method which let us set the number of retry to perform. """ given = 3 download_helper = DownloadHelper() actual = download_helper.set_retries(given) self.assertIsInstance(actual, DownloadHelper) def test_set_retries(self) -> None: """ Tests the method which let us set the number of retry to perform. """ given = 3 expected = 3 download_helper = DownloadHelper() download_helper.set_retries(given) actual = download_helper.retries self.assertEqual(expected, actual) download_helper = DownloadHelper(retries=given) actual = download_helper.retries self.assertEqual(expected, actual) def test_set_retries_not_int(self) -> None: """ Tests the method which let us set the number of retry to perform for the case that the given value is not a string. """ given = ["Hello", "World"] download_helper = DownloadHelper() self.assertRaises(TypeError, lambda: download_helper.set_retries(given)) def test_set_retries_less_than_zero(self) -> None: """ Tests the method which let us set the number of retry to perform for the case that the given value is less than zero """ given = -1 download_helper = DownloadHelper() self.assertRaises(ValueError, lambda: download_helper.set_retries(given)) @unittest.mock.patch.object(requests.Session, "get") def test_download_text(self, session_patch: unittest.mock.MagicMock) -> None: """ Tests the method which let us set download the text of a given url. """ given = "https://exmaple.org" download_helper = DownloadHelper(given) session_patch.return_value.text = "Hello, World!" session_patch.return_value.status_code = 200 expected = "Hello, World!" actual = download_helper.download_text() self.assertEqual(expected, actual) @unittest.mock.patch.object(requests.Session, "get") def test_download_text_to_file( self, session_patch: unittest.mock.MagicMock ) -> None: """ Tests the method which let us set download the text of a given url for the case that we want the response into a file. """ destination = tempfile.NamedTemporaryFile(delete=False) given = "https://exmaple.org" download_helper = DownloadHelper(given) session_patch.return_value.text = "Hello, World!" session_patch.return_value.status_code = 200 download_helper.download_text(destination=destination.name) destination.seek(0) expected = b"Hello, World!" actual = destination.read() self.assertEqual(expected, actual) @unittest.mock.patch.object(requests.Session, "get") def test_download_text_response_not_ok( self, session_patch: unittest.mock.MagicMock ) -> None: """ Tests the method which let us set download the text of a given url for the case that the response is not ok. """ destination = tempfile.NamedTemporaryFile(delete=False) given = "https://exmaple.org" download_helper = DownloadHelper(given) session_patch.return_value.status_code = 500 self.assertRaises( PyFunceble.helpers.exceptions.UnableToDownload, lambda: download_helper.download_text(destination=destination.name), ) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/helpers/test_environment_variable.py000066400000000000000000000272261467462152100250700ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the tests of our environment variable helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 os import tempfile import unittest from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper class TestEnvironmentVariableHelper(unittest.TestCase): """ Tests of our environment variable helper. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.helper = EnvironmentVariableHelper() self.test_name = "PYFUNCEBLE_TESTING" self.temp_env_file = tempfile.NamedTemporaryFile("w", delete=False) def tearDown(self) -> None: """ Destroys everything needed for the tests. """ self.temp_env_file.close() os.remove(self.temp_env_file.name) del self.temp_env_file del self.test_name del self.helper def test_set_name_return(self) -> None: """ Tests the response from the method which let us set the name to work with. """ actual = self.helper.set_name(self.test_name) self.assertIsInstance(actual, EnvironmentVariableHelper) def test_set_name_method(self) -> None: """ Tests the method which let us set the name to work with. """ given = self.test_name expected = given self.helper.set_name(given) actual = self.helper.name self.assertEqual(expected, actual) def test_set_name_attribute(self) -> None: """ Tests the method which let us overwrite the `name` attribute. """ given = self.test_name expected = given self.helper.name = given actual = self.helper.name self.assertEqual(expected, actual) def test_set_name_through_init(self) -> None: """ Tests the overwritting of the name to work with through the class constructor. """ given = self.test_name expected = given helper = EnvironmentVariableHelper(given) actual = helper.name self.assertEqual(expected, actual) def test_set_env_file_path_return(self) -> None: """ Tests the response from the method which let us set the path to the dot env file to work with. """ actual = self.helper.set_env_file_path(self.temp_env_file.name) self.assertIsInstance(actual, EnvironmentVariableHelper) def test_set_env_file_path_method(self) -> None: """ Tests the method which let us set the path to the dotenv file to work with. """ given = self.temp_env_file.name expected = given self.helper.set_env_file_path(given) actual = self.helper.env_file_path self.assertEqual(expected, actual) def test_set_env_file_path_attribute(self) -> None: """ Tests the method which let us overwrite the `env_file_path` attribute. """ given = self.temp_env_file.name expected = given self.helper.env_file_path = given actual = self.helper.env_file_path self.assertEqual(expected, actual) def test_set_env_file_path_through_init(self) -> None: """ Tests the overwritting of the dotenv file to work with through the class constructor. """ given = self.temp_env_file.name expected = given helper = EnvironmentVariableHelper(env_file_path=given) actual = helper.env_file_path self.assertEqual(expected, actual) def test_set_name_not_str(self) -> None: """ Tests the method which let us set the name of the environment variable to work with for the case that the given name is not a string. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.helper.set_name(given)) def test_set_env_file_path_not_str(self) -> None: """ Tests the method which let us set the path to the dotenv file to work with for the case that the given path is not a string. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.helper.set_env_file_path(given)) def test_exists(self) -> None: """ Tests of the method which let us test if an environment variable exists. """ expected = False actual = self.helper.set_name(self.test_name).exists() self.assertEqual(expected, actual) os.environ[self.test_name] = "This is a test." expected = True actual = self.helper.exists() self.assertEqual(expected, actual) del os.environ[self.test_name] def test_get_value(self) -> None: """ Tests of the method which let us get the value of an environment variable. """ expected = False actual = self.helper.set_name(self.test_name).exists() self.assertEqual(expected, actual) expected = "Hello" actual = self.helper.get_value(default="Hello") self.assertEqual(expected, actual) expected = "This is a test." os.environ[self.test_name] = "This is a test." actual = self.helper.get_value(default="Hello") self.assertEqual(expected, actual) del os.environ[self.test_name] def test_get_value_from_file(self) -> None: """ Tests of the method which let us get the value of an environment variable from a given environment file. """ self.temp_env_file.write("IS_THIS_A_GHOST=yes\n") self.temp_env_file.seek(0) self.helper.set_env_file_path(self.temp_env_file.name) self.helper.set_name("IS_THIS_A_GHOST") expected = "yes" actual = self.helper.get_value_from_env_file() self.assertEqual(expected, actual) def test_get_value_from_file_not_found(self) -> None: """ Tests of the method which let us get the value of an environment variable from a given environment file. In this case, we test the case that the given value is not known. """ self.temp_env_file.write("IS_THIS_A_GHOST_NOOOO=yes") self.temp_env_file.seek(0) self.helper.set_env_file_path(self.temp_env_file.name) self.helper.set_name("IS_THIS_A_GHOST") expected = "hello" actual = self.helper.get_value_from_env_file(default="hello") self.assertEqual(expected, actual) def test_set_value(self) -> None: """ Tests of the method which let us set the value of an environment variable. """ expected = False actual = self.helper.set_name(self.test_name).exists() self.assertEqual(expected, actual) self.helper.set_value("Hello, World!") expected = "Hello, World!" actual = self.helper.get_value() self.assertEqual(expected, actual) del os.environ[self.test_name] def test_set_value_in_env_file(self) -> None: """ Tests of the method which let us set the value of an environment variable into a file. """ self.helper.set_env_file_path(self.temp_env_file.name) self.helper.set_name("GHOST_FINDER") self.assertIsNone(self.helper.get_value()) expected = 'GHOST_FINDER="no"\n' self.helper.set_value_in_env_file("no") with open(self.temp_env_file.name, "r", encoding="utf-8") as file_stream: self.assertTrue("no" in file_stream.read()) expected = "no" self.assertEqual(expected, self.helper.get_value()) def test_set_value_not_str(self) -> None: """ Tests of the method which let us set the value of an environment variable for the case that the given value to set is not a string. """ expected = False actual = self.helper.set_name(self.test_name).exists() self.assertEqual(expected, actual) self.assertRaises(TypeError, lambda: self.helper.set_value(["Hello", "World!"])) def test_delete(self) -> None: """ Tests of the method which let us delete an environment variable. """ expected = False actual = self.helper.set_name(self.test_name).exists() self.assertEqual(expected, actual) self.helper.set_value("Hello, World!") expected = True actual = self.helper.exists() self.assertEqual(expected, actual) self.helper.delete() expected = False actual = self.helper.exists() self.assertEqual(expected, actual) def test_delete_value_in_env_file(self) -> None: """ Tests of the method which let us delete the value of an environment variable into a file. """ self.temp_env_file.write("GHOST_SPEAKER=yes\n") self.helper.set_env_file_path(self.temp_env_file.name) self.helper.set_name("GHOST_SPEAKER") self.helper.set_value("no") with open(self.temp_env_file.name, "r", encoding="utf-8") as file_stream: self.assertTrue(self.helper.name in x for x in file_stream.readlines()) self.helper.delete_from_env_file() with open(self.temp_env_file.name, "r", encoding="utf-8") as file_stream: self.assertTrue(self.helper.name not in x for x in file_stream.readlines()) self.assertIsNone(self.helper.get_value()) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/helpers/test_file.py000066400000000000000000000325101467462152100215660ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the file helper. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 os import secrets import tempfile import unittest from PyFunceble.helpers.file import FileHelper from PyFunceble.utils.platform import PlatformUtility class TestFileHelper(unittest.TestCase): """ Tests of the file helpers. """ def test_set_path_return(self) -> None: """ Tests the response from the method which let us set the path to work with. """ given = tempfile.NamedTemporaryFile() file_helper = FileHelper() actual = file_helper.set_path(given.name) self.assertIsInstance(actual, FileHelper) def test_set_path(self) -> None: """ Tests the method which let us set the path to work with. """ given = tempfile.NamedTemporaryFile() expected = given.name file_helper = FileHelper() file_helper.set_path(given.name) actual = file_helper.path self.assertEqual(expected, actual) file_helper = FileHelper(given.name) actual = file_helper.path self.assertEqual(expected, actual) def test_set_path_not_str(self) -> None: """ Tests the method which let us set the path to work with for the case that it's not a string. """ given = ["Hello", "World"] file_helper = FileHelper() self.assertRaises(TypeError, lambda: file_helper.set_path(given)) def test_join_path(self) -> None: """ Tests the method which let us join paths. """ given = "/hello/world" if PlatformUtility.is_windows(): expected = "/hello/world\\hello\\world" else: expected = "/hello/world/hello/world" actual = FileHelper(given).join_path("hello", "world") self.assertEqual(expected, actual) def test_exists(self) -> None: """ Tests the method which let us check if the given file exists. """ file_helper = FileHelper(tempfile.gettempdir()) file_helper.set_path(file_helper.join_path(secrets.token_hex(8))) expected = False actual = file_helper.exists() self.assertEqual(expected, actual) with open(file_helper.path, "w", encoding="utf-8") as file_stream: file_stream.write("Hello, World!") expected = True actual = file_helper.exists() self.assertEqual(expected, actual) os.remove(file_helper.path) expected = False actual = file_helper.exists() self.assertEqual(expected, actual) def test_get_size(self) -> None: """ Tests the method which let us get the size of a file. """ file_helper = FileHelper(tempfile.gettempdir()) file_helper.set_path(file_helper.join_path(secrets.token_hex(8))) expected = False actual = file_helper.exists() self.assertEqual(expected, actual) with open(file_helper.path, "w", encoding="utf-8") as file_stream: file_stream.write("Hello, World!") expected = True actual = file_helper.exists() self.assertEqual(expected, actual) expected = 13 actual = file_helper.get_size() self.assertEqual(expected, actual) os.remove(file_helper.path) def test_is_empty(self) -> None: """ Tests the method which let us check if a file is empty. """ file_helper = FileHelper(tempfile.gettempdir()) file_helper.set_path(file_helper.join_path(secrets.token_hex(8))) expected = False actual = file_helper.exists() self.assertEqual(expected, actual) with open(file_helper.path, "w", encoding="utf-8") as file_stream: file_stream.write("") expected = True actual = file_helper.is_empty() self.assertEqual(expected, actual) with open(file_helper.path, "w", encoding="utf-8") as file_stream: file_stream.write("Hello, World!") expected = False actual = file_helper.is_empty() self.assertEqual(expected, actual) os.remove(file_helper.path) def test_delete(self) -> None: """ Tests the method which let us delete a file. """ file_helper = FileHelper(tempfile.gettempdir()) file_helper.set_path(file_helper.join_path(secrets.token_hex(8))) expected = False actual = file_helper.exists() self.assertEqual(expected, actual) with open(file_helper.path, "w", encoding="utf-8") as file_stream: file_stream.write("") expected = True actual = file_helper.exists() self.assertEqual(expected, actual) file_helper.delete() expected = False actual = file_helper.exists() self.assertEqual(expected, actual) def test_write(self) -> None: """ Tests the method which let us write a file. """ given = tempfile.NamedTemporaryFile(delete=False) file_helper = FileHelper(given.name) file_helper.write("Hello, World!") given.seek(0) expected = b"Hello, World!" actual = given.read() self.assertEqual(expected, actual) file_helper.write("Hello, this is Funilrys!") given.seek(0) expected = b"Hello, World!Hello, this is Funilrys!" actual = given.read() self.assertEqual(expected, actual) file_helper.write("Hello, World!", overwrite=True) given.seek(0) expected = b"Hello, World!" actual = given.read() self.assertEqual(expected, actual) def test_read(self) -> None: """ Tests the method which let us read a file. """ given = tempfile.NamedTemporaryFile(delete=False) file_helper = FileHelper(given.name) file_helper.write("Hello, World!") given.seek(0) expected = "Hello, World!" actual = file_helper.read() self.assertEqual(expected, actual) def test_read_file_does_not_exists(self) -> None: """ Tests the method which let us read a file for the case that the given file does not exists. """ file_helper = FileHelper(tempfile.gettempdir()) file_helper.set_path(file_helper.join_path(secrets.token_hex(8))) expected = False actual = file_helper.exists() self.assertEqual(expected, actual) expected = None actual = file_helper.read() self.assertEqual(expected, actual) def test_read_bytes(self) -> None: """ Tests the method which let us read (bytes) a file. """ given = tempfile.NamedTemporaryFile(delete=False) file_helper = FileHelper(given.name) file_helper.write("Hello, World!") given.seek(0) expected = b"Hello, World!" actual = file_helper.read_bytes() self.assertEqual(expected, actual) def test_read_bytes_file_does_not_exists(self) -> None: """ Tests the method which let us read (bytes) a file for the case that the given file does not exists. """ file_helper = FileHelper(tempfile.gettempdir()) file_helper.set_path(file_helper.join_path(secrets.token_hex(8))) expected = False actual = file_helper.exists() self.assertEqual(expected, actual) expected = None actual = file_helper.read_bytes() self.assertEqual(expected, actual) def test_open(self) -> None: """ Tests the method which let us open the given file as we want. """ file_helper = FileHelper(tempfile.gettempdir()) file_helper.set_path(file_helper.join_path(secrets.token_hex(8))) expected = False actual = file_helper.exists() self.assertEqual(expected, actual) with file_helper.open("w") as file_stream: file_stream.write("Hello, World!") expected = True actual = file_helper.exists() self.assertEqual(expected, actual) expected = "Hello, World!" actual = file_helper.read() self.assertEqual(expected, actual) def test_copy(self) -> None: """ Tests the method which let us copy a file to another place. """ file_helper = FileHelper(tempfile.gettempdir()) file_helper.set_path(file_helper.join_path(secrets.token_hex(8))) copy_file_helper = FileHelper(tempfile.gettempdir()) copy_file_helper.set_path(copy_file_helper.join_path(secrets.token_hex(8))) expected = False actual = file_helper.exists() actual_copy = copy_file_helper.exists() self.assertEqual(expected, actual) self.assertEqual(expected, actual_copy) file_helper.write("Hello, World!") expected = True actual = file_helper.exists() self.assertEqual(expected, actual) expected = False actual_copy = copy_file_helper.exists() self.assertEqual(expected, actual_copy) file_helper.copy(copy_file_helper.path) expected = True actual_copy = copy_file_helper.exists() self.assertEqual(expected, actual_copy) expected = "Hello, World!" actual = copy_file_helper.read() self.assertEqual(expected, actual) expected = True actual = file_helper.exists() actual_copy = copy_file_helper.exists() self.assertEqual(expected, actual) self.assertEqual(expected, actual_copy) def test_move(self) -> None: """ Tests of the method which let us move a file to another location. """ file_helper = FileHelper(tempfile.gettempdir()) file_helper.set_path(file_helper.join_path(secrets.token_hex(8))) destination_file_helper = FileHelper(tempfile.gettempdir()) destination_file_helper.set_path( destination_file_helper.join_path(secrets.token_hex(8)) ) expected = False actual = file_helper.exists() actual_destination = destination_file_helper.exists() self.assertEqual(expected, actual) self.assertEqual(expected, actual_destination) file_helper.write("Hello, World!") expected = True actual = file_helper.exists() self.assertEqual(expected, actual) expected = False actual_destination = destination_file_helper.exists() self.assertEqual(expected, actual_destination) file_helper.move(destination_file_helper.path) expected = True actual_destination = destination_file_helper.exists() self.assertEqual(expected, actual_destination) expected = "Hello, World!" actual = destination_file_helper.read() self.assertEqual(expected, actual) expected = False actual = file_helper.exists() self.assertEqual(expected, actual) expected = True actual_destination = destination_file_helper.exists() self.assertEqual(expected, actual_destination) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/helpers/test_hash.py000066400000000000000000000143651467462152100216020ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the hash helper. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 tempfile import unittest from PyFunceble.helpers.hash import HashHelper class TestHashHelper(unittest.TestCase): """ Tests our hash helpers. """ def setUp(self) -> None: """ Setups everything needed by the tests. """ self.hashing_subject = ["Hello World!", "Thanks for using PyFunceble"] self.hashing_table = { "md5": "ba2e0e1774c2e60e2327f263402facd4", "sha1": "b5c8520cd2c422019997dc6fdbc9cb9d7002356e", "sha224": "863c46d5ed52b439da8f62a791e77c0cbbfb7d92af7c5549279f580d", "sha384": "6492f4b5732e0af4b9edf2c29ee4622c62ee418e5d6e0f34b13cb80560a28256c6e21e949119872d26d2327fc112a63b", # pylint: disable=line-too-long "sha512": "f193ad6ee2cfbecd580225d8e6bfb9df1910e5ca6135b21b03ae208a007f71e9b57b55e299d27157551a18ef4dfdde23c96aaea796064846edc6cd25ac7eaf7f", # pylint: disable=line-too-long "sha512_224": "7c43867047942e9d441f5e3e29ad63ad579bc038bf9eba925ff6896b", } def tearDown(self) -> None: """ Destroys everything which was setup for the tests. """ del self.hashing_table del self.hashing_subject def test_set_algo_return(self) -> None: """ Tests the response from the method which let us set the algoritm to work with. """ given = "SHA512_224" hash_helper = HashHelper() actual = hash_helper.set_algo(given) self.assertIsInstance(actual, HashHelper) def test_set_algo(self) -> None: """ Tests the method which let us set the algorithm to work with. """ given = "SHA512_224" expected = "SHA512_224" hash_helper = HashHelper() hash_helper.set_algo(given) actual = hash_helper.algo self.assertEqual(expected, actual) hash_helper = HashHelper(given) actual = hash_helper.algo self.assertEqual(expected, actual) def test_set_algo_not_str(self) -> None: """ Tests the method which let us set the the algorithm to work with. """ given = ["Hello", "World"] hash_helper = HashHelper() self.assertRaises(TypeError, lambda: hash_helper.set_algo(given)) def test_set_algo_not_valid(self) -> None: """ Tests the method which let us set the the algorithm to work with. """ given = "Hello" hash_helper = HashHelper() self.assertRaises(ValueError, lambda: hash_helper.set_algo(given)) def test_hash_data(self) -> None: """ Tests the method which let us get the hash of a given data. """ given = "\n".join(self.hashing_subject) hash_helper = HashHelper() for algo, expected in self.hashing_table.items(): actual = hash_helper.set_algo(algo).hash_data(given) self.assertEqual(expected, actual) actual = hash_helper.hash_data(given.encode()) self.assertEqual(expected, actual) def test_hash_data_wrong_type(self) -> None: """ Tests the method which let us get the hash of a given data for the case that the given data is not a bytes nor a string. """ given = 0 hash_helper = HashHelper() self.assertRaises(TypeError, lambda: hash_helper.hash_data(given)) def test_hash_file(self) -> None: """ Tests the method which let us hash the content of a given file. """ our_file = tempfile.NamedTemporaryFile(delete=False) our_file.write("\n".join(self.hashing_subject).encode()) our_file.seek(0) hash_helper = HashHelper() for algo, expected in self.hashing_table.items(): actual = hash_helper.set_algo(algo).hash_file(our_file.name) self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/helpers/test_list.py000066400000000000000000000165321467462152100216300ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our list helper. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 copy import unittest from PyFunceble.helpers.list import ListHelper class TestListHelper(unittest.TestCase): """ Provides the test of our dictionnary helper. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.helper = ListHelper() self.mixed_test_subject = [ ("Hello", "World"), "Hello", {"hello": "world"}, "World", 1, 4.5, None, "", ] self.str_test_subject = [ "hello", "world", "", "!", " ", "hello", "world!", "Hello", ] def tearDown(self) -> None: """ Destroy everything needed by the tests. """ del self.mixed_test_subject del self.str_test_subject def test_set_subject_return(self) -> None: """ Tests the response from the method which let us set the subject to work with. """ actual = self.helper.set_subject(self.mixed_test_subject) self.assertIsInstance(actual, ListHelper) def test_set_subject_method(self) -> None: """ Tests the method which let us set the subject to work with. """ given = self.mixed_test_subject expected = list(self.mixed_test_subject) self.helper.set_subject(given) actual = self.helper.subject self.assertEqual(expected, actual) def test_set_subject_attribute(self) -> None: """ Tests overwritting of the :code:`subject` attribute. """ given = self.mixed_test_subject expected = list(self.mixed_test_subject) self.helper.subject = given actual = self.helper.subject self.assertEqual(expected, actual) def test_set_subject_through_init(self) -> None: """ Tests the overwritting of the subject to work through the class constructor. """ given = self.mixed_test_subject expected = given helper = ListHelper(given) actual = helper.subject self.assertEqual(expected, actual) def test_set_subject_not_list(self) -> None: """ Tests the response of the method which let us set the subject for the case that the given subject is not a list. """ given = {"Hello": "World"} self.assertRaises(TypeError, lambda: self.helper.set_subject(given)) def test_remove_empty(self) -> None: """ Tests the method which let us remove the empty strings from a given list. """ given = copy.deepcopy(self.str_test_subject) expected = ["hello", "world", "!", " ", "hello", "world!", "Hello"] actual = self.helper.set_subject(given).remove_empty().subject self.assertEqual(expected, actual) given = copy.deepcopy(self.mixed_test_subject) expected = [ ("Hello", "World"), "Hello", {"hello": "world"}, "World", 1, 4.5, None, ] actual = self.helper.set_subject(given).remove_empty().subject self.assertEqual(expected, actual) def test_remove_duplicates(self) -> None: """ Tests the method which let us remove the duplicates from a given list. """ given = copy.deepcopy(self.str_test_subject) expected = ["hello", "world", "", "!", " ", "world!", "Hello"] actual = self.helper.set_subject(given).remove_duplicates().subject self.assertEqual(expected, actual) def test_sort(self) -> None: """ Tests the method which let us sort a given list. """ given = copy.deepcopy(self.str_test_subject) expected = [ "", " ", "!", "hello", "hello", "Hello", "world", "world!", ] actual = self.helper.set_subject(given).sort().subject self.assertEqual(expected, actual) def test_sort_reverse(self) -> None: """ Tests the method which let us sort a given list. """ given = copy.deepcopy(self.str_test_subject) expected = ["world!", "world", "hello", "hello", "Hello", "!", " ", ""] actual = self.helper.set_subject(given).sort(reverse=True).subject self.assertEqual(expected, actual) def test_custom_sort(self) -> None: """ Tests the method which let us sort a given list with a custom method. """ given = copy.deepcopy(self.str_test_subject) expected = ["", " ", "!", "world!", "world", "hello", "hello", "Hello"] actual = ( self.helper.set_subject(given) .custom_sort(lambda x: x[-1] if x else x) .subject ) self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/helpers/test_merge.py000066400000000000000000000272041467462152100217520ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the merging helper. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 unittest from PyFunceble.helpers.merge import Merge class TestMerge(unittest.TestCase): """ Tests our merging helper. """ def setUp(self) -> None: """ Setups everything needed by the tests. """ self.helper = Merge() def tearDown(self) -> None: """ Destroys everything needed by the tests. """ del self.helper def test_set_subject_return(self) -> None: """ Tests the response from the method which let us set the subject to work with. """ actual = self.helper.set_subject("This is an example.") self.assertIsInstance(actual, Merge) def test_set_subject_method(self) -> None: """ Tests the method which let us set the subject to work with. """ given = "This is an example." expected = given self.helper.set_subject(given) actual = self.helper.subject self.assertEqual(expected, actual) def test_set_subject_attribute(self) -> None: """ Tests overwritting of the :code:`subject` attribute. """ given = "This is another example." expected = given self.helper.subject = given actual = self.helper.subject self.assertEqual(expected, actual) def test_set_subject_through_init(self) -> None: """ Tests the overwritting of the subject to work through the class constructor. """ given = "This is a strange example." expected = given helper = Merge(given) actual = helper.subject self.assertEqual(expected, actual) def test_merge_str(self) -> None: """ Tests the method which let us merge 2 objects for the case that 2 strings are given. """ given = "Hello" expected = "Hello" actual = self.helper.set_subject(given).into("World") self.assertEqual(expected, actual) def test_merge_int(self) -> None: """ Tests the method which let us merge 2 objects for the case that 2 integers are given. """ given = 2 expected = 2 actual = self.helper.set_subject(given).into(1) self.assertEqual(expected, actual) def test_merge_float(self) -> None: """ Tests the method which let us merge 2 objects for the case that 2 floats are given. """ given = 2.1 expected = 2.1 actual = self.helper.set_subject(given).into(3.1) self.assertEqual(expected, actual) def test_strict_simple_dict(self) -> None: """ Tests the case that we want to strictly merge 2 simple dict. """ given = { "world": "Fun Ilrys", "hello_world": {"author": "funilrys", "name": "Fun"}, "hello": ["This is PyFunceble!", "Uhh!"], } to_merge = { "hello_world": {"author": "nobody", "surname": "body"}, "hello": ["hello", "Uhh"], } expected = { "hello_world": {"author": "nobody", "name": "Fun", "surname": "body"}, "world": "Fun Ilrys", "hello": ["hello", "Uhh"], } actual = self.helper.set_subject(to_merge).into(given, strict=True) self.assertEqual(expected, actual) def test_not_strict_simple_dict(self) -> None: """ Tests the case that we want to merge 2 simple dicts. """ given = { "hello": ["This is PyFunceble!", "Uhh!"], "world": "Fun Ilrys", "hello_world": {"author": "funilrys", "name": "Fun"}, } to_merge = { "hello": ["hello", "Uhh"], "hello_world": {"author": "nobody", "surname": "body"}, } expected = { "world": "Fun Ilrys", "hello_world": {"author": "nobody", "name": "Fun", "surname": "body"}, "hello": ["This is PyFunceble!", "Uhh!", "hello", "Uhh"], } actual = self.helper.set_subject(to_merge).into(given, strict=False) self.assertEqual(expected, actual) def test_strict_dict(self) -> None: """ Tests the case that we want to strictly merge 2 dicts. """ given = { "hello": {"world": ["This is PyFunceble!", "Uhh!"]}, "world": "Fun Ilrys", "hello_world": {"author": "funilrys", "name": "Fun"}, } to_merge = { "hello": {"world": ["hello", "Uhh!"]}, "hello_world": {"author": "nobody", "surname": "body"}, } expected = { "hello": {"world": ["hello", "Uhh!"]}, "world": "Fun Ilrys", "hello_world": {"author": "nobody", "name": "Fun", "surname": "body"}, } actual = self.helper.set_subject(to_merge).into(given, strict=True) self.assertEqual(expected, actual) def test_not_strict_dict(self) -> None: """ Tests the case that we want to merge 2 dicts. """ given = { "hello": {"world": ["This is PyFunceble!", "Uhh!"]}, "world": "Fun Ilrys", "hello_world": {"author": "funilrys", "name": "Fun"}, } to_merge = { "hello": {"world": ["hello", "Uhh!"]}, "hello_world": {"author": "nobody", "surname": "body"}, } expected = { "hello": {"world": ["This is PyFunceble!", "Uhh!", "hello"]}, "world": "Fun Ilrys", "hello_world": {"author": "nobody", "name": "Fun", "surname": "body"}, } actual = self.helper.set_subject(to_merge).into(given, strict=False) self.assertEqual(expected, actual) def test_strict_simple_list(self) -> None: """ Tests the case that we want to strictly merge 2 simple lists. """ given = [1, 2, 3, 4] to_merge = [2, 4, 5, 6, 7] expected = [2, 4, 5, 6, 7] actual = self.helper.set_subject(to_merge).into(given, strict=True) self.assertEqual(actual, expected) def test_not_strict_simple_list(self) -> None: """ Tests the case that we want to merge 2 simple lists. """ given = [1, 2, 3, 4] to_merge = [2, 4, 5, 6, 7] expected = [1, 2, 3, 4, 5, 6, 7] actual = self.helper.set_subject(to_merge).into(given, strict=False) self.assertEqual(actual, expected) def test_strict_list(self) -> None: """ Tests the case that we want to strictly merge 2 lists. """ given = ["hello", "world", 5, {"hello": "world"}, [1, 2, 3]] to_merge = ["hello", "world", 5, {"world": "hello"}, [4, 5]] expected = ["hello", "world", 5, {"hello": "world", "world": "hello"}, [4, 5]] actual = self.helper.set_subject(to_merge).into(given, strict=True) self.assertEqual(expected, actual) to_merge = ["hello", "world", 5, {"hello": "you!"}, [1, 2, 4, 5]] expected = ["hello", "world", 5, {"hello": "you!"}, [1, 2, 4, 5]] actual = self.helper.set_subject(to_merge).into(given, strict=True) self.assertEqual(expected, actual) to_merge = ["hello", "world", 5, {"hello": "you!"}, [1, 2, 4, 5]] expected = ["hello", "world", 5, {"hello": "you!"}, [1, 2, 4, 5]] actual = self.helper.set_subject(to_merge).into(given, strict=True) self.assertEqual(expected, actual) def test_not_strict_list(self) -> None: """ Tests the case that we want to merge 2 lists. """ given = ["hello", "world", 5, {"hello": "world"}, [1, 2, 3]] to_merge = ["hello", "world", 5, {"world": "hello"}, [4, 5]] expected = [ "hello", "world", 5, {"hello": "world"}, [1, 2, 3], {"world": "hello"}, [4, 5], ] actual = self.helper.set_subject(to_merge).into(given, strict=False) self.assertEqual(expected, actual) to_merge = ["hello", "world", 5, {"hello": "you!"}, [1, 2, 4, 5]] expected = [ "hello", "world", 5, {"hello": "world"}, [1, 2, 3], {"hello": "you!"}, [1, 2, 4, 5], ] actual = self.helper.set_subject(to_merge).into(given, strict=False) self.assertEqual(expected, actual) to_merge = ["hello", "world", 5, {"hello": "you!"}, [1, 2, 4, 5]] expected = [ "hello", "world", 5, {"hello": "world"}, [1, 2, 3], {"hello": "you!"}, [1, 2, 4, 5], ] actual = self.helper.set_subject(to_merge).into(given, strict=False) self.assertEqual(expected, actual) def test_mixed_str_int(self) -> None: """ Tests the case that we want to merge a str into an int. """ expected = "Hello" actual = self.helper.set_subject("Hello").into(1) self.assertEqual(expected, actual) def test_mixed_int_float(self) -> None: """ Tests the case that we want to merge an int into a float. """ expected = 1 actual = self.helper.set_subject(1).into(2.1) self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/helpers/test_regex.py000066400000000000000000000213701467462152100217630ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the regex helper. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 unittest from PyFunceble.helpers.regex import RegexHelper class TestRegexHelper(unittest.TestCase): """ Tests our regex helper. """ def setUp(self) -> None: """ Setups everything needed for the test. """ self.helper = RegexHelper() self.test_regex = "[a-z]" self.testing_list_subject = [ "hello", "world", "funilrys", "funceble", "PyFunceble", "pyfunceble", ] self.testing_subject = "Hello, this is Fun Ilrys. I just wanted to know how things goes around the tests." # pylint: disable=line-too-long def tearDown(self) -> None: """ Destroys everything previously initialized for the tests. """ del self.testing_list_subject del self.testing_subject def test_set_regex_return(self) -> None: """ Tests the response from the method which let us set the regex to work with. """ actual = self.helper.set_regex(self.test_regex) self.assertIsInstance(actual, RegexHelper) def test_set_regex_method(self) -> None: """ Tests the method which let us set the regex to work with. """ given = self.test_regex expected = given self.helper.set_regex(given) actual = self.helper.regex self.assertEqual(expected, actual) def test_set_regex_attribute(self) -> None: """ Tests overwritting of the :code:`regex` attribute. """ given = self.test_regex expected = given self.helper.regex = given actual = self.helper.regex self.assertEqual(expected, actual) def test_set_regex_through_init(self) -> None: """ Tests the overwritting of the regex to work through the class constructor. """ given = self.test_regex expected = given helper = RegexHelper(given) actual = helper.regex self.assertEqual(expected, actual) def test_set_regex_not_str(self) -> None: """ Tests the method which let us set the regex to work with for the case that it's not a string. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.helper.set_regex(given)) def test_set_regex_escape(self) -> None: """ Tests the method which let us set the regex to work with for the case that it's not a string. """ regex_helper = RegexHelper() regex_helper.escape_regex = True regex_helper.set_regex("[a-z]") expected = r"\[a\-z\]" actual = regex_helper.regex self.assertEqual(expected, actual) def test_not_matching_list(self) -> None: """ Tests the method which let us get a list of non matching strin from a given list of string. """ regex = "fun" expected = ["hello", "world", "PyFunceble"] actual = self.helper.set_regex(regex).get_not_matching_list( self.testing_list_subject ) self.assertEqual(expected, actual) def test_matching_list(self) -> None: """ Tests the method which let us get a list of matchint string from a given list of string. """ regex = "fun" expected = ["funilrys", "funceble", "pyfunceble"] actual = self.helper.set_regex(regex).get_matching_list( self.testing_list_subject ) self.assertEqual(expected, actual) def test_match_check(self) -> None: """ Tests the matching method for the case that we want to just check. """ regex = r"([a-z]{1,})\s([a-z]{1,})\s" expected = True actual = self.helper.set_regex(regex).match( self.testing_subject, return_match=False ) self.assertEqual(expected, actual) def test_match_not_check(self) -> None: """ Tests the matching method for the case that we want to just check. """ regex = r"@funilrys" expected = False actual = self.helper.set_regex(regex).match( self.testing_subject, return_match=False ) self.assertEqual(expected, actual) def test_match_rematch(self) -> None: """ Tests the matching method for the case that we want to rematch the different groups. """ regex = r"([a-z]{1,})\s([a-z]{1,})\s" expected = "is" actual = self.helper.set_regex(regex).match( self.testing_subject, rematch=True, group=1 ) self.assertEqual(expected, actual) def test_match_get_group(self) -> None: """ Tests the matching method for the case that we want a specific group. """ regex = "e" expected = "e" actual = self.helper.set_regex(regex).match(self.testing_subject, group=0) self.assertEqual(expected, actual) regex = r"([a-z]{1,})\s([a-z]{1,})\s" expected = "this" actual = self.helper.set_regex(regex).match(self.testing_subject, group=1) self.assertEqual(expected, actual) def test_replace_no_replacement(self) -> None: """ Tests the replacement method for the case that no replacement is not given. """ regex = "th" expected = self.testing_subject actual = self.helper.set_regex(regex).replace_match(self.testing_subject, None) self.assertEqual(expected, actual) def test_replace(self) -> None: """ Tests the replacement method. """ regex = "th" expected = ( "Hello, htis is Fun Ilrys. I just wanted to know how " "htings goes around hte tests." ) actual = self.helper.set_regex(regex).replace_match(self.testing_subject, "ht") self.assertEqual(expected, actual) def test_split(self) -> None: """ Tests the method which le us split occurences of a given regex. """ regex = "th" expected = [ "Hello, ", "is is Fun Ilrys. I just wanted to know how ", "ings goes around ", "e tests.", ] actual = self.helper.set_regex(regex).split(self.testing_subject) self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/pyf_test_dataset.py000066400000000000000000000313441467462152100215140ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some datasets. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from typing import List VALID_SECOND_LVL_DOMAINS: List[str] = [ "example.org", "example.net", "example.co.uk", "example.de", "985.com", ] NOT_VALID_SECOND_LVL_DOMAINS: List[str] = [ "hello.example.org", "world.example.net", "hello.world.example.co.uk", "world.hello.example.de", ] VALID_DOMAINS: List[str] = [ "_hello_.example.co.uk.", "_hello_.example.co.uk", "_hello_world_.example.co.uk.", "_hello_world_.example.co.uk", "_hello_world_.hello.eu.com.", "_hello_world_.hello.eu.com", "_hello-beautiful-world_.wold.eu.com.", "_hello-beautiful-world_.wold.eu.com", "_hello-world.example.co.uk.", "_hello-world.example.co.uk", "_hello._world.example.co.uk.", "_hello._world.example.co.uk", "_hello.example.co.uk.", "_hello.example.co.uk", "_world_.hello.eu.com.", "_world_.hello.eu.com", "_world.hello.eu.com.", "_world.hello.eu.com", "hello_.world.eu.com.", "hello_.world.eu.com", "hello_world.example.co.uk.", "hello_world.example.co.uk", "hello_world.world.com.", "hello_world.world.com", "hello_world.world.hello.com.", "hello_world.world.hello.com", "hello---world.com.", "hello---world.com", "hello-.example.co.uk.", "hello-.example.co.uk", "hello-world.com.", "hello-world.com", "hello.onion", "hello.world_hello.world.com.", "hello.world_hello.world.com", "hello.world.com.", "hello.world.com", "hello.world.hello.com.", "hello.world.hello.com", "pogotowie-komputerowe-warszawa.com.pl", "worl.hello.onion", "xn--bittr-fsa6124c.com.", "xn--bittr-fsa6124c.com", "xn--bllogram-g80d.com.", "xn--bllogram-g80d.com", "xn--coinbse-30c.com.", "xn--coinbse-30c.com", "xn--cryptopi-ux0d.com.", "xn--cryptopi-ux0d.com", "xn--cyptopia-4e0d.com.", "xn--cyptopia-4e0d.com", "www.hello_world.blogspot.co.nz", "hello_world.blogspot.co.nz", "example.org", "bแป‹llogram.com", "bittrรฉแบ‹.com", "coinbศงse.com", "cryptopiแบก.com", "cแน™yptopia.com", "985.com", "hello-world.example.msn.cn", "hello_world.co.uk", "_world._hello.eu.com", "_world.hello_.eu.com", ] NOT_VALID_DOMAINS: List[str] = [ "-hello-.example.co.uk", "-hello-world_.example.co.uk", "-hello-world_all-mine_.hello.eu.com", "-hello.example.co.uk", "-hello.world", "-world.hello", "..", ".", r"bแป‹l\llogram.com", "hello_world_.com", "hello_world.com", "hello-.world", "hello-world", "hello.-hello-world_.example.co.uk", "hello@world.com", "httpWd", "test.-hello-world_all-mine_.example.co.uk", "world_hello.com", "world-.hello", "world-hello", "world.hello:80", "world@hello.com", "example.com\\", "ex\\ample.com", ] VALID_SUBDOMAINS: List[str] = [ "hello_world.world.com", "hello_world.world.hello.com", "hello.world_hello.world.com", "hello.world.hello.com", "hello_.world.eu.com", "_world.hello.eu.com", "_world_.hello.eu.com", "_hello-beautiful-world_.wold.eu.com", "_hello_world_.hello.eu.com", "_hello.example.co.uk", "_hello_.example.co.uk", "_hello._world.example.co.uk", "_hello-world.example.co.uk", "_hello_world_.example.co.uk", "hello_world.example.co.uk", "hello-.example.co.uk", "hello.world.onion", "test.hello.blogspot.co.uk", "888.0769.com", "1661599812.hello.985.com", "hi.hello.example.world.s3.ap-northeast-2.amazonaws.com", "world_hello.hello_world.co.uk", ] NOT_VALID_SUBDOMAINS: List[str] = [ "-hello.world", "bแป‹llogram.com", "bittrรฉแบ‹.com", "coinbศงse.com", "cryptopiแบก.com", "cแน™yptopia.com", "google.com", "hello_world_.com", "hello_world.com", "hello-.world", "hello-world", "pogotowie-komputerowe-warszawa.com.pl", "hello.world.example.com\\", "he\\llo.world.example.com", ] VALID_IPV4: List[str] = ["15.47.85.65", "45.66.255.240", "255.45.65.0/24"] VALID_IPV6: List[str] = [ "2001:db8::", "2001:db8::1000", "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:db8:85a3:0:0:8a2e:370:7334", "2001:db8:85a3::8a2e:370:7334", "::1", "::", "2001:db8:1234::/48", "2001:db8:1234:0000:0000:0000:0000:0000", "2001:db8:1234:ffff:ffff:ffff:ffff:ffff", "2001:db8:a::/64", "2001:db8:a::123/64", "2001:db8:85a3:8d3:1319:8a2e:370:7348", "::/0", "::/128", "::1/128", "::ffff:0:0/96", "::ffff:0:0:0/96", "64:ff9b::/96", "100::/64", "2001::/32", "2001:20::/28", "2001:db8::/32", "2002::/16", "fc00::/7", "fe80::/10", "ff00::/8", ] NOT_VALID_IPV4: List[str] = ["google.com", "287.468.45.26", "245.85.69.17:8081"] NOT_VALID_IPV6: List[str] = [ "google.com", "287.468.45.26", "2001:db8::/4839", "2001:::", "2001:db8:85a3:8d3:1319:8a2e:370:7348f", "2001:db8:85a3:8d3:1319:8a2e:370:7348/129", ] VALID_IPV4_RANGES: List[str] = ["255.45.65.0/24", "255.45.65.6/18"] VALID_IPV6_RANGES: List[str] = [ "2001:db8::/128", "2001:db8:1234::/48", "2001:db8:a::/64", "2001:db8:a::123/64", ] NOT_VALID_IPV4_RANGES: List[str] = ["15.47.85.65", "45.66.255.240", "github.com"] NOT_VALID_IPV6_RANGES: List[str] = ["2001:db8::/129", "github.com", "2001:db8:a::"] RESERVED_IPV4: List[str] = [ "0.45.23.59", "10.39.93.13", "100.64.35.85", "127.57.91.13", "169.254.98.65", "172.16.17.200", "192.0.0.145", "192.0.2.39", "192.168.21.99", "192.175.48.25", "192.31.196.176", "192.52.193.245", "192.88.99.30", "198.18.145.234", "198.51.100.212", "203.0.113.103", "224.134.13.24", "240.214.30.11", "255.255.255.255", ] RESERVED_IPV6: List[str] = [ "::", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "::1", "::ffff:0.0.0.0", "::ffff:255.255.255.255", "::ffff:0:0.0.0.0", "::ffff:0:255.255.255.255", "64:ff9b::0.0.0.0", "64:ff9b::255.255.255.255", "100::", "100::ffff:ffff:ffff:ffff", "2001::", "2001::ffff:ffff:ffff:ffff:ffff:ffff", "2001:60::", "2001:5f:ffff:ffff:ffff:ffff:ffff:ffff", "2001:db8::", "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff", "fc00::", "fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "fe80::", "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "ff00::", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", ] NOT_RESERVED_IPV4: List[str] = [ "hello.world", "192.243.198.89", "45.34.29.15", "127.0.0.53/32", ] NOT_RESERVED_IPV6: List[str] = [ "2001:db8::/128", "hello.world", "2001:db8:1234::/48", "2001:db8:a::/64", "2001:db8:a::123/64", "github.com", ] DEFAULT_CONFIG: dict = { "cli_decoding": { "adblock": False, "aggressive": False, "rpz": False, "wildcard": False, }, "cli_testing": { "autocontinue": False, "ci": { "active": False, "branch": "master", "command": None, "commit_message": "PyFunceble - AutoSave", "distribution_branch": "master", "end_command": None, "end_commit_message": "PyFunceble - Results", "max_exec_minutes": 15, }, "complements": False, "cooldown_time": 0.0, "days_between": {"db_clean": 28, "db_retest": 1}, "db_type": "csv", "display_mode": { "all": False, "colour": True, "dots": False, "execution_time": False, "less": True, "percentage": True, "quiet": False, "simple": False, "status": "all", }, "file_filter": None, "file_generation": { "analytic": True, "hosts": False, "no_file": False, "plain": True, "unified_results": False, "merge_output_dirs": False, }, "hosts_ip": "0.0.0.0", "inactive_db": True, "local_network": False, "max_workers": None, "mining": False, "preload_file": False, "sorting_mode": {"hierarchical": False, "standard": True}, "testing_mode": {"availability": True, "reputation": False, "syntax": False}, "whois_db": True, }, "platform": { "push": False, "preferred_data_origin": "frequent", }, "debug": {"active": False, "level": "info"}, "dns": { "follow_server_order": True, "protocol": "UDP", "server": None, "trust_server": False, }, "http_codes": { "list": { "potentially_down": [400, 402, 404, 409, 410, 412, 414, 415, 416, 451], "potentially_up": [ 300, 301, 302, 303, 304, 305, 307, 308, 403, 405, 406, 407, 408, 411, 413, 417, 418, 421, 422, 423, 424, 426, 428, 431, 500, 501, 502, 503, 504, 505, 506, 507, 508, 510, 511, ], "up": [ 100, 101, 102, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 429, ], }, "self_managed": False, }, "links": { "api_date_format": "https://pyfunceble.funilrys.com/api/date-format", "api_no_referrer": "https://pyfunceble.funilrys.com/api/no-referrer", }, "lookup": { "dns": True, "http_status_code": True, "netinfo": True, "reputation": False, "special": True, "timeout": 5, "whois": True, "platform": False, }, "proxy": {"global": {"http": None, "https": None}, "rules": []}, "share_logs": False, "user_agent": {"browser": "chrome", "custom": None, "platform": "linux"}, "verify_ssl_certificate": False, } PyFunceble-4.2.29.dev/tests/pyf_test_helpers.py000066400000000000000000000105331467462152100215260ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides some test related helpers. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ from datetime import timedelta, timezone def convert_ipv4_to_rpz(subject: str) -> str: """ Converts the given IPv4 into a policy format which can later be used in the tests. """ return ".".join(reversed(subject.replace("/", ".").split("."))) def convert_ipv6_to_rpz(subject: str) -> str: """ Converts the given IPV6 into a policy format which can later be used in the tests. """ starting_point = subject.replace("/", ".") if "::" in starting_point: splitted = starting_point.split("::") if splitted[-1] and (splitted[-1].startswith(".") or "." in splitted[-1]): starting_point = starting_point.replace("::", ".zz.") else: starting_point = starting_point.replace("::", ".zz") return ".".join(reversed(starting_point.replace(":", ".").split("."))) def get_timezone( sign: str = "+", days: int = 0, seconds: int = 0, microseconds: int = 0, milliseconds: int = 0, minutes: int = 0, hours: int = 0, weeks: int = 0, ) -> timezone: """ Provides a timezone. :param str sign: The sign to apply. Should be :code:`+` or :code:`-`. :param int weeks: The number of weeks from UTC. :param int days: The number of days from UTC. :param int hours: The number of hours from UTC. :param int minutes: The number of minutes from UTC. :param int seconds: The number of seconds from UTC. :param int milliseconds: The number of days from UTC. :param int microseconds: The number of microseconds from UTC. """ if sign == "+": sign = 1 else: # pragma: no cover ## Not covered by default. sign = -1 delta = timedelta( days=days, seconds=seconds, microseconds=microseconds, milliseconds=milliseconds, minutes=minutes, hours=hours, weeks=weeks, ) return timezone(sign * delta) PyFunceble-4.2.29.dev/tests/query/000077500000000000000000000000001467462152100167405ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/query/__init__.py000066400000000000000000000000001467462152100210370ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/query/dnss/000077500000000000000000000000001467462152100177075ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/query/dnss/__init__.py000066400000000000000000000000001467462152100220060ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/query/dnss/test_nameserver.py000066400000000000000000000416331467462152100234760ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our nameserver manager. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 dataclasses import unittest import unittest.mock import dns.exception import dns.resolver from PyFunceble.config.loader import ConfigLoader from PyFunceble.query.dns.nameserver import Nameservers try: import pyf_test_dataset except (ModuleNotFoundError, ImportError): # pragma: no cover try: from .. import pyf_test_dataset except (ModuleNotFoundError, ImportError): from ... import pyf_test_dataset # pylint: disable=invalid-field-call class TestNameserver(unittest.TestCase): """ Tests our nameserver "manager". """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.config_loader = ConfigLoader() self.config_loader.start() self.nameserver_provider = Nameservers() def tearDown(self) -> None: """ Destroys everything previously initiated. """ del self.config_loader @staticmethod def fake_resolve_response( data: str, ) -> object: """ Provides a fake resolve response to use. """ return dataclasses.make_dataclass( "FakeResponse", [("address", str, dataclasses.field(default=data))] ) @staticmethod def fake_resolver(_: str, rqtype: str): """ Provides a fake resolution. """ if rqtype == "A": return [ TestNameserver.fake_resolve_response("192.168.1.1"), TestNameserver.fake_resolve_response("10.47.91.9"), ] return [ TestNameserver.fake_resolve_response("fe80::6b01:9045:a42a:fb5f"), TestNameserver.fake_resolve_response("fe80::6b01:9049:a42a:fb5f"), ] def test_split_nameserver_from_port(self) -> None: """ Tests the method which let us split the nameserver from the port. """ given = "example.org:45" expected = ("example.org", 45) actual = self.nameserver_provider.split_nameserver_from_port(given) self.assertEqual(expected, actual) def test_split_nameserver_from_port_no_port(self) -> None: """ Tests the method which let us split the nameserver from the port for the case that no port is given. """ given = "example.org" expected = ("example.org", 53) actual = self.nameserver_provider.split_nameserver_from_port(given) self.assertEqual(expected, actual) def test_split_nameserver_from_port_not_correct(self) -> None: """ Tests the method which let us split the nameserver from the port for the case that the port is incorrectly given. """ given = "10.0.0.1:ed" expected = ("10.0.0.1", 53) actual = self.nameserver_provider.split_nameserver_from_port(given) self.assertEqual(expected, actual) def test_split_nameserver_from_port_ipv6_no_port(self) -> None: """ Tests the method which let us split the nameserver from the port for the case that an IPv6 is given and no port. """ given = pyf_test_dataset.VALID_IPV6[0] expected = (pyf_test_dataset.VALID_IPV6[0], 53) actual = self.nameserver_provider.split_nameserver_from_port(given) self.assertEqual(expected, actual) def test_split_nameserver_from_port_ipv6_with_port(self) -> None: """ Tests the method which let us split the nameserver from the port for the case that an IPv6 is given and no port. """ given = f"{pyf_test_dataset.VALID_IPV6[1]}:55" expected = (f"{pyf_test_dataset.VALID_IPV6[1]}:55", 53) actual = self.nameserver_provider.split_nameserver_from_port(given) self.assertEqual(expected, actual) def test_split_nameserver_from_port_ipv6_convention(self) -> None: """ Tests the method which let us split the nameserver from the port. In this case we are trying to follow the :code:`[ip]:port` convention. """ given = f"[{pyf_test_dataset.VALID_IPV6[1]}]:55" expected = (pyf_test_dataset.VALID_IPV6[1], 55) actual = self.nameserver_provider.split_nameserver_from_port(given) self.assertEqual(expected, actual) def test_split_nameserver_from_port_ipv6_convention_port_not_digit(self) -> None: """ Tests the method which let us split the nameserver from the port. In this case we are trying to follow the :code:`[ip]:port` convention but the port is not a correct one.. """ given = f"[{pyf_test_dataset.VALID_IPV6[1]}]:ef" expected = (pyf_test_dataset.VALID_IPV6[1], 53) actual = self.nameserver_provider.split_nameserver_from_port(given) self.assertEqual(expected, actual) @unittest.mock.patch.object(dns.resolver.Resolver, "resolve") def test_get_ip_from_nameserver(self, resolver_patch) -> None: """ Tests the method which let us get the IP from a nameserver. """ resolver_patch.side_effect = self.fake_resolver given = "example.org" expected = [ "192.168.1.1", "10.47.91.9", "fe80::6b01:9045:a42a:fb5f", "fe80::6b01:9049:a42a:fb5f", ] actual = self.nameserver_provider.get_ip_from_nameserver(given) self.assertEqual(expected, actual) @unittest.mock.patch.object(dns.resolver.Resolver, "resolve") def test_get_ip_from_nameserver_exceptions(self, resolver_patch) -> None: """ Tests the method which let us get the IP from a nameserver for the case that only exceptions are given back. """ resolver_patch.side_effect = dns.exception.DNSException("This is a test :-)") given = "example.org" expected = [] actual = self.nameserver_provider.get_ip_from_nameserver(given) self.assertEqual(expected, actual) def test_get_ip_from_nameserver_not_valid_domain(self) -> None: """ Tests the method which let us get the IP from a nameserver for the case that a private domain is given. """ given = "example.funilrys" expected = ["example.funilrys"] actual = self.nameserver_provider.get_ip_from_nameserver(given) self.assertEqual(expected, actual) @unittest.mock.patch.object(dns.resolver.Resolver, "resolve") def test_set_nameservers(self, resolver_patch) -> None: """ Tests the method which let us set the nameserver to work with. """ resolver_patch.side_effect = self.fake_resolver given = ["example.org:53"] expected_nameserver = [ "192.168.1.1", "10.47.91.9", "fe80::6b01:9045:a42a:fb5f", "fe80::6b01:9049:a42a:fb5f", ] expected_nameserver_port = { "192.168.1.1": 53, "10.47.91.9": 53, "fe80::6b01:9045:a42a:fb5f": 53, "fe80::6b01:9049:a42a:fb5f": 53, } self.nameserver_provider.set_nameservers(given) actual = self.nameserver_provider.get_nameservers() actual_nameserver_port = self.nameserver_provider.get_nameserver_ports() self.assertEqual(expected_nameserver, actual) self.assertEqual(expected_nameserver_port, actual_nameserver_port) @unittest.mock.patch.object(dns.resolver.Resolver, "resolve") def test_set_nameservers_through_init(self, resolver_patch) -> None: """ Tests the method which let us set the nameserver from the contributor method. """ resolver_patch.side_effect = self.fake_resolver given = ["example.org:53"] expected_nameserver = [ "192.168.1.1", "10.47.91.9", "fe80::6b01:9045:a42a:fb5f", "fe80::6b01:9049:a42a:fb5f", ] expected_nameserver_port = { "192.168.1.1": 53, "10.47.91.9": 53, "fe80::6b01:9045:a42a:fb5f": 53, "fe80::6b01:9049:a42a:fb5f": 53, } nameserver_obj = Nameservers(nameserver=given) actual = nameserver_obj.get_nameservers() actual_nameserver_port = nameserver_obj.get_nameserver_ports() self.assertEqual(expected_nameserver, actual) self.assertEqual(expected_nameserver_port, actual_nameserver_port) def test_set_nameservers_https(self) -> None: """ Tests the method which let us set the nameserver to work with for the case that a URL is given. """ given = ["https://example.org/dns-query", "https://example.net/dns-query"] expected_nameserver = [ "https://example.org/dns-query", "https://example.net/dns-query", ] expected_nameserver_port = { "https://example.org/dns-query": 443, "https://example.net/dns-query": 443, } self.nameserver_provider.protocol = "HTTPS" self.nameserver_provider.set_nameservers(given) actual = self.nameserver_provider.get_nameservers() actual_nameserver_port = self.nameserver_provider.get_nameserver_ports() self.assertEqual(expected_nameserver, actual) self.assertEqual(expected_nameserver_port, actual_nameserver_port) def test_set_nameservers_https_no_scheme(self) -> None: """ Tests the method which let us set the nameserver to work with for the case that a URL is given. Now, we test for the case that no scheme is provided. """ given = ["example.org/dns-query", "example.net/dns-query"] expected_nameserver = [ "https://example.org/dns-query", "https://example.net/dns-query", ] expected_nameserver_port = { "https://example.org/dns-query": 443, "https://example.net/dns-query": 443, } self.nameserver_provider.protocol = "HTTPS" self.nameserver_provider.set_nameservers(given) actual = self.nameserver_provider.get_nameservers() actual_nameserver_port = self.nameserver_provider.get_nameserver_ports() self.assertEqual(expected_nameserver, actual) self.assertEqual(expected_nameserver_port, actual_nameserver_port) def test_set_nameservers_https_no_scheme_and_path(self) -> None: """ Tests the method which let us set the nameserver to work with for the case that a URL is given. Now, we test for the case that no scheme and explicit path is provided. """ given = ["example.org", "example.net"] expected_nameserver = [ "https://example.org", "https://example.net", ] expected_nameserver_port = { "https://example.org": 443, "https://example.net": 443, } self.nameserver_provider.protocol = "HTTPS" self.nameserver_provider.set_nameservers(given) actual = self.nameserver_provider.get_nameservers() actual_nameserver_port = self.nameserver_provider.get_nameserver_ports() self.assertEqual(expected_nameserver, actual) self.assertEqual(expected_nameserver_port, actual_nameserver_port) def test_set_nameservers_not_list(self) -> None: """ Tests the method which let us set the nameserver to work with for the case that the given value is not a list. """ given = "Hello, World!" self.assertRaises( TypeError, lambda: self.nameserver_provider.set_nameservers(given) ) def test_set_nameservers_empty_list(self) -> None: """ Tests the method which let us set the nameserver to work with for the case that the given value is an empty list. """ given = [] self.assertRaises(ValueError, lambda: Nameservers().set_nameservers(given)) @unittest.mock.patch.object(dns.resolver.Resolver, "resolve") def test_guess_and_set_nameservers(self, resolver_patch) -> None: """ Tests the method which let us guess the nameserver to use. """ resolver_patch.side_effect = self.fake_resolver given = ["example.org:53"] expected_nameserver = [ "192.168.1.1", "10.47.91.9", "fe80::6b01:9045:a42a:fb5f", "fe80::6b01:9049:a42a:fb5f", ] expected_nameserver_port = { "192.168.1.1": 53, "10.47.91.9": 53, "fe80::6b01:9045:a42a:fb5f": 53, "fe80::6b01:9049:a42a:fb5f": 53, } self.config_loader.set_custom_config({"dns": {"server": given}}).start() self.nameserver_provider.guess_and_set_nameservers() actual = self.nameserver_provider.get_nameservers() actual_nameserver_port = self.nameserver_provider.get_nameserver_ports() self.assertEqual(expected_nameserver, actual) self.assertEqual(expected_nameserver_port, actual_nameserver_port) self.config_loader.set_custom_config({"dns": {"server": given[0]}}).start() self.nameserver_provider.guess_and_set_nameservers() actual = self.nameserver_provider.get_nameservers() actual_nameserver_port = self.nameserver_provider.get_nameserver_ports() self.assertEqual(expected_nameserver, actual) self.assertEqual(expected_nameserver_port, actual_nameserver_port) @unittest.mock.patch.object(dns.resolver, "get_default_resolver") def test_guess_and_set_nameservers_no_default_resolver( self, get_default_resolver_patch ) -> None: """ Tests the method which let us guess the nameserver to use for the case that no resolver has been found. """ def fake_get_default_resolver(*args, **kwargs): raise dns.resolver.dns.resolver.NoResolverConfiguration("no nameservers") get_default_resolver_patch.side_effect = fake_get_default_resolver expected_nameserver = [ "9.9.9.10", "149.112.112.10", "2620:fe::10", "2620:fe::fe:10", ] expected_nameserver_port = { "9.9.9.10": 53, "149.112.112.10": 53, "2620:fe::10": 53, "2620:fe::fe:10": 53, } self.config_loader.set_custom_config({"dns": {"server": []}}).start() self.nameserver_provider.guess_and_set_nameservers() actual = self.nameserver_provider.get_nameservers() actual_nameserver_port = self.nameserver_provider.get_nameserver_ports() self.assertEqual(expected_nameserver, actual) self.assertEqual(expected_nameserver_port, actual_nameserver_port) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/query/dnss/test_query_tool.py000066400000000000000000001360131467462152100235260ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our query tool. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 dataclasses import secrets import socket import unittest import unittest.mock import dns.exception import dns.name import dns.query from PyFunceble.config.loader import ConfigLoader from PyFunceble.query.dns.query_tool import DNSQueryTool, DNSQueryToolRecord # pylint: disable=protected-access, too-many-lines, invalid-field-call class TestDNSQueryTool(unittest.TestCase): """ Tests our DNS query tool. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ def fake_response(data: str) -> object: return dataclasses.make_dataclass( "FakeResponse", [("address", str, dataclasses.field(default=data))] ) def fake_resolver(_: str, rqtype: str): if rqtype == "A": return [ fake_response("192.168.1.1"), fake_response("10.47.91.9"), ] return [ fake_response("fe80::6b01:9045:a42a:fb5f"), fake_response("fe80::6b01:9049:a42a:fb5f"), ] self.resolve_patch = unittest.mock.patch.object( dns.resolver.Resolver, "resolve" ) self.udp_query_patch = unittest.mock.patch.object(dns.query, "udp") self.tcp_query_patch = unittest.mock.patch.object(dns.query, "tcp") self.https_query_patch = unittest.mock.patch.object(dns.query, "https") self.tls_query_patch = unittest.mock.patch.object(dns.query, "tls") self.mock_resolve = self.resolve_patch.start() self.mock_resolve.side_effect = fake_resolver self.mock_udp_query = self.udp_query_patch.start() self.mock_tcp_query = self.tcp_query_patch.start() self.mock_https_query = self.https_query_patch.start() self.mock_tls_query = self.tls_query_patch.start() self.query_tool = DNSQueryTool(nameservers=["example.org"]) self.query_tool._get_result_from_response = lambda _: [] def tearDown(self) -> None: """ Destroys everything previously initiated for the tests. """ self.resolve_patch.stop() self.udp_query_patch.stop() self.tcp_query_patch.stop() self.https_query_patch.stop() self.tls_query_patch.stop() del self.resolve_patch del self.udp_query_patch del self.tcp_query_patch del self.https_query_patch del self.tls_query_patch del self.mock_resolve del self.mock_udp_query del self.mock_tcp_query del self.mock_https_query del self.mock_tls_query @staticmethod def timout_response(*args, **kwargs) -> None: """ Provides a response which raise a timeout error exception. """ raise dns.exception.Timeout() @staticmethod def malformed_response(*args, **kwargs) -> None: """ Provides a response which raises a malformed value error. """ raise ValueError("Input malformed") @staticmethod def unexpected_source_response(*args, **kwargs) -> None: """ Provides a response which raises an unexpected source exception. """ raise dns.query.UnexpectedSource("got a response from XXX instead of XXX.") @staticmethod def bad_response_response(*args, **kwargs) -> None: """ Provides a response which raises a bad response error. """ raise dns.query.BadResponse( "A DNS query response does not respond to the question asked." ) @staticmethod def socket_error(*args, **kwargs) -> None: """ Provides a response which raises a socket error. """ raise socket.gaierror("Socket Error.") def test_set_subject(self) -> None: """ Tests the method which let us set the subject to work with. """ given = "example.net" expected_dns_name = None actual = self.query_tool.dns_name self.assertEqual(expected_dns_name, actual) expected = "example.net" self.query_tool.set_subject(given) actual = self.query_tool.subject self.assertEqual(expected, actual) self.assertIsInstance(self.query_tool.dns_name, dns.name.Name) def test_set_subject_absolute(self) -> None: """ Tests the method which let us set the subject to work with. """ given = "example.net." expected_dns_name = None actual = self.query_tool.dns_name self.assertEqual(expected_dns_name, actual) expected = "example.net." self.query_tool.set_subject(given) actual = self.query_tool.subject self.assertEqual(expected, actual) self.assertIsInstance(self.query_tool.dns_name, dns.name.Name) def test_set_subject_not_str(self) -> None: """ Tests the method which let us set the subject to work with for the case that the given subject is not a string. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.query_tool.set_subject(given)) def test_set_subject_empty_str(self) -> None: """ Tests the method which let us set the subject to work with for the case that the given subject is an empty string. """ given = "" self.assertRaises(ValueError, lambda: self.query_tool.set_subject(given)) def test_set_follow_nameserver_order(self) -> None: """ Tests the method which let us allow/disallow the shuffle of the list of nameserver. """ given = True expected = True self.query_tool.set_follow_nameserver_order(given) actual = self.query_tool.follow_nameserver_order self.assertEqual(expected, actual) def test_set_follow_nameserver_order_not_bool(self) -> None: """ Tests the method which let us allow/disallow the shuffle of the list of nameserver for the case that the given value is not a boolean """ given = ["Hello", "World"] self.assertRaises( TypeError, lambda: self.query_tool.set_follow_nameserver_order(given) ) def test_set_follow_nameserver_order_through_init(self) -> None: """ Tests the overwritting of the `follow_nameserver_attribute` attribute through the class constructor. """ given = False expected = False query_tool = DNSQueryTool(follow_nameserver_order=given) actual = query_tool.follow_nameserver_order self.assertEqual(expected, actual) def test_guess_and_set_follow_nameserver_order(self) -> None: """ Tests the method which let us guess and set the order of the server. """ config_loader = ConfigLoader() config_loader.set_custom_config({"dns": {"follow_server_order": False}}).start() self.query_tool.guess_and_set_follow_nameserver_order() expected = False actual = self.query_tool.follow_nameserver_order self.assertEqual(expected, actual) del config_loader def test_guess_and_set_follow_nameserver_order_none(self) -> None: """ Tests the method which let us guess and set the order of the server. In this test, we check the case that the given value is set to None. """ config_loader = ConfigLoader() config_loader.set_custom_config({"dns": {"follow_server_order": None}}).start() self.query_tool.guess_and_set_follow_nameserver_order() expected = self.query_tool.STD_FOLLOW_NAMESERVER_ORDER actual = self.query_tool.follow_nameserver_order self.assertEqual(expected, actual) del config_loader def test_set_query_record_type_from_name(self) -> None: """ Tests the method which let us set the type of the record with for the case that the string representation of the record type is given. """ given = "A" self.query_tool.set_query_record_type(given) expected = dns.rdatatype.RdataType.A actual = self.query_tool.query_record_type self.assertEqual(expected, actual) expected = "A" actual = self.query_tool.get_human_query_record_type() self.assertEqual(expected, actual) def test_set_query_record_type_from_value(self) -> None: """ Tests the method which let us set the type of the record with for the case that the actual value (int) of the record type is given. """ given = dns.rdatatype.RdataType.AAAA self.query_tool.set_query_record_type(given) expected = dns.rdatatype.RdataType.AAAA actual = self.query_tool.query_record_type self.assertEqual(expected, actual) expected = "AAAA" actual = self.query_tool.get_human_query_record_type() self.assertEqual(expected, actual) def test_set_query_record_type_unknown_value(self) -> None: """ Tests the method which let us set the type of the record with for the case that the actual value is unknown """ given = 1010101010110101 self.assertRaises( ValueError, lambda: self.query_tool.set_query_record_type(given) ) def test_get_dns_name_from_subject_and_query_type(self) -> None: """ Tests themethod which let us us get the dns name that dnspython has to use base on the given subject and query type. """ self.query_tool.subject = "example.org" self.query_tool.query_record_type = "A" expected = dns.name.from_text("example.org") actual = self.query_tool.get_dns_name_from_subject_and_query_type() self.assertEqual(expected, actual) def test_get_dns_name_from_subject_and_query_type_label_too_long(self) -> None: """ Tests themethod which let us us get the dns name that dnspython has to use base on the given subject and query type. In this case we check that too long entries are handled correctly. """ self.query_tool.subject = f"{secrets.token_urlsafe(300)}.org" self.query_tool.query_record_type = "A" expected = None actual = self.query_tool.get_dns_name_from_subject_and_query_type() self.assertEqual(expected, actual) def test_get_dns_name_from_subject_and_query_type_label_not_ptr_compliant( self, ) -> None: """ Tests themethod which let us us get the dns name that dnspython has to use base on the given subject and query type. In this case we check the case that a non PTR compliant IP is given. """ self.query_tool.subject = "93.184.216.34" self.query_tool.query_record_type = "PTR" expected = dns.name.from_text("34.216.184.93.in-addr.arpa") actual = self.query_tool.get_dns_name_from_subject_and_query_type() self.assertEqual(expected, actual) def test_get_dns_name_from_subject_and_query_type_label_ptr_compliant( self, ) -> None: """ Tests themethod which let us us get the dns name that dnspython has to use base on the given subject and query type. In this case we check the case that a non PTR compliant IP is given. """ self.query_tool.subject = "34.216.184.93.in-addr.arpa" self.query_tool.query_record_type = "PTR" expected = dns.name.from_text("34.216.184.93.in-addr.arpa") actual = self.query_tool.get_dns_name_from_subject_and_query_type() self.assertEqual(expected, actual) def test_set_query_record_type_not_str_nor_int(self) -> None: """ Tests the method which let us set the type of the record with for the case that the given value is not a string nor integer. """ given = ["Hello", "World!"] self.assertRaises( TypeError, lambda: self.query_tool.set_query_record_type(given) ) def test_set_timeout(self) -> None: """ Tests the method which let us set the timeout to apply. """ given = 5.0 expected = 5.0 self.query_tool.set_timeout(given) actual = self.query_tool.query_timeout self.assertEqual(expected, actual) def test_set_timeout_not_int_nor_float(self) -> None: """ Tests the method which let us set the timeout to apply for the case that the given timeout is not a float nor a integer. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.query_tool.set_timeout(given)) def test_guess_and_set_timeout(self) -> None: """ Tests the method which let us guess and set the timeout from the configuration file. """ config_loader = ConfigLoader() config_loader.set_custom_config({"lookup": {"timeout": 10.0}}).start() self.query_tool.guess_and_set_timeout() expected = 10.0 actual = self.query_tool.query_timeout self.assertEqual(expected, actual) del config_loader def test_guess_and_set_timeout_none(self) -> None: """ Tests the method which let us guess and set the timeout from the configuration file. In this test, we check the case the None is given. """ config_loader = ConfigLoader() config_loader.set_custom_config({"lookup": {"timeout": None}}).start() self.query_tool.guess_and_set_timeout() expected = self.query_tool.STD_TIMEOUT actual = self.query_tool.query_timeout self.assertEqual(expected, actual) del config_loader def test_guess_and_set_timeout_config_not_loaded(self) -> None: """ Tests the method which let us guess and set the timeout from the configuration file. In this test, we check the case the config was not loader yet. """ self.query_tool.guess_and_set_timeout() expected = self.query_tool.STD_TIMEOUT actual = self.query_tool.query_timeout self.assertEqual(expected, actual) def test_set_trust_server(self) -> None: """ Tests the method which let us trust all the given server. """ given = True expected = True self.query_tool.set_trust_server(given) actual = self.query_tool.trust_server self.assertEqual(expected, actual) def test_set_trust_server_not_bool(self) -> None: """ Tests the method which let us trust all the given server. In this test we check the case that a non-boolean value is given. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.query_tool.set_trust_server(given)) def test_set_trust_server_through_init(self) -> None: """ Tests the overwritting of the `trust_server` attribute through the class constructor. """ given = True expected = True query_tool = DNSQueryTool(trust_server=given) actual = query_tool.trust_server self.assertEqual(expected, actual) def test_guess_and_set_trust_server(self) -> None: """ Tests the method which let us guess and set the trust flag from the configuration file. """ config_loader = ConfigLoader() config_loader.set_custom_config({"dns": {"trust_server": True}}).start() self.query_tool.guess_and_set_trust_server() expected = True actual = self.query_tool.trust_server self.assertEqual(expected, actual) del config_loader def test_guess_and_set_trust_server_none(self) -> None: """ Tests the method which let us guess and set the trust flag from the configuration file. In this case, we test the case that None or implicitly a non boolean value is given. """ config_loader = ConfigLoader() config_loader.set_custom_config({"dns": {"trust_server": None}}).start() self.query_tool.guess_and_set_trust_server() expected = self.query_tool.STD_TRUST_SERVER actual = self.query_tool.trust_server self.assertEqual(expected, actual) del config_loader def test_set_preferred_protocol(self) -> None: """ Tests the method which let us set the preferred protocol. """ given = "TCP" expected = "TCP" self.query_tool.set_preferred_protocol(given) actual = self.query_tool.preferred_protocol self.assertEqual(expected, actual) def test_set_preferred_protocol_through_init(self) -> None: """ Tests the method which let us set the preferred protocol. In this test we check that the transfert of the preferred protocol through the constructor is working. """ given = "TCP" query_tool = DNSQueryTool(preferred_protocol=given) expected = "TCP" actual = query_tool.preferred_protocol self.assertEqual(expected, actual) def test_set_preferred_protocol_not_str(self) -> None: """ Tests the method which let us set the preferred protocol for the case that the given protocol is not a string. """ given = ["Hello", "World"] self.assertRaises( TypeError, lambda: self.query_tool.set_preferred_protocol(given) ) def test_set_preferred_protocol_not_supported(self) -> None: """ Tests the method which let us set the preferred protocol for the case that the given protocol is not supported. """ given = "SNMP" self.assertRaises( ValueError, lambda: self.query_tool.set_preferred_protocol(given), ) def test_guess_and_set_preferred_protocol(self) -> None: """ Tests the method which let us guess and set the preferred protocol. """ config_loader = ConfigLoader() config_loader.set_custom_config({"dns": {"protocol": "HTTPS"}}).start() self.query_tool.guess_and_set_preferred_protocol() expected = "HTTPS" actual = self.query_tool.preferred_protocol self.assertEqual(expected, actual) del config_loader def test_guess_and_set_preferred_protocol_none(self) -> None: """ Tests the method which let us guess and set the preferred protocol. In this test, we check the case that the given protocol is set to None. """ config_loader = ConfigLoader() config_loader.set_custom_config({"dns": {"protocol": None}}).start() self.query_tool.guess_and_set_preferred_protocol() expected = self.query_tool.STD_PROTOCOL actual = self.query_tool.preferred_protocol self.assertEqual(expected, actual) def test_set_delay(self) -> None: """ Tests the method which let us set the delay. """ given = 0.48 expected = 0.48 self.query_tool.set_delay(given) actual = self.query_tool.delay self.assertEqual(expected, actual) def test_set_delay_through_init(self) -> None: """ Tests the method which let us set the delay. In this test we check that the transfert of the delay through the constructor is working. """ given = 0.55 query_tool = DNSQueryTool(delay=given) expected = 0.55 actual = query_tool.delay self.assertEqual(expected, actual) def test_set_delay_not_float(self) -> None: """ Tests the method which let us set the delay for the case that the given delay is not a float or int. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.query_tool.set_delay(given)) def test_guess_and_set_delay(self) -> None: """ Tests the method which let us guess and set the delay between each queries. In this test, we check the case that the given delay is set to a value greater than 0. """ config_loader = ConfigLoader() config_loader.set_custom_config({"dns": {"delay": 0.45}}).start() self.query_tool.guess_and_set_delay() expected = 0.45 actual = self.query_tool.delay self.assertEqual(expected, actual) def test_guess_and_set_delay_less_than_zero(self) -> None: """ Tests the method which let us guess and set the delay between each queries. In this test, we check the case that the given delay is set to a value less than 0. """ config_loader = ConfigLoader() config_loader.set_custom_config({"dns": {"delay": -3.0}}).start() # pylint: disable=unnecessary-lambda self.assertRaises(ValueError, lambda: self.query_tool.guess_and_set_delay()) def test_guess_and_set_delay_none(self) -> None: """ Tests the method which let us guess and set the delay between each queries. In this test, we check the case that the given delay is set to None. """ config_loader = ConfigLoader() config_loader.set_custom_config({"dns": {"delay": None}}).start() self.query_tool.guess_and_set_delay() expected = self.query_tool.STD_DELAY actual = self.query_tool.delay self.assertEqual(expected, actual) def test_get_lookup_record(self) -> None: """ Tests the method which let us get the lookup record. """ self.query_tool.preferred_protocol = "UDP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" _ = self.query_tool.query() actual = self.query_tool.get_lookup_record() self.assertIsInstance(actual, DNSQueryToolRecord) expected = "example.org" self.assertEqual(expected, actual.subject) def test_udp_query(self) -> None: """ Tests the method which let us query through the UDP protocol. """ self.query_tool.preferred_protocol = "UDP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" _ = self.query_tool.query() self.mock_udp_query.assert_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_udp_query_no_info(self) -> None: """ Tests the method which let us query through the UDP protocol. In this test, we check the case that we don't give any information. """ # pylint: disable=unnecessary-lambda self.assertRaises(TypeError, lambda: self.query_tool.query()) self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_udp_query_timeout(self) -> None: """ Tests the method which let us query through the UDP protocol. In this case, we check the case that a timeout exception is raised. """ self.query_tool.preferred_protocol = "UDP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_udp_query.side_effect = self.timout_response _ = self.query_tool.query() self.mock_udp_query.assert_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_udp_query_malformed_input(self) -> None: """ Tests the method which let us query through the UDP protocol. In this case, we check the case that a ValueError is raised. """ self.query_tool.preferred_protocol = "UDP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_udp_query.side_effect = self.malformed_response _ = self.query_tool.query() self.mock_udp_query.assert_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_udp_query_unexpected_source(self) -> None: """ Tests the method which let us query through the UDP protocol. In this case, we check the case that an UnexpectedSource exception is raised. """ self.query_tool.preferred_protocol = "UDP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_udp_query.side_effect = self.unexpected_source_response _ = self.query_tool.query() self.mock_udp_query.assert_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_udp_query_bad_response(self) -> None: """ Tests the method which let us query through the UDP protocol. In this case, we check the case that an BadResponse exception is raised. """ self.query_tool.preferred_protocol = "UDP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_udp_query.side_effect = self.bad_response_response _ = self.query_tool.query() self.mock_udp_query.assert_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_udp_query_socket_error(self) -> None: """ Tests the method which let us query through the UDP protocol. In this case, we check the case that a socket error is raised. """ self.query_tool.preferred_protocol = "UDP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_udp_query.side_effect = self.socket_error _ = self.query_tool.query() self.mock_udp_query.assert_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_udp_query_with_result(self) -> None: """ Tests the method which let us query through the UDP protocol. In this case we check that the response is is properly parsed to the lookup record. """ self.query_tool.preferred_protocol = "UDP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.query_tool._get_result_from_response = lambda _: ["93.184.216.34"] actual = self.query_tool.query() self.mock_udp_query.assert_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() self.mock_tcp_query.assert_not_called() # pragma: no cover ## Let's trust upstream expected = ["93.184.216.34"] self.assertEqual(expected, actual) self.assertEqual(expected, self.query_tool.lookup_record.response) def test_udp_query_bad_escape(self) -> None: """ Tests the method which let us query through the UDP protocol. In this case we check the case that a subject has some bad escape character. """ self.query_tool.preferred_protocol = "UDP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org\\" _ = self.query_tool.query() # Not called because inputted is invalid. self.mock_udp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() self.mock_tcp_query.assert_not_called() def test_tcp_query(self) -> None: """ Tests the method which let us query through the TCP protocol. """ self.query_tool.preferred_protocol = "TCP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" _ = self.query_tool.query() self.mock_tcp_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_tcp_query_timeout(self) -> None: """ Tests the method which let us query through the TCP protocol. In this case, we assume that a timeout was given. """ self.query_tool.preferred_protocol = "TCP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_tcp_query.side_effect = self.timout_response _ = self.query_tool.query() self.mock_tcp_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_tcp_query_malformed_input(self) -> None: """ Tests the method which let us query through the TCP protocol. In this case, we check the case that a ValueError is raised. """ self.query_tool.preferred_protocol = "TCP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_tcp_query.side_effect = self.malformed_response _ = self.query_tool.query() self.mock_tcp_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_tcp_query_unexpected_source(self) -> None: """ Tests the method which let us query through the TCP protocol. In this case, we check the case that an UnexpectedSource exception is raised. """ self.query_tool.preferred_protocol = "TCP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_tcp_query.side_effect = self.unexpected_source_response _ = self.query_tool.query() self.mock_tcp_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_tcp_query_bad_response(self) -> None: """ Tests the method which let us query through the TCP protocol. In this case, we check the case that an BadResponse exception is raised. """ self.query_tool.preferred_protocol = "TCP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_tcp_query.side_effect = self.bad_response_response _ = self.query_tool.query() self.mock_tcp_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_tcp_query_socket_error(self) -> None: """ Tests the method which let us query through the TCP protocol. In this case, we check the case that a socket error is raised. """ self.query_tool.preferred_protocol = "TCP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_tcp_query.side_effect = self.socket_error _ = self.query_tool.query() self.mock_tcp_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_tcp_query_with_result(self) -> None: """ Tests the method which let us query through the TCP protocol. In this case we check that the response is is properly parsed to the lookup record. """ self.query_tool.preferred_protocol = "TCP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.query_tool._get_result_from_response = lambda _: ["93.184.216.34"] actual = self.query_tool.query() self.mock_tcp_query.assert_called() self.mock_tls_query.assert_not_called() self.mock_udp_query.assert_not_called() self.mock_https_query.assert_not_called() # pragma: no cover ## Let's trust upstream expected = ["93.184.216.34"] self.assertEqual(expected, actual) self.assertEqual(expected, self.query_tool.lookup_record.response) def test_tcp_query_bad_escape(self) -> None: """ Tests the method which let us query through the TCP protocol. In this case we check the case that a subject has some bad escape character. """ self.query_tool.preferred_protocol = "TCP" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org\\" _ = self.query_tool.query() # Not called because inputted is invalid. self.mock_tcp_query.assert_not_called() self.mock_udp_query.assert_not_called() self.mock_https_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_https_query(self) -> None: """ Tests the method which let us query through the HTTPS protocol. """ self.query_tool.preferred_protocol = "HTTPS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" _ = self.query_tool.query() self.mock_https_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_https_query_timeout(self) -> None: """ Tests the method which let us query through the HTTPS protocol. In this case we check the case that a timeout exception is raised. """ self.query_tool.preferred_protocol = "HTTPS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_https_query.side_effect = self.timout_response _ = self.query_tool.query() self.mock_https_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_https_query_malformed_input(self) -> None: """ Tests the method which let us query through the HTTPS protocol. In this case, we check the case that a ValueError is raised. """ self.query_tool.preferred_protocol = "HTTPS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_https_query.side_effect = self.malformed_response _ = self.query_tool.query() self.mock_https_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_https_query_socket_error(self) -> None: """ Tests the method which let us query through the HTTPS protocol. In this case, we check the case that a socket error is raised. """ self.query_tool.preferred_protocol = "HTTPS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_https_query.side_effect = self.socket_error _ = self.query_tool.query() self.mock_https_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_https_query_unexpected_source(self) -> None: """ Tests the method which let us query through the HTTPS protocol. In this case, we check the case that an UnexpectedSource exception is raised. """ self.query_tool.preferred_protocol = "HTTPS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_https_query.side_effect = self.unexpected_source_response _ = self.query_tool.query() self.mock_https_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_https_query_bad_response(self) -> None: """ Tests the method which let us query through the HTTPS protocol. In this case, we check the case that an BadResponse exception is raised. """ self.query_tool.preferred_protocol = "HTTPS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_https_query.side_effect = self.bad_response_response _ = self.query_tool.query() self.mock_https_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_https_query_with_result(self) -> None: """ Tests the method which let us query through the HTTPS protocol. In this case we check that the response is is properly parsed to the lookup record. """ self.query_tool.preferred_protocol = "HTTPS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.query_tool._get_result_from_response = lambda _: ["93.184.216.34"] actual = self.query_tool.query() self.mock_https_query.assert_called() self.mock_tls_query.assert_not_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() # pragma: no cover ## Let's trust upstream expected = ["93.184.216.34"] self.assertEqual(expected, actual) self.assertEqual(expected, self.query_tool.lookup_record.response) def test_https_query_bad_escape(self) -> None: """ Tests the method which let us query through the HTTPS protocol. In this case we check the case that a subject has some bad escape character. """ self.query_tool.preferred_protocol = "HTTPS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org\\" self.query_tool._get_result_from_response = lambda _: ["93.184.216.34"] _ = self.query_tool.query() # Not called because inputted is invalid. self.mock_https_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_udp_query.assert_not_called() self.mock_tls_query.assert_not_called() def test_tls_query(self) -> None: """ Tests the method which let us query through the TLS protocol. """ self.query_tool.preferred_protocol = "TLS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" _ = self.query_tool.query() self.mock_tls_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() def test_tls_query_timeout(self) -> None: """ Tests the method which let us query through the TLS protocol. In this case we check the case that a timeout exception is raised.Is """ self.query_tool.preferred_protocol = "TLS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_tls_query.side_effect = self.timout_response _ = self.query_tool.query() self.mock_tls_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() def test_tls_query_malformed_input(self) -> None: """ Tests the method which let us query through the TLS protocol. In this case, we check the case that a ValueError is raised. """ self.query_tool.preferred_protocol = "TLS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_tls_query.side_effect = self.malformed_response _ = self.query_tool.query() self.mock_tls_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() def test_tls_query_socket_error(self) -> None: """ Tests the method which let us query through the TLS protocol. In this case, we check the case that a socket error is raised. """ self.query_tool.preferred_protocol = "TLS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_tls_query.side_effect = self.socket_error _ = self.query_tool.query() self.mock_tls_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() def test_tls_query_unexpected_source(self) -> None: """ Tests the method which let us query through the TLS protocol. In this case, we check the case that an UnexpectedSource exception is raised. """ self.query_tool.preferred_protocol = "TLS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_tls_query.side_effect = self.unexpected_source_response _ = self.query_tool.query() self.mock_tls_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() def test_tls_query_bad_response(self) -> None: """ Tests the method which let us query through the TLS protocol. In this case, we check the case that an BadResponse exception is raised. """ self.query_tool.preferred_protocol = "TLS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.mock_tls_query.side_effect = self.bad_response_response _ = self.query_tool.query() self.mock_tls_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() def test_tls_query_with_result(self) -> None: """ Tests the method which let us query through the TLS protocol. In this case we check that the response is is properly parsed to the lookup record. """ self.query_tool.preferred_protocol = "TLS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org" self.query_tool._get_result_from_response = lambda _: ["93.184.216.34"] actual = self.query_tool.query() self.mock_tls_query.assert_called() self.mock_udp_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_https_query.assert_not_called() # pragma: no cover ## Let's trust upstream expected = ["93.184.216.34"] self.assertEqual(expected, actual) self.assertEqual(expected, self.query_tool.lookup_record.response) def test_tls_query_bad_escape(self) -> None: """ Tests the method which let us query through the TLS protocol. In this case we check the case that a subject has some bad escape character. """ self.query_tool.preferred_protocol = "TLS" self.query_tool.query_record_type = "A" self.query_tool.subject = "example.org\\" _ = self.query_tool.query() # Not called because inputted is invalid. self.mock_tls_query.assert_not_called() self.mock_tcp_query.assert_not_called() self.mock_udp_query.assert_not_called() self.mock_https_query.assert_not_called() class TestDNSQueryToolRecord(unittest.TestCase): """ Tests of our record class. """ def test_getitem(self) -> None: """ Tests the method which let us get an item. """ our_record = DNSQueryToolRecord(nameserver="hello.world", subject="world.hello") expected = "hello.world" actual = our_record.nameserver self.assertEqual(expected, actual) expected = "world.hello" actual = our_record["subject"] self.assertEqual(expected, actual) def test_to_dict(self) -> None: """ Tests the method which let us get the dict representation of the dataset. """ our_record = DNSQueryToolRecord(nameserver="hello.world", subject="world.hello") expected = {"nameserver": "hello.world", "subject": "world.hello"} actual = our_record.to_dict() expected_dataset = dict(actual, **expected) self.assertEqual(expected_dataset, our_record.to_dict()) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/query/dnss/test_resolver.py000066400000000000000000000203271467462152100231650ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our resolver provider. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 dataclasses import unittest import unittest.mock import dns.resolver from PyFunceble.config.loader import ConfigLoader from PyFunceble.query.dns.resolver import Resolver # pylint: disable=invalid-field-call class TestResolver(unittest.TestCase): """ Provides the tests of our resolver configurator. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ def fake_response(data: str) -> object: return dataclasses.make_dataclass( "FakeResponse", [("address", str, dataclasses.field(default=data))] ) def fake_resolver(_: str, rqtype: str): if rqtype == "A": return [ fake_response("192.168.1.1"), fake_response("10.47.91.9"), ] return [ fake_response("fe80::6b01:9045:a42a:fb5f"), fake_response("fe80::6b01:9049:a42a:fb5f"), ] self.resolve_patch = unittest.mock.patch.object( dns.resolver.Resolver, "resolve" ) self.mock_resolve = self.resolve_patch.start() self.mock_resolve.side_effect = fake_resolver self.resolver_provider = Resolver() def tearDown(self) -> None: """ Destroys everything previously initiated for the tests. """ self.resolve_patch.stop() del self.resolve_patch del self.mock_resolve del self.resolver_provider def test_set_nameservers(self) -> None: """ Tests the method which let us set the nameservers to work with. """ given = ["example.org"] self.resolver_provider.set_nameservers(given) expected = [ "192.168.1.1", "10.47.91.9", "fe80::6b01:9045:a42a:fb5f", "fe80::6b01:9049:a42a:fb5f", ] actual = self.resolver_provider.get_nameservers() self.assertEqual(expected, actual) expected = { "192.168.1.1": 53, "10.47.91.9": 53, "fe80::6b01:9045:a42a:fb5f": 53, "fe80::6b01:9049:a42a:fb5f": 53, } actual = self.resolver_provider.get_nameserver_ports() self.assertEqual(expected, actual) def test_set_nameservers_through_init(self) -> None: """ Tests the method which let us set the nameservers to work with. Here we check the case that the nameservers are given through the constructor. """ given = ["example.org"] resolver_provider = Resolver(nameservers=given) expected = [ "192.168.1.1", "10.47.91.9", "fe80::6b01:9045:a42a:fb5f", "fe80::6b01:9049:a42a:fb5f", ] actual = resolver_provider.get_nameservers() self.assertEqual(expected, actual) expected = { "192.168.1.1": 53, "10.47.91.9": 53, "fe80::6b01:9045:a42a:fb5f": 53, "fe80::6b01:9049:a42a:fb5f": 53, } actual = resolver_provider.get_nameserver_ports() self.assertEqual(expected, actual) def test_set_timeout(self) -> None: """ Tests the method which let us set the timeout to apply. """ given = 4.0 self.resolver_provider.set_timeout(given) expected = 4.0 actual = self.resolver_provider.get_timeout() self.assertEqual(expected, actual) def test_set_timeout_though_init(self) -> None: """ Tests the method which let us set the timeout to apply. Here we check the case that the timeout is given through the constructor. """ given = 4.0 resolver_provider = Resolver(timeout=given) expected = 4.0 actual = resolver_provider.get_timeout() self.assertEqual(expected, actual) def test_set_timeout_not_float_nor_int(self) -> None: """ Tests the method which let us set the timeout to apply for the case that it's not an int nor a float. """ given = "Hello, World!" self.assertRaises(TypeError, lambda: self.resolver_provider.set_timeout(given)) def test_guess_and_set_timeout(self) -> None: """ Tests the method which let us guess the timeout to use. """ config_loader = ConfigLoader() config_loader.set_custom_config({"lookup": {"timeout": 10.0}}).start() self.resolver_provider.guess_and_set_timeout() expected = 10.0 actual = self.resolver_provider.get_timeout() self.assertEqual(expected, actual) def test_get_resolver(self) -> None: """ Tests the method which let us get the configured resolver. """ self.resolver_provider.set_nameservers(["example.org"]) self.resolver_provider.set_timeout(5.0) the_resolver = self.resolver_provider.get_resolver() expected_timeout = 5.0 expected_lifetime = 7.0 expected_nameservers = [ "192.168.1.1", "10.47.91.9", "fe80::6b01:9045:a42a:fb5f", "fe80::6b01:9049:a42a:fb5f", ] expected_nameserver_ports = { "192.168.1.1": 53, "10.47.91.9": 53, "fe80::6b01:9045:a42a:fb5f": 53, "fe80::6b01:9049:a42a:fb5f": 53, } self.assertEqual(expected_timeout, the_resolver.timeout) self.assertEqual(expected_lifetime, the_resolver.lifetime) self.assertEqual(expected_nameservers, the_resolver.nameservers) self.assertEqual(expected_nameserver_ports, the_resolver.nameserver_ports) # Let's test the recall :-) the_second_resolver = self.resolver_provider.get_resolver() self.assertEqual(id(the_resolver), id(the_second_resolver)) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/query/netinfo/000077500000000000000000000000001467462152100204025ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/query/netinfo/__init__.py000066400000000000000000000000001467462152100225010ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/query/netinfo/test_address.py000066400000000000000000000106631467462152100234460ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our address info class. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 socket import unittest import unittest.mock from PyFunceble.query.netinfo.address import AddressInfo class TestAddressInfo(unittest.TestCase): """ Tests the of the interface which let us get the information about an address. """ @unittest.mock.patch.object(socket, "getaddrinfo") def test_get_info(self, addrinfo_path: unittest.mock.MagicMock) -> None: """ Tests the method which let us get the information to work with. """ def fake_getattrinfo(*args, **kwargs): _ = args _ = kwargs return [("192.169.1.1", "10.20.30.40", ["10.55.0.32"])] addrinfo_path.side_effect = fake_getattrinfo given = "example.org" expected = ["10.55.0.32"] actual = AddressInfo(given).get_info() self.assertEqual(expected, actual) @unittest.mock.patch.object(socket, "getaddrinfo") def test_get_info_gaierror(self, addrinfo_path: unittest.mock.MagicMock) -> None: """ Tests the method which let us get the information to work with for the case that we get an gaierror exception. """ def fake_getattrinfo(*args, **kwargs): raise socket.gaierror("This is a test :-)") addrinfo_path.side_effect = fake_getattrinfo given = "example.org" expected = [] actual = AddressInfo(given).get_info() self.assertEqual(expected, actual) @unittest.mock.patch.object(socket, "getaddrinfo") def test_get_info_herror(self, addrinfo_path: unittest.mock.MagicMock) -> None: """ Tests the method which let us get the information to work with for the case that we get an herror exception. """ def fake_getattrinfo(*args, **kwargs): raise socket.herror("This is a test :-)") addrinfo_path.side_effect = fake_getattrinfo given = "example.org" expected = [] actual = AddressInfo(given).get_info() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/query/netinfo/test_base.py000066400000000000000000000126651467462152100227370ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our our netinfo base class. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 unittest import unittest.mock from PyFunceble.query.netinfo.base import NetInfoBase class TestNetInfobase(unittest.TestCase): """ Tests the of the base of all out netinfo classes. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.interface = NetInfoBase() def tearDown(self) -> None: """ Destroys everything previously initiated. """ del self.interface def test_set_subject_return(self) -> None: """ Tests the response from the method which let us set the subject to work with. """ given = "example.com" actual = self.interface.set_subject(given) self.assertIsInstance(actual, NetInfoBase) def test_set_subject_method(self) -> None: """ Tests the method which let us set the subject to work with. """ given = "example.com" expected = "example.com" self.interface.set_subject(given) actual = self.interface.subject self.assertEqual(expected, actual) def test_set_subject_not_str(self) -> None: """ Tests the method which let us set the subject to work with for the case that a non string value is given. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.interface.set_subject(given)) def test_set_subject_empty_str(self) -> None: """ Tests the method which let us set the subject to work with for the case that an empty string is given """ given = "" self.assertRaises(ValueError, lambda: self.interface.set_subject(given)) def test_set_subject_attribute(self) -> None: """ Tests overwritting of the :code:`subject` attribute. """ given = "example.com" expected = "example.com" self.interface.subject = given actual = self.interface.subject self.assertEqual(expected, actual) def test_set_subject_through_init(self) -> None: """ Tests the overwritting of the subject to work through the class constructor. """ given = "example.com" expected = "example.com" interface = NetInfoBase(given) actual = interface.subject self.assertEqual(expected, actual) def test_get_info_no_subject_given(self) -> None: """ Tests the method which let us get the information we are looking for; for the case that no subject is given. """ # pylint: disable=unnecessary-lambda self.assertRaises(TypeError, lambda: self.interface.get_info()) def test_get_info(self) -> None: """ Tests the method which let us get the information we are looking for. """ given = "example.com" self.interface.subject = given # pylint: disable=unnecessary-lambda self.assertRaises(NotImplementedError, lambda: self.interface.get_info()) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/query/netinfo/test_hostbyaddr.py000066400000000000000000000112641467462152100241620ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our hostsbyaddr implementation. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 socket import unittest import unittest.mock from PyFunceble.query.netinfo.hostbyaddr import HostByAddrInfo class TestHostByAddrInfo(unittest.TestCase): """ Tests the of the interface which let us get the information about an address. """ @unittest.mock.patch.object(socket, "gethostbyaddr") def test_get_info(self, addrinfo_path: unittest.mock.MagicMock) -> None: """ Tests the method which let us get the information to work with. """ def fake_hostbyaddr(*args, **kwargs): _ = args _ = kwargs return ["www.example.org", ["example.org", "example.net"], ["10.55.39.20"]] addrinfo_path.side_effect = fake_hostbyaddr given = "example.org" expected = { "hostname": "www.example.org", "aliases": ["example.org", "example.net"], "ips": ["10.55.39.20"], } actual = HostByAddrInfo(given).get_info() self.assertEqual(expected, actual) @unittest.mock.patch.object(socket, "gethostbyaddr") def test_get_info_gaierror(self, addrinfo_path: unittest.mock.MagicMock) -> None: """ Tests the method which let us get the information to work with for the case that we get an gaierror exception. """ def fake_hostbyaddr(*args, **kwargs): raise socket.gaierror("This is a test :-)") addrinfo_path.side_effect = fake_hostbyaddr given = "example.org" expected = dict() # pylint: disable=use-dict-literal actual = HostByAddrInfo(given).get_info() self.assertEqual(expected, actual) @unittest.mock.patch.object(socket, "gethostbyaddr") def test_get_info_herror(self, addrinfo_path: unittest.mock.MagicMock) -> None: """ Tests the method which let us get the information to work with for the case that we get an herror exception. """ def fake_hostbyaddr(*args, **kwargs): raise socket.herror("This is a test :-)") addrinfo_path.side_effect = fake_hostbyaddr given = "example.org" expected = dict() # pylint: disable=use-dict-literal actual = HostByAddrInfo(given).get_info() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/query/test_http_status_code.py000066400000000000000000000564301467462152100237350ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the HTTP status code query tool. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest import unittest.mock import requests import requests.models import PyFunceble.factory from PyFunceble.config.loader import ConfigLoader from PyFunceble.query.http_status_code import HTTPStatusCode class TestHTTPStatusCode(unittest.TestCase): """ Tests the HTTP status code query tool. """ def setUp(self) -> None: """ Sets everything needed by the tests. """ self.query_tool = HTTPStatusCode() return super().setUp() def tearDown(self) -> None: """ Destroys everything needed by the tests. """ del self.query_tool def test_set_subject_return(self) -> None: """ Tests the response from the method which let us set the subject to work with. """ given = "example.org" actual = self.query_tool.set_subject(given) self.assertIsInstance(actual, HTTPStatusCode) def test_set_subject_method(self) -> None: """ Tests the method which let us set the subject to work with. """ given = "example.org" expected = "example.org" self.query_tool.set_subject(given) actual = self.query_tool.subject self.assertEqual(expected, actual) def test_set_subject_attribute(self) -> None: """ Tests overwritting of the :code:`subject` attribute. """ given = "example.org" expected = "example.org" self.query_tool.subject = given actual = self.query_tool.subject self.assertEqual(expected, actual) def test_set_subject_through_init(self) -> None: """ Tests the overwritting of the subject to work through the class constructor. """ given = "example.org" expected = "example.org" query_tool = HTTPStatusCode(subject=given) actual = query_tool.subject self.assertEqual(expected, actual) def test_set_subject_not_str(self) -> None: """ Tests the method which let us set the subject to work with for the case that the given subject is not a :py:class:`str`. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.query_tool.set_subject(given)) def test_set_subject_empty_str(self) -> None: """ Tests the method which let us set the subject to work with for the case that the given subject is an empty :py:class:`str`. """ given = "" self.assertRaises(ValueError, lambda: self.query_tool.set_subject(given)) def test_set_timeout_return(self) -> None: """ Tests the response from the method which let us set the timeout to work with. """ given = 15.0 actual = self.query_tool.set_timeout(given) self.assertIsInstance(actual, HTTPStatusCode) def test_set_timeout_method(self) -> None: """ Tests the method which let us set the timeout to work with. """ given = 15.0 expected = 15.0 self.query_tool.set_timeout(given) actual = self.query_tool.timeout self.assertEqual(expected, actual) def test_set_timeout_attribute(self) -> None: """ Tests overwritting of the :code:`timeout` attribute. """ given = 15.0 expected = 15.0 self.query_tool.timeout = given actual = self.query_tool.timeout self.assertEqual(expected, actual) def test_set_timeout_through_init(self) -> None: """ Tests the overwritting of the timeout to work through the class constructor. """ given = 15.0 expected = 15.0 query_tool = HTTPStatusCode(timeout=given) actual = query_tool.timeout self.assertEqual(expected, actual) def test_set_timeout_not_int_nor_float(self) -> None: """ Tests the method which let us set the timeout to work with for the case that the given timeout is not a :py:class:`int`. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.query_tool.set_timeout(given)) def test_set_timeout_lower_than_1(self) -> None: """ Tests the method which let us set the timeout to work with for the case that the given timeout is less than 1. """ given = 0.5 expected = 0.5 query_tool = HTTPStatusCode(timeout=given) actual = query_tool.timeout self.assertEqual(expected, actual) def test_set_timeout_equal_0(self) -> None: """ Tests the method which let us set the timeout to work with for the case that the given timeout is equal to 0. """ given = 0 expected = 0.0 query_tool = HTTPStatusCode(timeout=given) actual = query_tool.timeout self.assertEqual(expected, actual) def test_set_timeout_lower_0(self) -> None: """ Tests the method which let us set the timeout to work with for the case that the given timeout is lower then 0. """ given = -3 self.assertRaises(ValueError, lambda: self.query_tool.set_timeout(given)) def test_guess_and_set_timeout(self) -> None: """ Tests the method which let us guess and set the timeout from the configuration file. """ config_loader = ConfigLoader() config_loader.set_custom_config({"lookup": {"timeout": 15.0}}).start() self.query_tool.guess_and_set_timeout() expected = 15.0 actual = self.query_tool.timeout self.assertEqual(expected, actual) del config_loader def test_guess_and_set_timeout_config_not_loaded(self) -> None: """ Tests the method which let us guess and set the timeout from the configuration file. """ self.query_tool.guess_and_set_timeout() expected = self.query_tool.STD_TIMEOUT actual = self.query_tool.timeout self.assertEqual(expected, actual) def test_set_verify_certificate_return(self) -> None: """ Tests the response from the method which let us activate or disable the certificate verification. """ given = True actual = self.query_tool.set_verify_certificate(given) self.assertIsInstance(actual, HTTPStatusCode) def test_set_verify_certificate_method(self) -> None: """ Tests the method which let us activate or disable the certificate verification. """ given = True expected = True self.query_tool.set_verify_certificate(given) actual = self.query_tool.verify_certificate self.assertEqual(expected, actual) def test_set_verify_certificate_attribute(self) -> None: """ Tests overwritting of the :code:`verify_certificate` attribute. """ given = True expected = True self.query_tool.verify_certificate = given actual = self.query_tool.verify_certificate self.assertEqual(expected, actual) def test_set_verify_certificate_through_init(self) -> None: """ Tests the overwritting of the value of the certificate validation through the class constructor. """ given = True expected = True query_tool = HTTPStatusCode(verify_certificate=given) actual = query_tool.verify_certificate self.assertEqual(expected, actual) def test_set_verify_certificate_not_bool(self) -> None: """ Tests the method which let us activate or disable the certificate validation for the case that the given value is not a :py:class`bool`. """ given = ["Hello", "World!"] self.assertRaises( TypeError, lambda: self.query_tool.set_verify_certificate(given) ) def test_guess_and_set_verify_certificate(self) -> None: """ Tests the method which let us guess and set the certificate verification attribute from the configuration file. """ config_loader = ConfigLoader() config_loader.set_custom_config({"verify_ssl_certificate": True}).start() self.query_tool.guess_and_set_verify_certificate() expected = True actual = self.query_tool.verify_certificate self.assertEqual(expected, actual) del config_loader def test_guess_and_set_certificate_verification_config_not_loaded(self) -> None: """ Tests the method which let us guess and set the certificate verification from the configuration file. """ self.query_tool.guess_and_set_verify_certificate() expected = self.query_tool.STD_VERIFY_CERTIFICATE actual = self.query_tool.verify_certificate self.assertEqual(expected, actual) def test_set_allow_redirects_return(self) -> None: """ Tests the response from the method which let us allow the redirection. """ given = True actual = self.query_tool.set_allow_redirects(given) self.assertIsInstance(actual, HTTPStatusCode) def test_set_allow_redirects_method(self) -> None: """ Tests the method which let us allow the redirection. """ given = True expected = True self.query_tool.set_allow_redirects(given) actual = self.query_tool.allow_redirects self.assertEqual(expected, actual) def test_set_allow_redirects_not_bool(self) -> None: """ Tests the method which let us allow the redirection for the case that the given value is not a boolean. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.query_tool.set_allow_redirects(given)) def test_set_allow_redirects_attribute(self) -> None: """ Tests overwritting of the :code:`allow_redirects` attribute. """ given = True expected = True self.query_tool.allow_redirects = given actual = self.query_tool.allow_redirects self.assertEqual(expected, actual) def test_set_allow_redirects_through_init(self) -> None: """ Tests the overwritting of the attribute which let us allow the redirection. """ given = True expected = True query_tool = HTTPStatusCode(allow_redirects=given) actual = query_tool.allow_redirects self.assertEqual(expected, actual) def test_get_status_code_no_subject(self) -> None: """ Tests the method which let us get the status code of the given subject for the case that no subject is actually given. """ # pylint: disable=unnecessary-lambda self.assertRaises(TypeError, lambda: self.query_tool.get_status_code()) @unittest.mock.patch.object(PyFunceble.factory.Requester, "get") def test_get_status_code(self, request_mock) -> None: """ Tests the method which let us get the status code of the given subject. """ def mocking(*args, **kwargs): # pylint: disable=unused-argument response_content = "I'm a teapot." response = requests.models.Response() response.url = "https://example.org" response.status_code = 418 # pylint: disable=protected-access response._content = str.encode(response_content) response.history = [response] return response self.query_tool.subject = "https://example.org" request_mock.side_effect = mocking expected = 418 actual = self.query_tool.get_status_code() self.assertEqual(expected, actual) @unittest.mock.patch.object(PyFunceble.factory.Requester, "get") def test_get_status_code_error(self, request_mock) -> None: """ Tests the method which let us get the status code of the given subject for the case that an error happened during the request. """ def mocking(*args, **kwargs): # pylint: disable=unused-argument raise PyFunceble.factory.Requester.exceptions.ConnectionError( "I'm a teapot." ) self.query_tool.subject = "https://example.org" request_mock.side_effect = mocking expected = self.query_tool.STD_UNKNOWN_STATUS_CODE actual = self.query_tool.get_status_code() self.assertEqual(expected, actual) @unittest.mock.patch.object(PyFunceble.factory.Requester, "get") def test_get_status_code_too_many_redirects(self, request_mock) -> None: """ Tests the method which let us get the status code of the given subject for the case that too many redirects happened during the request. """ def mocking(*args, **kwargs): # pylint: disable=unused-argument raise PyFunceble.factory.Requester.exceptions.TooManyRedirects( "Exceeded 30 redirects." ) self.query_tool.subject = "https://example.org" request_mock.side_effect = mocking expected = self.query_tool.STD_UNKNOWN_STATUS_CODE actual = self.query_tool.get_status_code() self.assertEqual(expected, actual) @unittest.mock.patch.object(PyFunceble.factory.Requester, "get") def test_get_status_code_http_to_https(self, request_mock) -> None: """ Tests the method which let us get the status code of the given subject for the case that a redirection from HTTP to HTTPS is done. """ def mocking(*args, **kwargs): # pylint: disable=unused-argument first_response = requests.models.Response() first_response.headers = {"Location": "https://example.org"} first_response.url = "http://example.org" first_response.status_code = 302 final_response = requests.models.Response() final_response.url = "https://example.org" final_response.status_code = 200 # pylint: disable=protected-access final_response._content = "Hello, World!".encode("utf-8") final_response.history = [first_response] return final_response self.query_tool.subject = "http://example.org" request_mock.side_effect = mocking expected = 200 actual = self.query_tool.get_status_code() self.assertEqual(expected, actual) @unittest.mock.patch.object(PyFunceble.factory.Requester, "get") def test_get_status_code_http_to_https_different_subject( self, request_mock ) -> None: """ Tests the method which let us get the status code of the given subject for the case that a redirection from HTTP to HTTPS is done but the subject of the HTTPS query is different from the original one. """ def mocking(*args, **kwargs): # pylint: disable=unused-argument first_response = requests.models.Response() first_response.headers = {"Location": "https://test.example.org"} first_response.url = "http://example.org" first_response.status_code = 302 final_response = requests.models.Response() final_response.url = "https://test.example.org" final_response.status_code = 200 # pylint: disable=protected-access final_response._content = "Hello, World!".encode("utf-8") final_response.history = [first_response] return final_response self.query_tool.subject = "http://example.org" request_mock.side_effect = mocking expected = 302 actual = self.query_tool.get_status_code() self.assertEqual(expected, actual) @unittest.mock.patch.object(PyFunceble.factory.Requester, "get") def test_get_status_code_http_to_https_different_subject_allow_redirects( self, request_mock ) -> None: """ Tests the method which let us get the status code of the given subject for the case that a redirection from HTTP to HTTPS is done but the subject of the HTTPS query is different from the original one. In this case, we forces the interface to follow the redirect. Meaning that the status code of the final one should be always returned. """ def mocking(*args, **kwargs): # pylint: disable=unused-argument first_response = requests.models.Response() first_response.headers = {"Location": "https://test.example.org"} first_response.url = "http://example.org" first_response.status_code = 302 final_response = requests.models.Response() final_response.url = "https://test.example.org" final_response.status_code = 200 # pylint: disable=protected-access final_response._content = "Hello, World!".encode("utf-8") final_response.history = [first_response] return final_response self.query_tool.allow_redirects = True self.query_tool.subject = "http://example.org" request_mock.side_effect = mocking expected = 200 actual = self.query_tool.get_status_code() self.assertEqual(expected, actual) @unittest.mock.patch.object(PyFunceble.factory.Requester, "get") def test_get_status_code_http_to_https_multiple_jump(self, request_mock) -> None: """ Tests the method which let us get the status code of the given subject for the case that a redirection from HTTP to HTTPS is done but other redirect came along the route. In this case, only the first one (in the row) should be provided. """ def mocking(*args, **kwargs): # pylint: disable=unused-argument first_response = requests.models.Response() first_response.headers = {"Location": "https://test.example.org"} first_response.url = "http://example.org" first_response.status_code = 301 second_response = requests.models.Response() second_response.headers = {"Location": "https://test2.example.org"} second_response.url = "https://test.example.org" second_response.status_code = 302 third_response = requests.models.Response() third_response.headers = {"Location": "https://example.org"} third_response.url = "https://test2.example.org" third_response.status_code = 302 final_response = requests.models.Response() final_response.url = "https://test.example.org" final_response.status_code = 200 # pylint: disable=protected-access final_response._content = "Hello, World!".encode("utf-8") final_response.history = [first_response, second_response, third_response] return final_response self.query_tool.subject = "http://example.org" request_mock.side_effect = mocking expected = 301 actual = self.query_tool.get_status_code() self.assertEqual(expected, actual) @unittest.mock.patch.object(PyFunceble.factory.Requester, "get") def test_get_status_code_http_to_https_multiple_jump_allow_redirects( self, request_mock ) -> None: """ Tests the method which let us get the status code of the given subject for the case that a redirection from HTTP to HTTPS is done but other redirect came along the route. In this case we force the interface to follow the redirect. Meaning that the final status code should be provided. """ def mocking(*args, **kwargs): # pylint: disable=unused-argument first_response = requests.models.Response() first_response.headers = {"Location": "https://test.example.org"} first_response.url = "http://example.org" first_response.status_code = 301 second_response = requests.models.Response() second_response.headers = {"Location": "https://test2.example.org"} second_response.url = "https://test.example.org" second_response.status_code = 302 third_response = requests.models.Response() third_response.headers = {"Location": "https://example.org"} third_response.url = "https://test2.example.org" third_response.status_code = 302 final_response = requests.models.Response() final_response.url = "https://test.example.org" final_response.status_code = 200 # pylint: disable=protected-access final_response._content = "Hello, World!".encode("utf-8") final_response.history = [first_response, second_response, third_response] return final_response self.query_tool.allow_redirects = True self.query_tool.subject = "http://example.org" request_mock.side_effect = mocking expected = 200 actual = self.query_tool.get_status_code() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/query/test_platform.py000066400000000000000000001141241467462152100222000ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the Platform query tool. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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. """ # pylint: disable=too-many-lines import json import os import secrets import unittest import unittest.mock from datetime import datetime, timezone import requests import requests.models from PyFunceble.checker.availability.status import AvailabilityCheckerStatus from PyFunceble.config.loader import ConfigLoader from PyFunceble.query.platform import PlatformQueryTool class TestPlatformQueryTool(unittest.TestCase): """ Tests the Platform query tool. """ def setUp(self) -> None: """ Sets everything needed by the tests. """ self.query_tool = PlatformQueryTool() self.response_dataset = { "subject": "example.net", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "status": { "syntax": { "latest": { "status": "VALID", "status_source": "SYNTAX", "tested_at": "2021-09-28T19:32:07.167Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", }, "frequent": "VALID", }, "availability": { "latest": { "status": "ACTIVE", "status_source": "WHOIS", "tested_at": "2021-09-28T19:32:07.167Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", }, "frequent": "ACTIVE", }, "reputation": { "latest": { "status": "SANE", "status_source": "REPUTATION", "tested_at": "2021-09-28T19:32:07.167Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", }, "frequent": "SANE", }, "whois": { "expiration_date": "2021-09-28T19:32:07.167Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "subject_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", }, }, } self.status_dataset = { "status": "ACTIVE", "status_source": "WHOIS", "tested_at": "2021-09-28T20:55:41.730Z", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "subject_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", } self.availability_status_dataset = { "checker_type": "AVAILABILITY", "dns_lookup": {"NS": ["a.iana-servers.net.", "b.iana-servers.net."]}, "dns_lookup_record": { "dns_name": "example.com.", "follow_nameserver_order": True, "nameserver": "9.9.9.9", "port": 53, "preferred_protocol": "UDP", "query_record_type": "NS", "query_timeout": 5.0, "response": ["a.iana-servers.net.", "b.iana-servers.net."], "subject": "example.com", "used_protocol": "UDP", }, "domain_syntax": True, "expiration_date": None, "http_status_code": None, "idna_subject": "example.com", "ip_syntax": False, "ipv4_range_syntax": False, "ipv4_syntax": False, "ipv6_range_syntax": False, "ipv6_syntax": False, "netinfo": None, "params": { "do_syntax_check_first": False, "use_dns_lookup": True, "use_extra_rules": True, "use_http_code_lookup": True, "use_netinfo_lookup": True, "use_reputation_lookup": False, "use_whois_db": True, "use_whois_lookup": False, }, "second_level_domain_syntax": True, "status": "ACTIVE", "status_after_extra_rules": None, "status_before_extra_rules": None, "status_source": "DNSLOOKUP", "status_source_after_extra_rules": None, "status_source_before_extra_rules": None, "subdomain_syntax": False, "subject": "example.com", "tested_at": datetime.fromisoformat( "2021-03-09T17:42:15.771647" ).astimezone(timezone.utc), "url_syntax": False, "whois_lookup_record": { "expiration_date": None, "port": 43, "query_timeout": 5.0, "record": None, "server": None, "subject": "example.com", }, "whois_record": None, } return super().setUp() def tearDown(self) -> None: """ Destroys everything needed by the tests. """ del self.query_tool del self.response_dataset del self.availability_status_dataset def test_set_token_return(self) -> None: """ Tests the response from the method which let us set the token to work with. """ given = secrets.token_urlsafe(6) actual = self.query_tool.set_token(given) self.assertIsInstance(actual, PlatformQueryTool) def test_set_token_method(self) -> None: """ Tests the method which let us set the token to work with. """ given = secrets.token_urlsafe(6) expected = given self.query_tool.set_token(given) actual = self.query_tool.token self.assertEqual(expected, actual) def test_set_token_attribute(self) -> None: """ Tests the overwritting of the token attribute. """ given = secrets.token_urlsafe(6) expected = given self.query_tool.token = given actual = self.query_tool.token self.assertEqual(expected, actual) def test_set_token_through_init(self) -> None: """ Tests the overwritting of the token to work through the class constructor. """ given = secrets.token_urlsafe(6) expected = given query_tool = PlatformQueryTool(token=given) actual = query_tool.token self.assertEqual(expected, actual) def test_set_token_through_init_environment_variable_not_given(self) -> None: """ Tests the overwritting of the token to work through the class constructor. In this test we test the case that nothing is given or declared. """ if "PYFUNCEBLE_COLLECTION_API_TOKEN" in os.environ: del os.environ["PYFUNCEBLE_COLLECTION_API_TOKEN"] if "PYFUNCEBLE_PLATFORM_API_TOKEN" in os.environ: del os.environ["PYFUNCEBLE_PLATFORM_API_TOKEN"] expected = "" query_tool = PlatformQueryTool(token=None) actual = query_tool.token self.assertEqual(expected, actual) def test_set_token_through_init_environment_variable_given(self) -> None: """ Tests the overwritting of the token to work through the class constructor. In this test we test the case that the environment variable is given. """ given = secrets.token_urlsafe(6) expected = given if "PYFUNCEBLE_COLLECTION_API_TOKEN" in os.environ: del os.environ["PYFUNCEBLE_COLLECTION_API_TOKEN"] os.environ["PYFUNCEBLE_PLATFORM_API_TOKEN"] = given query_tool = PlatformQueryTool(token=None) actual = query_tool.token self.assertEqual(expected, actual) def test_set_token_not_str(self) -> None: """ Tests the method which let us set the token to work with for the case that the given token is not a :py:class:`str`. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.query_tool.set_token(given)) def test_set_url_base_not_str(self) -> None: """ Tests the method which let us set the URL to work from for the case that the given URL is not a :py:class:`str`. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.query_tool.set_url_base(given)) def test_set_url_base_not_url(self) -> None: """ Tests the method which let us set the URL to work from for the case that the given URL is not a supported URL. """ given = "example.org" self.assertRaises(ValueError, lambda: self.query_tool.set_url_base(given)) def test_set_url_base_ends_with_slash(self) -> None: """ Tests the method which let us set the URL to work from for the case that the given URL is not a supported URL. """ given = "http://example.org/" expected = "http://example.org" self.query_tool.url_base = given actual = self.query_tool.url_base self.assertEqual(expected, actual) def test_set_preferred_status_origin_return(self) -> None: """ Tests the response from the method which let us set the preferred status origin. """ given = "latest" actual = self.query_tool.set_preferred_status_origin(given) self.assertIsInstance(actual, PlatformQueryTool) def test_set_preferred_status_origin_method(self) -> None: """ Tests the method which let us set the preferred status origin. """ given = "frequent" expected = given self.query_tool.set_preferred_status_origin(given) actual = self.query_tool.preferred_status_origin self.assertEqual(expected, actual) def test_set_preferred_status_origin_attribute(self) -> None: """ Tests the overwritting of the the preferred status origin. """ given = "latest" expected = given self.query_tool.preferred_status_origin = given actual = self.query_tool.preferred_status_origin self.assertEqual(expected, actual) def test_setpreferred_status_origin_through_init(self) -> None: """ Tests the overwritting of the preferred status origin through the class constructor. """ given = "frequent" expected = given query_tool = PlatformQueryTool(preferred_status_origin=given) actual = query_tool.preferred_status_origin self.assertEqual(expected, actual) def test_set_preferred_status_origin_through_init_none_given(self) -> None: """ Tests the overwritting of the preferred status origin through the class constructor. In this test, we test the case that nothing is given. """ given = None expected = "frequent" query_tool = PlatformQueryTool(preferred_status_origin=given) actual = query_tool.preferred_status_origin self.assertEqual(expected, actual) def test_set_preferred_status_origin_not_str(self) -> None: """ Tests the method which let us set the preferred status origin for the case that the given value is not a :py:class:`str`. """ given = ["Hello", "World!"] self.assertRaises( TypeError, lambda: self.query_tool.set_preferred_status_origin(given) ) def test_set_preferred_status_origin_not_supported(self) -> None: """ Tests the method which let us set the URL to work from for the case that the given URL is not a supported URL. """ given = "hello" self.assertRaises( ValueError, lambda: self.query_tool.set_preferred_status_origin(given) ) def test_guess_and_set_preferred_status_origin(self) -> None: """ Tests the method which let us guess and set the preferred status origin. """ config_loader = ConfigLoader() config_loader.set_custom_config( {"platform": {"preferred_status_origin": "latest"}} ).start() self.query_tool.guess_and_set_preferred_status_origin() expected = "latest" actual = self.query_tool.preferred_status_origin self.assertEqual(expected, actual) del config_loader def test_guess_and_set_preferred_status_origin_not_str(self) -> None: """ Tests the method which let us guess and set the preferred status origin. """ config_loader = ConfigLoader() config_loader.set_custom_config( {"platform": {"preferred_status_origin": None}} ).start() self.query_tool.guess_and_set_preferred_status_origin() expected = "frequent" actual = self.query_tool.preferred_status_origin self.assertEqual(expected, actual) del config_loader def test_set_checker_priority_return(self) -> None: """ Tests the response from the method which let us set the checker priority to use. """ given = ["reputation", "syntax", "availability"] actual = self.query_tool.set_checker_priority(given) self.assertIsInstance(actual, PlatformQueryTool) def test_set_checker_priority_method(self) -> None: """ Tests the method which let us set the checker priority to use. """ given = ["availability", "syntax", "reputation"] expected = given self.query_tool.set_checker_priority(given) actual = self.query_tool.checker_priority self.assertEqual(expected, actual) def test_set_checker_priority_attribute(self) -> None: """ Tests the overwritting of the the checker priority. """ given = ["syntax", "availability", "reputation"] expected = given self.query_tool.checker_priority = given actual = self.query_tool.checker_priority self.assertEqual(expected, actual) def test_checker_priority_through_init(self) -> None: """ Tests the overwritting of the checker priority through the class constructor. """ given = ["reputation", "syntax", "availability"] expected = given query_tool = PlatformQueryTool(checker_priority=given) actual = query_tool.checker_priority self.assertEqual(expected, actual) def test_set_checker_priority_init_none_given(self) -> None: """ Tests the overwritting of the checker through the class constructor. In this test, we test the case that nothing is given. """ given = None expected = ["none"] query_tool = PlatformQueryTool(checker_priority=given) actual = query_tool.checker_priority self.assertEqual(expected, actual) def test_set_checker_priority_not_str(self) -> None: """ Tests the method which let us set the checker priority for the case that a given value is not a :py:class:`str`. """ given = ["reputation", "syntax", 123] self.assertRaises( TypeError, lambda: self.query_tool.set_checker_priority(given) ) def test_set_checker_priority_not_supported(self) -> None: """ Tests the method which let us set the checker priority to work from for the case that the given checker is not supported. """ given = ["reputation", "syntax", "hello"] self.assertRaises( ValueError, lambda: self.query_tool.set_checker_priority(given) ) def test_guess_and_set_checker_priority(self) -> None: """ Tests the method which let us guess and set the checker type. """ config_loader = ConfigLoader() config_loader.set_custom_config( {"platform": {"checker_priority": ["reputation", "syntax", "availability"]}} ).start() self.query_tool.guess_and_set_checker_priority() expected = ["reputation", "syntax", "availability"] actual = self.query_tool.checker_priority self.assertEqual(expected, actual) del config_loader def test_guess_and_set_checker_priority_not_str(self) -> None: """ Tests the method which let us guess and set the checker priority. """ config_loader = ConfigLoader() config_loader.set_custom_config( {"platform": {"checker_priority": None}} ).start() self.query_tool.guess_and_set_checker_priority() expected = ["none"] actual = self.query_tool.checker_priority self.assertEqual(expected, actual) del config_loader def test_set_checker_exclude_return(self) -> None: """ Tests the response from the method which let us set the checker to exclude. """ given = ["reputation", "syntax", "availability"] actual = self.query_tool.set_checker_exclude(given) self.assertIsInstance(actual, PlatformQueryTool) def test_set_checker_exclude_method(self) -> None: """ Tests the method which let us set the checker to exclude. """ given = ["availability", "syntax", "reputation"] expected = given self.query_tool.set_checker_exclude(given) actual = self.query_tool.checker_exclude self.assertEqual(expected, actual) def test_set_checker_exclude_attribute(self) -> None: """ Tests the overwritting of the checker exclude to use. """ given = ["syntax", "availability", "reputation"] expected = given self.query_tool.checker_exclude = given actual = self.query_tool.checker_exclude self.assertEqual(expected, actual) def test_checker_exclude_through_init(self) -> None: """ Tests the overwritting of the checker to exclude through the class constructor. """ given = ["reputation", "syntax", "availability"] expected = given query_tool = PlatformQueryTool(checker_exclude=given) actual = query_tool.checker_exclude self.assertEqual(expected, actual) def test_set_checker_exclude_init_none_given(self) -> None: """ Tests the overwritting of the checker through the class constructor. In this test, we test the case that nothing is given. """ given = None expected = ["none"] query_tool = PlatformQueryTool(checker_exclude=given) actual = query_tool.checker_exclude self.assertEqual(expected, actual) def test_set_checker_exclude_not_str(self) -> None: """ Tests the method which let us set the checker exclude for the case that a given value is not a :py:class:`str`. """ given = ["reputation", "syntax", 123] self.assertRaises(TypeError, lambda: self.query_tool.set_checker_exclude(given)) def test_set_checker_exclude_not_supported(self) -> None: """ Tests the method which let us set the checker exclude to work with for the case that the given checker is not supported. """ given = ["syntax", "reputation", "hello"] self.assertRaises( ValueError, lambda: self.query_tool.set_checker_exclude(given) ) def test_guess_and_set_checker_exclude(self) -> None: """ Tests the method which let us guess and set the checker type to exclude. """ config_loader = ConfigLoader() config_loader.set_custom_config( {"platform": {"checker_exclude": ["syntax", "reputation", "availability"]}} ).start() self.query_tool.guess_and_set_checker_exclude() expected = ["syntax", "reputation", "availability"] actual = self.query_tool.checker_exclude self.assertEqual(expected, actual) del config_loader def test_guess_and_set_checker_exclude_not_str(self) -> None: """ Tests the method which let us guess and set the checker to exclude. """ config_loader = ConfigLoader() config_loader.set_custom_config({"platform": {"checker_exclude": None}}).start() self.query_tool.guess_and_set_checker_exclude() expected = ["none"] actual = self.query_tool.checker_exclude self.assertEqual(expected, actual) del config_loader @unittest.mock.patch.object(requests.Session, "post") def test_platform_contain(self, request_mock) -> None: """ Tests the method which let us pull the subject from the platform. """ response_dict = self.response_dataset response_dict["subject"] = "example.com" def mocking(*args, **kwargs): # pylint: disable=unused-argument response_content = json.dumps(response_dict) response = requests.models.Response() response.url = "https://example.org/v1/search" response.status_code = 200 # pylint: disable=protected-access response._content = str.encode(response_content) response.history = [response] return response self.query_tool.url_base = "https://example.org" request_mock.side_effect = mocking expected = True actual = "example.com" in self.query_tool self.assertEqual(expected, actual) @unittest.mock.patch.object(requests.Session, "post") def test_platform_not_contain(self, request_mock) -> None: """ Tests the method which let us pull the subject from the platform. """ response_dict = {"detail": "Invalid subject."} def mocking(*args, **kwargs): # pylint: disable=unused-argument response_content = json.dumps(response_dict) response = requests.models.Response() response.url = "https://example.org/v1/search" response.status_code = 404 # pylint: disable=protected-access response._content = str.encode(response_content) response.history = [response] return response self.query_tool.url_base = "https://example.org" request_mock.side_effect = mocking expected = False actual = "example.com" in self.query_tool self.assertEqual(expected, actual) @unittest.mock.patch.object(requests.Session, "post") def test_getitem(self, request_mock) -> None: """ Tests the method which let us pull the subject from the platform. """ response_dict = self.response_dataset response_dict["subject"] = "example.org" def mocking(*args, **kwargs): # pylint: disable=unused-argument response_content = json.dumps(response_dict) response = requests.models.Response() response.url = "https://example.org/v1/search" response.status_code = 200 # pylint: disable=protected-access response._content = str.encode(response_content) response.history = [response] return response self.query_tool.url_base = "https://example.org" request_mock.side_effect = mocking expected = response_dict actual = self.query_tool["example.org"] self.assertEqual(expected, actual) @unittest.mock.patch.object(requests.Session, "post") def test_getitem_not_found(self, request_mock) -> None: """ Tests the method which let us pull the subject from the platform. """ response_dict = {"detail": "Invalid subject."} def mocking(*args, **kwargs): # pylint: disable=unused-argument response_content = json.dumps(response_dict) response = requests.models.Response() response.url = "https://example.org/v1/search" response.status_code = 404 # pylint: disable=protected-access response._content = str.encode(response_content) response.history = [response] return response self.query_tool.url_base = "https://example.org" request_mock.side_effect = mocking expected = None actual = self.query_tool["example.de"] self.assertEqual(expected, actual) @unittest.mock.patch.object(requests.Session, "post") def test_pull(self, request_mock) -> None: """ Tests the method which let us pull the subject from the platform. """ response_dict = self.response_dataset response_dict["subject"] = "example.net" def mocking(*args, **kwargs): # pylint: disable=unused-argument response_content = json.dumps(response_dict) response = requests.models.Response() response.url = "https://example.org/v1/search" response.status_code = 200 # pylint: disable=protected-access response._content = str.encode(response_content) response.history = [response] return response self.query_tool.url_base = "https://example.org" request_mock.side_effect = mocking expected = response_dict actual = self.query_tool.pull("example.net") self.assertEqual(expected, actual) @unittest.mock.patch.object(requests.Session, "post") def test_pull_subject_not_found(self, request_mock) -> None: """ Tests the method which let us pull the subject from the platform. In this test case we check what happens when a subject is not found. """ response_dict = {"detail": "Invalid subject."} def mocking(*args, **kwargs): # pylint: disable=unused-argument response_content = json.dumps(response_dict) response = requests.models.Response() response.url = "https://example.org/v1/search" response.status_code = 404 # pylint: disable=protected-access response._content = str.encode(response_content) response.history = [response] return response self.query_tool.url_base = "https://example.org" request_mock.side_effect = mocking expected = None actual = self.query_tool.pull("example.net") self.assertEqual(expected, actual) @unittest.mock.patch.object(requests.Session, "post") def test_pull_subject_no_json_response(self, request_mock) -> None: """ Tests the method which let us pull the subject from the platform. In this test case we check what happens when no JSON response is given. """ def mocking(*args, **kwargs): # pylint: disable=unused-argument response_content = "I'm a teapot." response = requests.models.Response() response.url = "https://example.org/v1/search" response.status_code = 418 # pylint: disable=protected-access response._content = str.encode(response_content) response.history = [response] return response self.query_tool.url_base = "https://example.org" request_mock.side_effect = mocking expected = None actual = self.query_tool.pull("example.net") self.assertEqual(expected, actual) def test_pull_subject_not_str(self) -> None: """ Tests the method which let us pull the subject from the platform. In this test we test the case that the given subject is not a :py:class:`str`. """ self.query_tool.url_base = "https://example.org" self.assertRaises(TypeError, lambda: self.query_tool.pull(284)) @unittest.mock.patch.object(requests.Session, "post") def test_push(self, request_mock) -> None: """ Tests the method which let us push some dataset into the platform. """ response_dict = self.response_dataset response_dict["subject"] = "example.net" def mocking(*args, **kwargs): # pylint: disable=unused-argument response_content = json.dumps(response_dict) response = requests.models.Response() response.url = "https://example.org/v1/status/availability" response.status_code = 200 # pylint: disable=protected-access response._content = str.encode(response_content) response.history = [response] return response self.query_tool.url_base = "https://example.org" self.query_tool.token = secrets.token_urlsafe(6) request_mock.side_effect = mocking expected = response_dict actual = self.query_tool.push( AvailabilityCheckerStatus(**self.availability_status_dataset) ) self.assertEqual(expected, actual) @unittest.mock.patch.object(requests.Session, "post") def test_push_no_json_response(self, request_mock) -> None: """ Tests the method which let us push some dataset into the platform. In this test case, we test the case that the response is not JSON encoded. """ response_dict = self.response_dataset response_dict["subject"] = "example.net" def mocking(*args, **kwargs): # pylint: disable=unused-argument response_content = "I'm a teapot." response = requests.models.Response() response.url = "https://example.org/v1/status/availability" response.status_code = 418 # pylint: disable=protected-access response._content = str.encode(response_content) response.history = [response] return response self.query_tool.url_base = "https://example.org" request_mock.side_effect = mocking expected = None actual = self.query_tool.push( AvailabilityCheckerStatus(**self.availability_status_dataset) ) self.assertEqual(expected, actual) @unittest.mock.patch.object(requests.Session, "post") def test_push_with_whois(self, request_mock) -> None: """ Tests the method which let us push some dataset into the platform. """ response_dict = self.response_dataset response_dict["subject"] = "example.net" self.availability_status_dataset["expiration_date"] = "23-nov-2090" def mocking(*args, **kwargs): # pylint: disable=unused-argument response_content = json.dumps(response_dict) response = requests.models.Response() response.url = "https://example.org/v1/status/availability" response.status_code = 200 # pylint: disable=protected-access response._content = str.encode(response_content) response.history = [response] return response self.query_tool.url_base = "https://example.org" self.query_tool.token = secrets.token_urlsafe(6) request_mock.side_effect = mocking expected = response_dict actual = self.query_tool.push( AvailabilityCheckerStatus(**self.availability_status_dataset) ) self.assertEqual(expected, actual) @unittest.mock.patch.object(requests.Session, "post") def test_push_with_whois_no_json_response(self, request_mock) -> None: """ Tests the method which let us push some dataset into the platform. """ response_dict = self.response_dataset response_dict["subject"] = "example.net" self.availability_status_dataset["expiration_date"] = "23-nov-2090" def mocking(*args, **kwargs): # pylint: disable=unused-argument response_content = "I'm a teapot." response = requests.models.Response() response.url = "https://example.org/v1/status/availability" response.status_code = 418 # pylint: disable=protected-access response._content = str.encode(response_content) response.history = [response] return response self.query_tool.url_base = "https://example.org" self.query_tool.token = secrets.token_urlsafe(6) request_mock.side_effect = mocking expected = None actual = self.query_tool.push( AvailabilityCheckerStatus(**self.availability_status_dataset) ) self.assertEqual(expected, actual) def test_push_with_whois_token_not_given(self) -> None: """ Tests the method which let us push some dataset into the platform. In this test, we test the case that no token is given. """ response_dict = self.response_dataset response_dict["subject"] = "example.net" self.availability_status_dataset["expiration_date"] = "23-nov-2090" if "PYFUNCEBLE_COLLECTION_API_TOKEN" in os.environ: del os.environ["PYFUNCEBLE_COLLECTION_API_TOKEN"] if "PYFUNCEBLE_PLATFORM_API_TOKEN" in os.environ: del os.environ["PYFUNCEBLE_PLATFORM_API_TOKEN"] self.query_tool.token = "" expected = None actual = self.query_tool.push( AvailabilityCheckerStatus(**self.availability_status_dataset) ) self.assertEqual(expected, actual) def test_push_subject_not_str(self) -> None: """ Tests the method which let us push some dataset into the platform. In this test, we test the case that the given subject is not a string. """ self.availability_status_dataset["subject"] = 293 self.assertRaises( TypeError, lambda: self.query_tool.push( AvailabilityCheckerStatus(**self.availability_status_dataset) ), ) def test_push_checker_status_not_correct(self) -> None: """ Tests the method which let us push some dataset into the platform. In this test, we test the case that the given checker status is not correct. """ self.availability_status_dataset["subject"] = "foo.example.org" self.assertRaises( TypeError, lambda: self.query_tool.push(self.availability_status_dataset), ) def test_push_subject_empty_str(self) -> None: """ Tests the method which let us push some dataset into the platform. In this test, we test the case that the given subject is an empty string. """ self.availability_status_dataset["subject"] = "" self.assertRaises( ValueError, lambda: self.query_tool.push( AvailabilityCheckerStatus(**self.availability_status_dataset) ), ) def test_push_checker_type_not_str(self) -> None: """ Tests the method which let us push some dataset into the platform. In this test, we test the case that the given subject is not a string. """ self.availability_status_dataset["checker_type"] = 987 self.assertRaises( TypeError, lambda: self.query_tool.push( AvailabilityCheckerStatus(**self.availability_status_dataset) ), ) def test_push_checker_type_not_supported(self) -> None: """ Tests the method which let us push some dataset into the platform. In this test, we test the case that the given subject is not a string. """ self.availability_status_dataset["checker_type"] = "GIT" self.query_tool.token = secrets.token_urlsafe(6) self.assertRaises( ValueError, lambda: self.query_tool.push( AvailabilityCheckerStatus(**self.availability_status_dataset) ), ) def test_push_token_not_given(self) -> None: """ Tests the method which let us push some dataset into the platform. In this test, we test the case that no token is given. """ if "PYFUNCEBLE_COLLECTION_API_TOKEN" in os.environ: del os.environ["PYFUNCEBLE_COLLECTION_API_TOKEN"] if "PYFUNCEBLE_PLATFORM_API_TOKEN" in os.environ: del os.environ["PYFUNCEBLE_PLATFORM_API_TOKEN"] self.query_tool.token = "" expected = None actual = self.query_tool.push( AvailabilityCheckerStatus(**self.availability_status_dataset) ) self.assertEqual(expected, actual) PyFunceble-4.2.29.dev/tests/query/whois/000077500000000000000000000000001467462152100200715ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/query/whois/__init__.py000066400000000000000000000000001467462152100221700ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/query/whois/converter/000077500000000000000000000000001467462152100221005ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/query/whois/converter/__init__.py000066400000000000000000000000001467462152100241770ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/query/whois/converter/test_base.py000066400000000000000000000115661467462152100244340ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of the base of all our WHOIS data converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.query.whois.converter.base import ConverterBase class TestConverterBase(unittest.TestCase): """ Tests the base of all our converters. """ def setUp(self) -> None: """ Setups everything needed. """ self.converter = ConverterBase() def tearDown(self) -> None: """ Destroys everything that was needed. """ del self.converter def test_set_data_to_convert_return(self) -> None: """ Tests the response from the method which let us set the data to work with. """ given = "example.org" actual = self.converter.set_data_to_convert(given) self.assertIsInstance(actual, ConverterBase) def test_set_data_to_convert_method(self) -> None: """ Tests the method which let us set the data to work with. """ given = "example.org" expected = "example.org" self.converter.set_data_to_convert(given) actual = self.converter.data_to_convert self.assertEqual(expected, actual) def test_set_data_to_convert_attribute(self) -> None: """ Tests overwritting of the :code:`data_to_convert` attribute. """ given = "example.org" expected = "example.org" self.converter.data_to_convert = given actual = self.converter.data_to_convert self.assertEqual(expected, actual) def test_set_data_to_convert_through_init(self) -> None: """ Tests the overwritting of the data to work through the class constructor. """ given = "example.org" expected = "example.org" converter = ConverterBase(given) actual = converter.data_to_convert self.assertEqual(expected, actual) def test_get_converted_data_not_given(self) -> None: """ Tests the method which let us get the converted data for the case that no data to convert was given. """ # pylint: disable=unnecessary-lambda self.assertRaises(TypeError, lambda: self.converter.get_converted()) def test_get_converted_data(self) -> None: """ Tests the method which let us get the converted data. """ self.converter.data_to_convert = "example.org" # pylint: disable=unnecessary-lambda self.assertRaises(NotImplementedError, lambda: self.converter.get_converted()) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/query/whois/converter/test_digit2digits.py000066400000000000000000000076241467462152100261100ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our digit 2 digits converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 unittest from PyFunceble.query.whois.converter.digit2digits import Digit2Digits class TestDigit2Digits(unittest.TestCase): """ Tests the digit2digits converter. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = Digit2Digits() def tearDown(self) -> None: """ Destroys everything needed for the tests. """ del self.converter def test_set_data_to_convert_not_str(self) -> None: """ Tests the method which let us set the data to work with for the case that it's not a string. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_data_to_convert(given)) def test_get_converted_already_formatted(self) -> None: """ Tests the method which let us get the converted data for the case that the given data is already converted. """ expected = "21" actual = self.converter.set_data_to_convert("21").get_converted() self.assertEqual(expected, actual) def test_get_converted_more_than_two_digits(self) -> None: """ Tests the method which let us get the converted data for the case that the given data has more that 2 digits. """ expected = "211" actual = self.converter.set_data_to_convert("211").get_converted() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/query/whois/converter/test_expiration_date.py000066400000000000000000000155571467462152100267050ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our expiration date extractor. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 unittest from typing import List from PyFunceble.query.whois.converter.expiration_date import ExpirationDateExtractor class TestExpirationDateExtractor(unittest.TestCase): """ Tests our interface for the extraction of expiration date. """ DATE_SAMPLES: List[str] = [ "02-jan-2017", "02.01.2017", "02/01/2017", "2017-01-02", "2017.01.02", "2017/01/02", "2017.01.02 15:00:00", "20170102 15:00:00", "2017-01-02 15:00:00", "02.01.2017 15:00:00", "02-Jan-2017 15:00:00 UTC", "2017/01/02 01:00:00 (+0900)", "2017/01/02 01:00:00", "Mon Jan 02 15:00:00 GMT 2017", "Mon Jan 02 2017", "2017-01-02T15:00:00", "2017-01-02T15:00:00Z", "2017-01-02T15:00:00+0200", "2017-01-02T15:00:00+0200.622265+03:00", "2017-01-02T15:00:00+0200.622265", "2017-01-02T23:59:59.0Z", "02-01-2017", "2017. 01. 02.", "2017-01-02T00:00:00+13:00", "20170102", "02-Jan-2017", "02.1.2017", "02 Jan 2017", "02-January-2017", "2017-Jan-02.", "Mon Jan 02 15:00:00 2017", "January 02 2017-Jan-02", "2.1.2017", "20170102000000", "January 2 2017", "2nd January 2017", ] EXPIRATION_DATE_MARKERS: List[str] = [ "expire: ", "expire on: ", "Expiry Date: ", "free-date ", "expires: ", "Expiration date: ", "Expiry date: ", "Expire Date: ", "renewal date: ", "Expires: ", "validity: ", "Expiration Date : ", "Expiry : ", "expires at: ", "domain_datebilleduntil: ", "Data de expiraรงรฃo / Expiration Date (dd/mm/yyyy): ", "Fecha de expiraciรณn (Expiration date): ", "[Expires on] ", "status: OK-UNTIL ", "renewal: ", "expires............: ", "expire-date: ", "Exp date: ", "Valid-date ", "Expires On: ", "Fecha de vencimiento: ", "Expiration:......... ", "Fecha de Vencimiento: ", "Registry Expiry Date: ", "Expires on..............: ", "Expiration Time: ", "Expiration Date: ", "Expired: ", "Date d'expiration: ", "expiration date: ", ] def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = ExpirationDateExtractor() def tearDown(self) -> None: """ Destroys everything needed for the tests. """ del self.converter def test_set_data_to_convert_not_str(self) -> None: """ Tests the method which let us set the data to work with for the case that it's not a string. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_data_to_convert(given)) def test_set_data_to_convert_empty_str(self) -> None: """ Tests the method which let us set the data to work with for the case that it's an empty string. """ given = "" self.assertRaises(ValueError, lambda: self.converter.set_data_to_convert(given)) def test_get_converted(self) -> None: """ Tests the method which let us get the converted data. """ expected = "02-jan-2017" for marker in self.EXPIRATION_DATE_MARKERS: for date_sample in self.DATE_SAMPLES: test_line = f"{marker} {date_sample}" self.converter.data_to_convert = test_line actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_no_pattern(self) -> None: """ Tests the method which let us get the converted data. """ given = "Hello, World!" expected = None self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_pattern_no_date(self) -> None: """ Tests the method which let us get the converted data. """ given = f"{self.EXPIRATION_DATE_MARKERS[0]} 02 Hello :-)" expected = None self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/query/whois/converter/test_month2unified.py000066400000000000000000000220051467462152100262630ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our month converter. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 unittest from PyFunceble.query.whois.converter.month2unified import Month2Unified class TestMonth2Unified(unittest.TestCase): """ Tests our month converter. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = Month2Unified() def tearDown(self) -> None: """ Destroys everything needed for the tests. """ del self.converter def test_set_data_to_convert_not_str(self) -> None: """ Tests the method which let us set the data to work with for the case that it's not a string. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_data_to_convert(given)) def test_get_converted_no_month(self): """ Tests the method which let us get the converted month for the case that no actual month is given. """ given = "Hello, World!" expected = "Hello, World!" actual = self.converter.set_data_to_convert(given).get_converted() self.assertEqual(expected, actual) def test_get_converted_january(self): """ Tests the method which let us get the converted month for the case that we give a representation of the January month. """ given = ["jan", "Jan", "January", "01", "1", "Jan.", "jan."] expected = "jan" for data in given: actual = self.converter.set_data_to_convert(data).get_converted() self.assertEqual(expected, actual) def test_get_converted_february(self): """ Tests the method which let us get the converted month for the case that we give a representation of the February month. """ given = ["feb", "Feb", "February", "02", "2", "Feb.", "feb."] expected = "feb" for data in given: actual = self.converter.set_data_to_convert(data).get_converted() self.assertEqual(expected, actual, data) def test_get_converted_march(self): """ Tests the method which let us get the converted month for the case that we give a representation of the March month. """ given = ["mar", "Mar", "March", "03", "3", "Mar.", "mar."] expected = "mar" for data in given: actual = self.converter.set_data_to_convert(data).get_converted() self.assertEqual(expected, actual, data) def test_get_converted_april(self): """ Tests the method which let us get the converted month for the case that we give a representation of the April month. """ given = ["apr", "Apr", "April", "04", "4", "Apr.", "apr."] expected = "apr" for data in given: actual = self.converter.set_data_to_convert(data).get_converted() self.assertEqual(expected, actual, data) def test_get_converted_may(self): """ Tests the method which let us get the converted month for the case that we give a representation of the May month. """ given = ["may", "May", "05", "5"] expected = "may" for data in given: actual = self.converter.set_data_to_convert(data).get_converted() self.assertEqual(expected, actual, data) def test_get_converted_june(self): """ Tests the method which let us get the converted month for the case that we give a representation of the June month. """ given = ["jun", "Jun", "June", "06", "6", "Jun.", "jun."] expected = "jun" for data in given: actual = self.converter.set_data_to_convert(data).get_converted() self.assertEqual(expected, actual, data) def test_get_converted_july(self): """ Tests the method which let us get the converted month for the case that we give a representation of the July month. """ given = ["jul", "Jul", "July", "07", "7", "Jul.", "jul."] expected = "jul" for data in given: actual = self.converter.set_data_to_convert(data).get_converted() self.assertEqual(expected, actual, data) def test_get_converted_august(self): """ Tests the method which let us get the converted month for the case that we give a representation of the August month. """ given = ["aug", "Aug", "August", "08", "8", "Aug.", "aug."] expected = "aug" for data in given: actual = self.converter.set_data_to_convert(data).get_converted() self.assertEqual(expected, actual, data) def test_get_converted_september(self): """ Tests the method which let us get the converted month for the case that we give a representation of the September month. """ given = [ "sep", "Sep", "sept", "Sept", "September", "09", "9", "Sept.", "sept.", "Sep.", "sep.", ] expected = "sep" for data in given: actual = self.converter.set_data_to_convert(data).get_converted() self.assertEqual(expected, actual, data) def test_get_converted_october(self): """ Tests the method which let us get the converted month for the case that we give a representation of the October month. """ given = ["oct", "Oct", "October", "10", "Oct.", "oct."] expected = "oct" for data in given: actual = self.converter.set_data_to_convert(data).get_converted() self.assertEqual(expected, actual, data) def test_get_converted_november(self): """ Tests the method which let us get the converted month for the case that we give a representation of the November month. """ given = ["nov", "Nov", "November", "11", "Nov.", "nov."] expected = "nov" for data in given: actual = self.converter.set_data_to_convert(data).get_converted() self.assertEqual(expected, actual, data) def test_get_converted_december(self): """ Tests the method which let us get the converted month for the case that we give a representation of the December month. """ given = ["dec", "Dec", "December", "12", "Dec.", "dec."] expected = "dec" for data in given: actual = self.converter.set_data_to_convert(data).get_converted() self.assertEqual(expected, actual, data) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/query/whois/converter/test_registrar.py000066400000000000000000000124231467462152100255150ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our registrar extractor. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 unittest from typing import List from PyFunceble.query.whois.converter.registrar import RegistarExtractor class TestRegistrarExtractor(unittest.TestCase): """ Tests the interface for the extration of expiration date. """ REGISTRAR_SAMPLES: List[str] = [ "Hello, Inc.", "Alphabet, Inc.", "Example, Inc.", "Google, Inc.", ] REGISTRAR_MARKERS: List[str] = [ "Authorized Agency :", "Domain Support:", "Registrar:", "Registrar :", "Registrar...........:", "Registration Service Provider :", "Sponsoring Registrar :", "Sponsoring Registrar Organization :", ] def setUp(self) -> None: """ Setups everything needed for the tests. """ self.converter = RegistarExtractor() def tearDown(self) -> None: """ Destroys everything needed for the tests. """ del self.converter def test_set_data_to_convert_not_str(self) -> None: """ Tests the method which let us set the data to work with for the case that it's not a string. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.converter.set_data_to_convert(given)) def test_set_data_to_convert_empty_str(self) -> None: """ Tests the method which let us set the data to work with for the case that it's an empty string. """ given = "" self.assertRaises(ValueError, lambda: self.converter.set_data_to_convert(given)) def test_get_converted(self) -> None: """ Tests the method that let us get the registrar part. """ for marker in self.REGISTRAR_MARKERS: for sample in self.REGISTRAR_SAMPLES: expected = sample test_line = f"{marker} {sample}" self.converter.data_to_convert = test_line actual = self.converter.get_converted() self.assertEqual(expected, actual, test_line) def test_get_converted_no_pattern(self) -> None: """ Tests the method that let us get the registrar part. """ given = "Hello, World!" expected = None self.converter.data_to_convert = given actual = self.converter.get_converted() self.assertEqual(expected, actual) def test_get_converted_empty_registrar(self) -> None: """ Tests the method that let us get the registrar part for the case that the registrar is empty. """ expected = None for marker in self.REGISTRAR_MARKERS: test_line = f"{marker} " self.converter.data_to_convert = test_line actual = self.converter.get_converted() self.assertEqual(expected, actual, test_line) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/query/whois/test_query_tool.py000066400000000000000000000227471467462152100237200ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests our WHOIS query tool. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2021, 2021 Nissar Chababy 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 https://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 unittest import unittest.mock from PyFunceble.query.record.whois import WhoisQueryToolRecord from PyFunceble.query.whois.query_tool import WhoisQueryTool class TestWhoisQueryTool(unittest.TestCase): """ Tests of our WHOIS record query tool. """ def setUp(self) -> None: """ Setups everything needed for the tests. """ self.query_tool = WhoisQueryTool() def tearDown(self) -> None: """ Destroys everything needed for the tests. """ del self.query_tool def test_set_subject_return(self) -> None: """ Tests the response from the method which let us set the subject to work with. """ given = "example.org" actual = self.query_tool.set_subject(given) self.assertIsInstance(actual, WhoisQueryTool) def test_set_subject_method(self) -> None: """ Tests the method which let us set the subject to work with. """ given = "example.org" expected = "example.org" self.query_tool.set_subject(given) actual = self.query_tool.subject self.assertEqual(expected, actual) def test_set_subject_not_str(self) -> None: """ Tests the method which let us set the subject to work with; For the case that the given subject is not a :py:class:`str`. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.query_tool.set_subject(given)) def test_set_subject_empty_str(self) -> None: """ Tests the method which let us set the subject to work with; For the case that the given subject is an empty :py:class:`str`. """ given = "" self.assertRaises(ValueError, lambda: self.query_tool.set_subject(given)) def test_set_subject_attribute(self) -> None: """ Tests overwritting of the :code:`subject` attribute. """ given = "example.org" expected = "example.org" self.query_tool.subject = given actual = self.query_tool.subject self.assertEqual(expected, actual) def test_set_subject_through_init(self) -> None: """ Tests the overwritting of the subject to work through the class constructor. """ given = "example.org" expected = "example.org" query_tool = WhoisQueryTool(subject=given) actual = query_tool.subject self.assertEqual(expected, actual) def test_set_server_return(self) -> None: """ Tests the response from the method which let us set the server to work with. """ given = "whois.example.org" actual = self.query_tool.set_server(given) self.assertIsInstance(actual, WhoisQueryTool) def test_set_server_method(self) -> None: """ Tests the method which let us set the server to work with. """ given = "whois.example.org" expected = "whois.example.org" self.query_tool.set_server(given) actual = self.query_tool.server self.assertEqual(expected, actual) def test_set_server_not_str(self) -> None: """ Tests the method which let us set the server to work with; For the case that the given server is not a :py:class:`str`. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.query_tool.set_server(given)) def test_set_server_empty_str(self) -> None: """ Tests the method which let us set the server to work with; For the case that the given server is an empty :py:class:`str`. """ given = "" self.assertRaises(ValueError, lambda: self.query_tool.set_server(given)) def test_set_server_attribute(self) -> None: """ Tests overwritting of the :code:`server` attribute. """ given = "whois.example.org" expected = "whois.example.org" self.query_tool.server = given actual = self.query_tool.server self.assertEqual(expected, actual) def test_set_server_through_init(self) -> None: """ Tests the overwritting of the server to work through the class constructor. """ given = "whois.example.org" expected = "whois.example.org" query_tool = WhoisQueryTool(server=given) actual = query_tool.server self.assertEqual(expected, actual) def test_set_query_timeout_return(self) -> None: """ Tests the response from the method which let us set the timeout to apply. """ given = 100 actual = self.query_tool.set_query_timeout(given) self.assertIsInstance(actual, WhoisQueryTool) def test_set_query_timeout_method(self) -> None: """ Tests the method which let us set the query timeout to apply. """ given = 1000 expected = 1000.0 self.query_tool.set_query_timeout(given) actual = self.query_tool.query_timeout self.assertEqual(expected, actual) def test_set_query_timeout_not_int_nor_float(self) -> None: """ Tests the method which let us set the query timeout to apply; For the case that the given timeout is not a :py:class:`int` nor :py:class:`float`. """ given = ["Hello", "World!"] self.assertRaises(TypeError, lambda: self.query_tool.set_query_timeout(given)) def test_set_query_timeout_empty_str(self) -> None: """ Tests the method which let us set the query timeout to apply; For the case that the given timeout is less than 1. """ given = -4 self.assertRaises(ValueError, lambda: self.query_tool.set_query_timeout(given)) def test_set_query_timeout_attribute(self) -> None: """ Tests overwritting of the :code:`query_timeout` attribute. """ given = 10000 expected = 10000.0 self.query_tool.query_timeout = given actual = self.query_tool.query_timeout self.assertEqual(expected, actual) def test_set_query_timeout_through_init(self) -> None: """ Tests the overwritting of the query timeout to use through the class constructor. """ given = 1000 expected = 1000.0 query_tool = WhoisQueryTool(query_timeout=given) actual = query_tool.query_timeout self.assertEqual(expected, actual) def test_get_lookup_record(self) -> None: """ Tests the method which let us get the lookup record. """ self.query_tool.server = "whois.example.org" self.query_tool.query_timeout = 10000.0 self.query_tool.subject = "example.org" actual = self.query_tool.get_lookup_record() self.assertIsInstance(actual, WhoisQueryToolRecord) expected = "example.org" self.assertEqual(expected, actual.subject) expected = 10000.0 self.assertEqual(expected, actual.query_timeout) expected = "whois.example.org" self.assertEqual(expected, actual.server) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/stdout_base.py000066400000000000000000000053441467462152100204670ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Provides the base to use while working with stdout. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 io import sys import unittest class StdoutBase(unittest.TestCase): """ Use when we want to catch stdout. """ def setUp(self): """ Setup stdout. """ sys.stdout = io.StringIO() def tearDown(self): sys.stdout.close() sys.stdout = sys.__stdout__ PyFunceble-4.2.29.dev/tests/utils/000077500000000000000000000000001467462152100167335ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/utils/__init__.py000066400000000000000000000000001467462152100210320ustar00rootroot00000000000000PyFunceble-4.2.29.dev/tests/utils/test_platform.py000066400000000000000000000157321467462152100222000ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our platform utility. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 platform import unittest import unittest.mock from PyFunceble.utils.platform import PlatformUtility class TestPlatformUtility(unittest.TestCase): """ Tests our platform utility. """ def setUp(self) -> None: """ Setups everything needed by the tests. """ self.system_platform_mock = unittest.mock.patch.object(platform, "system") def tearDown(self) -> None: """ Destroys everything set up previously. """ del self.system_platform_mock def test_is_cygwin(self): """ Tests the method which let us know if the current platform is the CygWin one. """ with self.system_platform_mock as platform_patch: platform_patch.return_value = "Cygwin" expected = True actual = PlatformUtility.is_cygwin() self.assertEqual(expected, actual) def test_is_cygwin_with_version(self): """ Tests the method which let us know if the current platform is the CygWin one for the case that it's given with a certain version. """ with self.system_platform_mock as platform_patch: platform_patch.return_value = "Cygwin-NT-50.0.1" expected = True actual = PlatformUtility.is_cygwin() self.assertEqual(expected, actual) def test_is_not_cygwin(self): """ Tests the method which let us know if the current platform is the CygWin one for the case it's no cygwin version. """ with self.system_platform_mock as platform_patch: platform_patch.return_value = "Windows" expected = False actual = PlatformUtility.is_cygwin() self.assertEqual(expected, actual) def test_is_windows(self): """ Tests the method which let us know if the current platform is the Windows one. """ with self.system_platform_mock as platform_patch: platform_patch.return_value = "windows" expected = True actual = PlatformUtility.is_windows() self.assertEqual(expected, actual) def test_is_not_windows(self): """ Tests the method which let us know if the current platform is the Windows one for that case that it's the linux one. """ with self.system_platform_mock as platform_patch: platform_patch.return_value = "Linux" expected = False actual = PlatformUtility.is_windows() self.assertEqual(expected, actual) def test_is_unix(self): """ Tests the method which let us know if the current platform is the Linux one. """ with self.system_platform_mock as platform_patch: platform_patch.return_value = "Linux" expected = True actual = PlatformUtility.is_unix() self.assertEqual(expected, actual) def test_is_unix_darwin(self): """ Tests the method which let us know if the current platform is the Darwin (OSX) one. """ with self.system_platform_mock as platform_patch: platform_patch.return_value = "Darwin" expected = True actual = PlatformUtility.is_unix() self.assertEqual(expected, actual) def test_is_not_unix(self): """ Tests the method which let us know if the current platform is the Linux one for that case that it's the Windows one. """ with self.system_platform_mock as platform_patch: platform_patch.return_value = "Windows" expected = False actual = PlatformUtility.is_unix() self.assertEqual(expected, actual) def test_is_mac_os(self): """ Tests the method which let us know if the current platform is the MacOS one. """ with self.system_platform_mock as platform_patch: platform_patch.return_value = "Darwin" expected = True actual = PlatformUtility.is_mac_os() self.assertEqual(expected, actual) def test_is_not_mac_os(self): """ Tests the method which let us know if the current platform is the MacOS one for that case that it's the Windows one. """ with self.system_platform_mock as platform_patch: platform_patch.return_value = "Windows" expected = False actual = PlatformUtility.is_mac_os() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tests/utils/test_version.py000066400000000000000000000507051467462152100220400ustar00rootroot00000000000000""" The tool to check the availability or syntax of domain, IP or URL. :: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ•šโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• Tests of our version utility. Author: Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom Special thanks: https://pyfunceble.github.io/special-thanks.html Contributors: https://pyfunceble.github.io/contributors.html Project link: https://github.com/funilrys/PyFunceble Project documentation: https://docs.pyfunceble.com Project homepage: https://pyfunceble.github.io/ License: :: Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024 Nissar Chababy 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 https://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 unittest from PyFunceble.utils.version import VersionUtility class TestVersionUtility(unittest.TestCase): """ Tests our version utility. """ def setUp(self) -> None: """ Setups everything needed. """ self.utility = VersionUtility() def tearDown(self) -> None: """ Destroys everything that was needed. """ del self.utility def test_set_local_version_return(self) -> None: """ Tests the response from the method which let us set the data to work with. """ given = "example.com" actual = self.utility.set_local_version(given) self.assertIsInstance(actual, VersionUtility) def test_set_local_version_method(self) -> None: """ Tests the method which let us set the data to work with. """ given = "1.0.0.dev (Hello, World)" expected = "1.0.0.dev (Hello, World)" self.utility.set_local_version(given) actual = self.utility.local_version self.assertEqual(expected, actual) def test_set_local_version_attribute(self) -> None: """ Tests overwritting of the :code:`local_version` attribute. """ given = "1.0.0.dev (Hello, World)" expected = "1.0.0.dev (Hello, World)" self.utility.local_version = given actual = self.utility.local_version self.assertEqual(expected, actual) def test_set_local_version_through_init(self) -> None: """ Tests the overwritting of the data to work through the class constructor. """ given = "1.0.0.dev (Hello, World)" expected = "1.0.0.dev (Hello, World)" utility = VersionUtility(given) actual = utility.local_version self.assertEqual(expected, actual) def test_set_local_version_not_str(self) -> None: """ Tests the method which let us set the version to work with for the case that it's not a string. """ given = ["Hello", "World"] self.assertRaises(TypeError, lambda: self.utility.set_local_version(given)) def test_get_splitted(self) -> None: """ Tests the method which let us split the version from it's code name. """ given = "1.0.0.dev (Hello, World)" expected = (["1", "0", "0"], "dev (Hello, World)") actual = self.utility.get_splitted(given) self.assertEqual(expected, actual) def test_get_splitted_alpha(self) -> None: """ Tests the method which let us split the version from it's code name for the case that we follow PEP440. """ given = "1.0.0a1.dev (Hello, World)" expected = (["1", "0", "0a1"], "dev (Hello, World)") actual = self.utility.get_splitted(given) self.assertEqual(expected, actual) def test_get_splitted_alpha_no_code_name(self) -> None: """ Tests the method which let us split the version from it's code name for the case that we follow PEP440. In this case we don't give any code name. """ given = "1.0.0a1" expected = (["1", "0", "0a1"], "") actual = self.utility.get_splitted(given) self.assertEqual(expected, actual) def test_literally_compare(self) -> None: """ Tests the method which let us literally compare 2 versions. """ given_local = "1.0.0a1.dev (Hello, World)" given_upstream = "1.0.0a1.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.literally_compare(given_upstream) self.assertEqual(expected, actual) def test_literally_compare_not_equal(self) -> None: """ Tests the method which let us literally compare 2 versions for the case that the 2 versions differs. """ given_local = "1.0.0a1.dev (Hello, World)" given_upstream = "1.0.0a2.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.literally_compare(given_upstream) self.assertEqual(expected, actual) def test_is_older_than(self) -> None: """ Tests the method which let us check if the local version is older than the given one. """ given_local = "1.0.0a1.dev (Hello, World)" given_upstream = "1.0.0a2.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_older_than(given_upstream) self.assertEqual(expected, actual) def test_is_older_than_release_candidate(self) -> None: """ Tests the method which let us check if the local version is older than the given one - which is a release candidate. """ given_local = "1.0.0a1.dev (Hello, World)" given_upstream = "1.0.0rc1.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_older_than(given_upstream) self.assertEqual(expected, actual) def test_is_older_than_huge_number(self) -> None: """ Tests the method which let us check if the local version is older than the given one. In this case we give huge numbers as local version. """ given_local = "1.0.0a40.dev (Hello, World)" given_upstream = "1.0.0a2.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_older_than(given_upstream) self.assertEqual(expected, actual) def test_is_older_almost_same(self) -> None: """ Tests the method which let us check if the local version is older than the given one. In this case we compare a10 agains a1. """ given_local = "1.0.0a1.dev (Hello, World)" given_upstream = "1.0.0a10.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_older_than(given_upstream) self.assertEqual(expected, actual) def test_is_recent_beta(self) -> None: """ Tests the method which let us check if the local version is recent than the given one. In this case we compare the beta against the alpha. """ given_local = "1.0.0b10.dev (Hello, World)" given_upstream = "1.0.0a20.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_recent(given_upstream) self.assertEqual(expected, actual) def test_is_older_beta(self) -> None: """ Tests the method which let us check if the local version is older than the given one. In this case we compare the alpha against the beta. """ given_local = "1.0.0a40.dev (Hello, World)" given_upstream = "1.0.0b2.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_older_than(given_upstream) self.assertEqual(expected, actual) def test_is_recent_alpha(self) -> None: """ Tests the method which let us check if the local version is recent than the given one. In this case we compare the beta against the alpha. """ given_local = "1.0.0a40.dev (Hello, World)" given_upstream = "1.0.0b1.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_recent(given_upstream) self.assertEqual(expected, actual) def test_is_recent_almost_same(self) -> None: """ Tests the method which let us check if the local version is older than the given one. In this case we compare a10 agains a1. """ given_local = "1.0.0a10.dev (Hello, World)" given_upstream = "1.0.0a1.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_recent(given_upstream) self.assertEqual(expected, actual) def test_is_older_alpha(self) -> None: """ Tests the method which let us check if the local version is recent than the given one. In this case we compare the alpha against the beta. """ given_local = "1.0.0a40.dev (Hello, World)" given_upstream = "1.0.0b2.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_older_than(given_upstream) self.assertEqual(expected, actual) def test_is_equal_beta(self) -> None: """ Tests the method which let us check if the local version is equal to the given one. In this case we compare the beta against the beta. """ given_local = "1.0.0b1.dev (Hello, World)" given_upstream = "1.0.0b1.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_equal_to(given_upstream) self.assertEqual(expected, actual) def test_is_equal_almost_same(self) -> None: """ Tests the method which let us check if the local version is older than the given one. In this case we compare a10 agains a1. """ given_local = "1.0.0a10.dev (Hello, World)" given_upstream = "1.0.0a1.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_equal_to(given_upstream) self.assertEqual(expected, actual) def test_is_older_alpha_non_beta(self) -> None: """ Tests the method which let us check if the local version is older than the given one. In this case we compare the alpha against a non alpha version. """ given_local = "1.0.1a1.dev (Hello, World)" given_upstream = "1.0.1.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_older_than(given_upstream) self.assertEqual(expected, actual) def test_is_older_non_beta_alpha(self) -> None: """ Tests the method which let us check if the local version is older than the given one. In this case we compare the non alpha against the alpha. """ given_local = "1.0.1.dev (Hello, World)" given_upstream = "1.0.1a1.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_older_than(given_upstream) self.assertEqual(expected, actual) def test_is_recent_alpha_non_beta(self) -> None: """ Tests the method which let us check if the local version is recent than the given one. In this case we compare the alpha against a non alpha version. """ given_local = "1.0.1a1.dev (Hello, World)" given_upstream = "1.0.1.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_recent(given_upstream) self.assertEqual(expected, actual) def test_is_recent_alpha_non_beta_4_x_to_3_x(self) -> None: """ Tests the method which let us check if the local version is recent than the given one. In this case we compare the alpha against a non alpha version. """ given_local = "4.0.0a1.dev (Hello, World)" given_upstream = "3.2.3.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_recent(given_upstream) self.assertEqual(expected, actual) def test_is_older_alpha_non_beta_4_x_to_3_x(self) -> None: """ Tests the method which let us check if the local version is older than the given one. In this case we compare the alpha against a non alpha version. """ given_local = "4.0.0a1.dev (Hello, World)" given_upstream = "3.2.2.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_older_than(given_upstream) self.assertEqual(expected, actual) def test_is_recent_non_beta_alpha(self) -> None: """ Tests the method which let us check if the local version is recent than the given one. In this case we compare the non alpha against the alpha. """ given_local = "1.0.1.dev (Hello, World)" given_upstream = "1.0.1a1.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_recent(given_upstream) self.assertEqual(expected, actual) def test_is_not_older_than(self) -> None: """ Tests the method which let us check if the local version is older than the given one for the case that the given version is actualy not older. """ given_local = "1.0.0a1.dev (Hello, World)" given_upstream = "1.0.0a0.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_older_than(given_upstream) self.assertEqual(expected, actual) def test_is_not_older_than_equal(self) -> None: """ Tests the method which let us check if the local version is older than the given one for the case that the given version is actualy not older but equal. """ given_local = "1.0.0a1.dev (Hello, World)" given_upstream = "1.0.0a1.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_older_than(given_upstream) self.assertEqual(expected, actual) def test_is_equal_to(self) -> None: """ Tests the method which let us check if the local version is equal to the given one. """ given_local = "1.0.0a1.dev (Hello, World)" given_upstream = "1.0.0a1.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_equal_to(given_upstream) self.assertEqual(expected, actual) def test_is_not_equal_to(self) -> None: """ Tests the method which let us check if the local version is equal to the given one for the case that the given version is not equal.. """ given_local = "1.0.0a1.dev (Hello, World)" given_upstream = "1.0.0a0.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_equal_to(given_upstream) self.assertEqual(expected, actual) def test_is_not_equal_to_recent(self) -> None: """ Tests the method which let us check if the local version is equal to the given one. """ given_local = "1.0.0a1.dev (Hello, World)" given_upstream = "1.0.0a2.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_equal_to(given_upstream) self.assertEqual(expected, actual) def test_is_recent(self) -> None: """ Tests the method which let us check if the local version is more recent than the given one. """ given_local = "1.0.0a2.dev (Hello, World)" given_upstream = "1.0.0a1.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_recent(given_upstream) self.assertEqual(expected, actual) def test_is_not_recent(self) -> None: """ Tests the method which let us check if the local version is more recent than the given one. """ given_local = "1.0.0a2.dev (Hello, World)" given_upstream = "1.0.0a3.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_recent(given_upstream) self.assertEqual(expected, actual) def test_is_not_recent_recent(self) -> None: """ Tests the method which let us check if the local version is more recent than the given one. """ given_local = "1.0.0a2.dev (Hello, World)" given_upstream = "1.0.0a2.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_recent(given_upstream) self.assertEqual(expected, actual) def test_is_dev(self) -> None: """ Tests the method which let us check if the given version is the dev one. """ given_local = "1.0.0a2.dev (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_dev() self.assertEqual(expected, actual) def test_is_not_dev(self) -> None: """ Tests the method which let us check if the given version is the dev one for the case that the given version is not a dev one. """ given_local = "1.0.0a2.internal (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_dev() self.assertEqual(expected, actual) def test_is_master(self) -> None: """ Tests the method which let us check if the given version is the master one. """ given_local = "1.0.0a2. (Hello, World)" expected = True self.utility.local_version = given_local actual = self.utility.is_master() self.assertEqual(expected, actual) def test_is_not_master(self) -> None: """ Tests the method which let us check if the given version is the master one for the case that the given version is not a master one. """ given_local = "1.0.0a2.dev (Hello, World)" expected = False self.utility.local_version = given_local actual = self.utility.is_master() self.assertEqual(expected, actual) if __name__ == "__main__": unittest.main() PyFunceble-4.2.29.dev/tox.ini000066400000000000000000000005061467462152100157450ustar00rootroot00000000000000[tox] recreate = True [testenv] setenv = PYFUNCEBLE_AUTO_CONFIGURATION = YES PYFUNCEBLE_CONFIG_DIR = /tmp/pyfunceble PYTHONIOENCODING = utf-8 deps = -rrequirements.txt -rrequirements.test.txt commands = coverage run -m unittest discover tests coverage xml coverage html coverage report -mPyFunceble-4.2.29.dev/tox_run.ini000066400000000000000000000041631467462152100166340ustar00rootroot00000000000000[tox] recreate = True [testenv] setenv = PYFUNCEBLE_AUTO_CONFIGURATION = YES DEBUG_PYFUNCEBLE_ON_SCREEN=yes PYFUNCEBLE_LOGGING_LVL=critical PYFUNCEBLE_CONFIG_DIR = {toxinidir}/tests_dir PYFUNCEBLE_INSTALL_HELPERS = yes PYTHONIOENCODING = utf-8 passenv = PYFUNCEBLE_* deps = -rrequirements.txt changedir = {toxinidir}/tests_dir commands = public-suffix-pyfunceble clean-pyfunceble --all PyFunceble -v PyFunceble -t 3 -ex -d github.com --dns 9.9.9.10 149.112.112.10 --dots --logging-level critical PyFunceble -t 3 -ex -s -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --logging-level critical PyFunceble -t 3 -ex --syntax -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --logging-level critical PyFunceble -t 3 -ex -f {toxinidir}/examples/lists/simple --plain --dns 9.9.9.10 149.112.112.10 --dots --logging-level critical PyFunceble -t 3 -ex -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --logging-level critical # Normally, all inactive are not tested anymore. PyFunceble -t 3 -ex --inactive-db -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --logging-level critical # And they will be retested. PyFunceble -t 3 -ex --inactive-db --filter ".info$" -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --logging-level critical # Only .info domains should be tested. PyFunceble -t 3 -ex --adblock -a -f {toxinidir}/examples/lists/adblock --dns 9.9.9.10 149.112.112.10 --dots --logging-level critical PyFunceble -t 3 -ex -f https://raw.githubusercontent.com/FadeMind/hosts.extras/master/UncheckyAds/hosts --dns 9.9.9.10 149.112.112.10 --dots --logging-level critical python {toxinidir}/examples/api_usage/basic.py python {toxinidir}/examples/api_usage/basic_syntax.py python {toxinidir}/examples/api_usage/advanced.py python {toxinidir}/examples/api_usage/loop.py python {toxinidir}/examples/api_usage/custom_configuration.py python {toxinidir}/examples/api_usage/file_generation.py python {toxinidir}/examples/api_usage/reputation.py PyFunceble-4.2.29.dev/tox_run_mariadb.ini000066400000000000000000000045131467462152100203120ustar00rootroot00000000000000[tox] recreate = True [testenv] setenv = PYFUNCEBLE_AUTO_CONFIGURATION = YES DEBUG_PYFUNCEBLE_ON_SCREEN=yes PYFUNCEBLE_LOGGING_LVL=critical PYFUNCEBLE_CONFIG_DIR = {toxinidir}/tests_dir PYFUNCEBLE_INSTALL_HELPERS = yes PYTHONIOENCODING = utf-8 passenv = PYFUNCEBLE_* deps = -rrequirements.txt changedir = {toxinidir}/tests_dir commands = public-suffix-pyfunceble clean-pyfunceble --all PyFunceble -v PyFunceble -t 3 -ex -d github.com --dns 9.9.9.10 149.112.112.10 --dots --database-type mariadb --logging-level critical PyFunceble -t 3 -ex -s -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --database-type mariadb --logging-level critical PyFunceble -t 3 -ex --syntax -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --database-type mariadb --logging-level critical PyFunceble -t 3 -ex -f {toxinidir}/examples/lists/simple --plain --dns 9.9.9.10 149.112.112.10 --dots --database-type mariadb --logging-level critical PyFunceble -t 3 -ex -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --database-type mariadb --logging-level critical # Normally, all inactive are not tested anymore. PyFunceble -t 3 -ex --inactive-db -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --database-type mariadb --logging-level critical # And they will be retested. PyFunceble -t 3 -ex --inactive-db --filter ".info$" -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --database-type mariadb --logging-level critical # Only .info domains should be tested. PyFunceble -t 3 -ex --adblock -a -f {toxinidir}/examples/lists/adblock --dns 9.9.9.10 149.112.112.10 --dots --database-type mariadb --logging-level critical PyFunceble -t 3 -ex -f https://raw.githubusercontent.com/FadeMind/hosts.extras/master/UncheckyAds/hosts --dns 9.9.9.10 149.112.112.10 --dots --database-type mariadb --logging-level critical python {toxinidir}/examples/api_usage/basic.py python {toxinidir}/examples/api_usage/basic_syntax.py python {toxinidir}/examples/api_usage/advanced.py python {toxinidir}/examples/api_usage/loop.py python {toxinidir}/examples/api_usage/custom_configuration.py python {toxinidir}/examples/api_usage/file_generation.py python {toxinidir}/examples/api_usage/reputation.pyPyFunceble-4.2.29.dev/tox_run_postgresql.ini000066400000000000000000000045671467462152100211270ustar00rootroot00000000000000[tox] recreate = True [testenv] setenv = PYFUNCEBLE_AUTO_CONFIGURATION = YES DEBUG_PYFUNCEBLE_ON_SCREEN=yes PYFUNCEBLE_LOGGING_LVL=critical PYFUNCEBLE_CONFIG_DIR = {toxinidir}/tests_dir PYFUNCEBLE_INSTALL_HELPERS = yes PYTHONIOENCODING = utf-8 passenv = PYFUNCEBLE_* deps = -rrequirements.txt psycopg2 changedir = {toxinidir}/tests_dir commands = public-suffix-pyfunceble clean-pyfunceble --all PyFunceble -v PyFunceble -t 3 -ex -d github.com --dns 9.9.9.10 149.112.112.10 --dots --database-type postgresql --logging-level critical PyFunceble -t 3 -ex -s -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --database-type postgresql --logging-level critical PyFunceble -t 3 -ex --syntax -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --database-type postgresql --logging-level critical PyFunceble -t 3 -ex -f {toxinidir}/examples/lists/simple --plain --dns 9.9.9.10 149.112.112.10 --dots --database-type postgresql --logging-level critical PyFunceble -t 3 -ex -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --database-type postgresql --logging-level critical # Normally, all inactive are not tested anymore. PyFunceble -t 3 -ex --inactive-db -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --database-type postgresql --logging-level critical # And they will be retested. PyFunceble -t 3 -ex --inactive-db --filter ".info$" -f {toxinidir}/examples/lists/simple --dns 9.9.9.10 149.112.112.10 --dots --database-type postgresql --logging-level critical # Only .info domains should be tested. PyFunceble -t 3 -ex --adblock -a -f {toxinidir}/examples/lists/adblock --dns 9.9.9.10 149.112.112.10 --dots --database-type postgresql --logging-level critical PyFunceble -t 3 -ex -f https://raw.githubusercontent.com/FadeMind/hosts.extras/master/UncheckyAds/hosts --dns 9.9.9.10 149.112.112.10 --dots --database-type postgresql --logging-level critical python {toxinidir}/examples/api_usage/basic.py python {toxinidir}/examples/api_usage/basic_syntax.py python {toxinidir}/examples/api_usage/advanced.py python {toxinidir}/examples/api_usage/loop.py python {toxinidir}/examples/api_usage/custom_configuration.py python {toxinidir}/examples/api_usage/file_generation.py python {toxinidir}/examples/api_usage/reputation.pyPyFunceble-4.2.29.dev/version.yaml000066400000000000000000000015661467462152100170120ustar00rootroot00000000000000current_version: '4.2.29.dev (Blue Duckling: Tulip)' deprecated: - 3.0.21 - 3.1.20 - 3.2.13 - 4.0.0a1 - 4.1.0b1 - 4.2.0a1 force_update: minimal_version: - 2.58.0 status: true messages: 1.0.0: - message: '๐ŸŽ‰๐ŸŒ  Happy New Year! ๐ŸŒ ๐ŸŽ‰ Best wishes to you and your beloved ones. ' type: info until_date: '2021-02-01T00:01:00+00:00' 4.0.0a1: - message: 'You are using the Alpha version of PyFunceble 4.0.0! Please take the time to communicate with us when you notice something unusual. ' type: info until: 4.0.0b1 4.0.0b1: - message: 'You are using the Beta version of PyFunceble 4.0.0! Please take the time to communicate with us when you notice something unusual. ' type: info until: 4.0.0