geckordp


Namegeckordp JSON
Version 1.0.3 PyPI version JSON
download
home_pageNone
SummaryA client implementation of Firefox DevTools over remote debug protocol.
upload_time2024-09-03 09:22:12
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseMIT License Copyright 2023 jpramosi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords crawler debug firefox rdp remote-debug-protocol ui-testing webconsole
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
geckordp
=

This is a client implementation of Firefox DevTools over remote debug protocol in python.

It essentially exposes the raw api to interact with the debug server and has some similarities with a common webdriver. See also [Documentation](https://jpramosi.github.io/geckordp).

***What's possible with geckordp?***

Geckordp is meant to be used as a low level library to build tools on top.
With a few helpers like the WebExtension-API and a proxy server, it can be feature rich enough for:

+ web ui-testing
+ extension testing
+ browser test tools
+ webdriver
+ data scraping
+ https recording
+ network traffic analysis
+ remote controller for browser
+ ...and possibly more


## Getting Started
<!-- SEPARATOR -->

To use Geckordp, install it with:

```bash
pip install --upgrade geckordp
# python -m pip install --upgrade geckordp
# python -m pip install --upgrade geckordp[develop]
```

Alternative installation with [venv](https://docs.python.org/3/library/venv.html):
```bash
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade geckordp
```

Documentation can be generated with:
```bash
sphinx-build -a -c docs/src -b html docs/build docs
```
Package signature can be checked with:
```bash
pip download --no-deps geckordp
wget https://github.com/jpramosi.gpg -O pub.gpg
wget https://raw.githubusercontent.com/jpramosi/geckordp/master/signatures/geckordp-latest-py3-none-any.whl.asc -O latest.asc
gpg --no-default-keyring --output pub.sig --dearmor pub.gpg
gpg --no-default-keyring --keyring ./pub.sig --verify latest.asc geckordp-*.whl
```
```bash
# exemplary output:
gpg: Signature made Di 03 Sep 2024 11:19:17 CEST
gpg:                using RSA key 21F942661941E642894267539B8551A5AEA1227A
gpg:                issuer "jimmy.pramosi@protonmail.com"
gpg: Good signature from "Jimmy Pramosi (git) <jimmy.pramosi@protonmail.com>" [ultimate]
```

## Usage
<!-- SEPARATOR -->

```python
import json

from geckordp.actors.root import RootActor
from geckordp.firefox import Firefox
from geckordp.profile import ProfileManager
from geckordp.rdp_client import RDPClient

""" Uncomment to enable debug output
"""
# from geckordp.settings import GECKORDP
# GECKORDP.DEBUG = 1
# GECKORDP.DEBUG_REQUEST = 1
# GECKORDP.DEBUG_RESPONSE = 1


def main():
    # clone default profile to 'geckordp'
    pm = ProfileManager()
    profile_name = "geckordp"
    port = 6000
    pm.clone("default-release", profile_name)
    profile = pm.get_profile_by_name(profile_name)
    profile.set_required_configs()

    # start firefox with specified profile
    Firefox.start("https://example.com/", port, profile_name, ["-headless"])

    # create client and connect to firefox
    client = RDPClient()
    client.connect("localhost", port)

    # initialize root
    root = RootActor(client)

    # get a list of tabs
    tabs = root.list_tabs()
    print(json.dumps(tabs, indent=2))

    input()


if __name__ == "__main__":
    main()
```
See also [examples](https://jpramosi.github.io/geckordp/examples/modules.html) and [tests](https://github.com/jpramosi/geckordp/tree/master/tests/actors).


## Tested Platforms
<!-- SEPARATOR -->

| Tested Platform                            | Working                 | Firefox-Version         | Geckordp-Version        |
| -------------------------------------------| ------------------------| ------------------------| ------------------------|
| Windows (x64)                              | [?](https://github.com/jpramosi/geckordp/issues/new)                     |  129.0                   |  1.0.3                  |
| Ubuntu 24.04                               | yes                     |  129.0                   |  1.0.3                  |
| macOS 12                                   | [?](https://github.com/jpramosi/geckordp/issues/new)                       |  129.0                   |  1.0.3                  |

Geckordp requires minimum Python 3.10 and the latest Firefox build. Older versions of Firefox may also work as long the API changes are not too drastically. In case of doubt, clone and run tests with:
```bash
cd <your-repositories-path>
git clone https://github.com/jpramosi/geckordp
cd geckordp
python -m venv .venv
source .venv/bin/activate
python -m pip install -e $PWD
pytest tests/ &> test.log
```


## Versions
<!-- SEPARATOR -->

Geckordp is following the [semantic versioning](https://semver.org/spec/v2.0.0.html) (Major.Minor.Patch).<br>
Bug fixes not affecting the API increment the patch version, backward compatible API additions/changes increment the minor version, and backward incompatible API changes increment the major version.
Breaking changes will be additionally labeled with [breaking] in the [changelog](https://github.com/jpramosi/geckordp/blob/master/CHANGELOG.md).<br>
Older versions of Geckordp with its corresponding Firefox version can be found [here](https://github.com/jpramosi/geckordp/blob/master/VERSIONS.md). But keep in mind it may have missing actors or bug-fixes.


## Contribute
<!-- SEPARATOR -->

Every help in form of issues, questions or pull requests are very appreciated. If you would like to improve the project there are a few things to keep in mind:

For submitted code:
* formatting
* tests (optional)
* should basically reflect the geckodriver api (if possible)

Even incomplete contributions are welcome and can be finished together.<br>
For problems or improvements just open an [issue](https://github.com/jpramosi/geckordp/issues/new).

Eventually you can also contribute to the project just by asking what do you need (examples, a specific task, features or whether something is feasible) on the issue tracker. Often it will also help other users too.


## Develop
<!-- SEPARATOR -->

To get an idea what's missing, here is a rough list of some notable objectives:

* add remaining actors from geckodriver
* add documentation for *all* actors its functions (even official repository got none)

If you are willing to get your hands dirty, please follow me [here](https://github.com/jpramosi/geckordp/blob/master/dev/README.md).


## Technical Details
<!-- SEPARATOR -->

To be able to communicate with the server, a pre-configured profile is required.

Geckordp offers additional helper functions to resolve this problem with the [ProfileManager](https://jpramosi.github.io/geckordp/geckordp.profile.html#geckordp.profile.ProfileManager).

The following flags are changed on profile configuration:

    ### disable crash-recover after 'ungraceful' process termination
    ("browser.sessionstore.resume_from_crash", False)

    ### disable safe-mode after 'ungraceful' process termination
    ("browser.sessionstore.max_resumed_crashes", 0)
    ("toolkit.startup.max_resumed_crashes", -1)
    ("browser.sessionstore.restore_on_demand", False)
    ("browser.sessionstore.restore_tabs_lazily", False)

    ### set download folder (not set by firefox)
    ("browser.download.dir", str(Path.home()))

    ### enable compatibility
    ("devtools.chrome.enabled", True)

    ### don't open dialog to accept connections from client
    ("devtools.debugger.prompt-connection", False)

    ### enable remote debugging
    ("devtools.debugger.remote-enabled", True)

    ### allow tab isolation (for e.g. separate cookie-jar)
    ("privacy.userContext.enabled", True)

    ### misc
    ("devtools.cache.disabled", True)
    ("browser.aboutConfig.showWarning", False)
    ("browser.tabs.warnOnClose", False)
    ("browser.tabs.warnOnCloseOtherTabs", False)
    ("browser.shell.skipDefaultBrowserCheckOnFirstRun", True)
    ("pdfjs.firstRun", True)
    ("doh-rollout.doneFirstRun", True)
    ("browser.startup.firstrunSkipsHomepage", True)
    ("browser.tabs.warnOnOpen", False)
    ("browser.warnOnQuit", False)
    ("toolkit.telemetry.reportingpolicy.firstRun", False)
    ("trailhead.firstrun.didSeeAboutWelcome", True)

<!-- SEPARATOR -->
Once the new profile was created, Firefox can be started with it.
However, actors need to be initialized at first.

Some actors need to call additional functions to get initialized on server-side.
But this is not always necessary and depends on what is actually needed.
These required functions and its actors are initialized respectively used in this order according to the [pcap-dumps](https://github.com/jpramosi/geckordp/blob/master/dev).


| Browser initialization:

    RDPClient()                 -> .connect()
        v
    RootActor()                 -> .get_root()
        v
    DeviceActor()               -> .get_description()
        v
    ProcessActor()              -> .get_target()
        v
    WebConsoleActor()           -> .start_listeners([])
        v
    ContentProcessActor()       -> .list_workers()

| Tab initialization:

    TabActor()                  -> .get_target()*
        v
    WebConsoleActor()           -> .start_listeners([])*
        v
    ThreadActor()               -> .attach()*
        v
    WatcherActor()              -> .watch_resources(...)*
        v
    TargetConfigurationActor()


\**required if this actor will be used or events are wanted*

<!-- SEPARATOR -->
The following hierarchy [diagram](https://github.com/jpramosi/geckordp/blob/master/actor-hierarchy.pdf) shows dependencies between the actors and how to initialize individual actors: [](#diagram)

![](https://raw.githubusercontent.com/jpramosi/geckordp/master/actor-hierarchy.png)

For debugging purposes, Geckordp can be configured to print out requests and responses to better understand the structure of the json packets.
To enable it use:

```python
from geckordp.settings import GECKORDP
GECKORDP.DEBUG = 1
GECKORDP.DEBUG_REQUEST = 1
GECKORDP.DEBUG_RESPONSE = 1
# environment variables can also be used for e.g.
# GECKORDP_DEBUG_RESPONSE=1
```

<!-- SEPARATOR -->

Other noteworthy general hints, issues or experiences:

* actor initialization (plus the related functions like attach, watch or listening) on blank new tabs may get detached after visiting a new url and must be reinitiated (can be avoided if the page got a html header & body)
* received messages are just plain python dictionaries and most of the time it has consistent fields which can be directly accessed
* failed requests will return 'None'
* actors can have multiple contexts, that means different actor IDs can have the same actor model (for e.g. WebConsoleActor for process or tab)
* called functions within manually registered **async** handlers on RDPClient can not call functions which emitting 'RDPClient.send_receive()' later in its execution path (instead use non-async handlers in this case)
* on a new Firefox update it can happen that a few events doesn't get caught by the RDPClient handler or requests getting a wrong response, unfortunately a few event/response packets doesn't follow the same pattern and events must be manually specified in Geckordp which can have the implied side effects


## License
<!-- SEPARATOR -->
```
MIT License

Copyright (c) 2024 jpramosi

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
```

<!-- CLASS_INDEX -->

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "geckordp",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "crawler, debug, firefox, rdp, remote-debug-protocol, ui-testing, webconsole",
    "author": null,
    "author_email": "Jimmy Pramosi <jimmy.pramosi@protonmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/05/13/cb61ea488c7d10e6ea304ad7c5e3075110b88910b5b831bc4456701eea8a/geckordp-1.0.3.tar.gz",
    "platform": null,
    "description": "\ngeckordp\n=\n\nThis is a client implementation of Firefox DevTools over remote debug protocol in python.\n\nIt essentially exposes the raw api to interact with the debug server and has some similarities with a common webdriver. See also [Documentation](https://jpramosi.github.io/geckordp).\n\n***What's possible with geckordp?***\n\nGeckordp is meant to be used as a low level library to build tools on top.\nWith a few helpers like the WebExtension-API and a proxy server, it can be feature rich enough for:\n\n+ web ui-testing\n+ extension testing\n+ browser test tools\n+ webdriver\n+ data scraping\n+ https recording\n+ network traffic analysis\n+ remote controller for browser\n+ ...and possibly more\n\n\n## Getting Started\n<!-- SEPARATOR -->\n\nTo use Geckordp, install it with:\n\n```bash\npip install --upgrade geckordp\n# python -m pip install --upgrade geckordp\n# python -m pip install --upgrade geckordp[develop]\n```\n\nAlternative installation with [venv](https://docs.python.org/3/library/venv.html):\n```bash\npython -m venv .venv\nsource .venv/bin/activate\npython -m pip install --upgrade geckordp\n```\n\nDocumentation can be generated with:\n```bash\nsphinx-build -a -c docs/src -b html docs/build docs\n```\nPackage signature can be checked with:\n```bash\npip download --no-deps geckordp\nwget https://github.com/jpramosi.gpg -O pub.gpg\nwget https://raw.githubusercontent.com/jpramosi/geckordp/master/signatures/geckordp-latest-py3-none-any.whl.asc -O latest.asc\ngpg --no-default-keyring --output pub.sig --dearmor pub.gpg\ngpg --no-default-keyring --keyring ./pub.sig --verify latest.asc geckordp-*.whl\n```\n```bash\n# exemplary output:\ngpg: Signature made Di 03 Sep 2024 11:19:17 CEST\ngpg:                using RSA key 21F942661941E642894267539B8551A5AEA1227A\ngpg:                issuer \"jimmy.pramosi@protonmail.com\"\ngpg: Good signature from \"Jimmy Pramosi (git) <jimmy.pramosi@protonmail.com>\" [ultimate]\n```\n\n## Usage\n<!-- SEPARATOR -->\n\n```python\nimport json\n\nfrom geckordp.actors.root import RootActor\nfrom geckordp.firefox import Firefox\nfrom geckordp.profile import ProfileManager\nfrom geckordp.rdp_client import RDPClient\n\n\"\"\" Uncomment to enable debug output\n\"\"\"\n# from geckordp.settings import GECKORDP\n# GECKORDP.DEBUG = 1\n# GECKORDP.DEBUG_REQUEST = 1\n# GECKORDP.DEBUG_RESPONSE = 1\n\n\ndef main():\n    # clone default profile to 'geckordp'\n    pm = ProfileManager()\n    profile_name = \"geckordp\"\n    port = 6000\n    pm.clone(\"default-release\", profile_name)\n    profile = pm.get_profile_by_name(profile_name)\n    profile.set_required_configs()\n\n    # start firefox with specified profile\n    Firefox.start(\"https://example.com/\", port, profile_name, [\"-headless\"])\n\n    # create client and connect to firefox\n    client = RDPClient()\n    client.connect(\"localhost\", port)\n\n    # initialize root\n    root = RootActor(client)\n\n    # get a list of tabs\n    tabs = root.list_tabs()\n    print(json.dumps(tabs, indent=2))\n\n    input()\n\n\nif __name__ == \"__main__\":\n    main()\n```\nSee also [examples](https://jpramosi.github.io/geckordp/examples/modules.html) and [tests](https://github.com/jpramosi/geckordp/tree/master/tests/actors).\n\n\n## Tested Platforms\n<!-- SEPARATOR -->\n\n| Tested Platform                            | Working                 | Firefox-Version         | Geckordp-Version        |\n| -------------------------------------------| ------------------------| ------------------------| ------------------------|\n| Windows (x64)                              | [?](https://github.com/jpramosi/geckordp/issues/new)                     |  129.0                   |  1.0.3                  |\n| Ubuntu 24.04                               | yes                     |  129.0                   |  1.0.3                  |\n| macOS 12                                   | [?](https://github.com/jpramosi/geckordp/issues/new)                       |  129.0                   |  1.0.3                  |\n\nGeckordp requires minimum Python 3.10 and the latest Firefox build. Older versions of Firefox may also work as long the API changes are not too drastically. In case of doubt, clone and run tests with:\n```bash\ncd <your-repositories-path>\ngit clone https://github.com/jpramosi/geckordp\ncd geckordp\npython -m venv .venv\nsource .venv/bin/activate\npython -m pip install -e $PWD\npytest tests/ &> test.log\n```\n\n\n## Versions\n<!-- SEPARATOR -->\n\nGeckordp is following the [semantic versioning](https://semver.org/spec/v2.0.0.html) (Major.Minor.Patch).<br>\nBug fixes not affecting the API increment the patch version, backward compatible API additions/changes increment the minor version, and backward incompatible API changes increment the major version.\nBreaking changes will be additionally labeled with [breaking] in the [changelog](https://github.com/jpramosi/geckordp/blob/master/CHANGELOG.md).<br>\nOlder versions of Geckordp with its corresponding Firefox version can be found [here](https://github.com/jpramosi/geckordp/blob/master/VERSIONS.md). But keep in mind it may have missing actors or bug-fixes.\n\n\n## Contribute\n<!-- SEPARATOR -->\n\nEvery help in form of issues, questions or pull requests are very appreciated. If you would like to improve the project there are a few things to keep in mind:\n\nFor submitted code:\n* formatting\n* tests (optional)\n* should basically reflect the geckodriver api (if possible)\n\nEven incomplete contributions are welcome and can be finished together.<br>\nFor problems or improvements just open an [issue](https://github.com/jpramosi/geckordp/issues/new).\n\nEventually you can also contribute to the project just by asking what do you need (examples, a specific task, features or whether something is feasible) on the issue tracker. Often it will also help other users too.\n\n\n## Develop\n<!-- SEPARATOR -->\n\nTo get an idea what's missing, here is a rough list of some notable objectives:\n\n* add remaining actors from geckodriver\n* add documentation for *all* actors its functions (even official repository got none)\n\nIf you are willing to get your hands dirty, please follow me [here](https://github.com/jpramosi/geckordp/blob/master/dev/README.md).\n\n\n## Technical Details\n<!-- SEPARATOR -->\n\nTo be able to communicate with the server, a pre-configured profile is required.\n\nGeckordp offers additional helper functions to resolve this problem with the [ProfileManager](https://jpramosi.github.io/geckordp/geckordp.profile.html#geckordp.profile.ProfileManager).\n\nThe following flags are changed on profile configuration:\n\n    ### disable crash-recover after 'ungraceful' process termination\n    (\"browser.sessionstore.resume_from_crash\", False)\n\n    ### disable safe-mode after 'ungraceful' process termination\n    (\"browser.sessionstore.max_resumed_crashes\", 0)\n    (\"toolkit.startup.max_resumed_crashes\", -1)\n    (\"browser.sessionstore.restore_on_demand\", False)\n    (\"browser.sessionstore.restore_tabs_lazily\", False)\n\n    ### set download folder (not set by firefox)\n    (\"browser.download.dir\", str(Path.home()))\n\n    ### enable compatibility\n    (\"devtools.chrome.enabled\", True)\n\n    ### don't open dialog to accept connections from client\n    (\"devtools.debugger.prompt-connection\", False)\n\n    ### enable remote debugging\n    (\"devtools.debugger.remote-enabled\", True)\n\n    ### allow tab isolation (for e.g. separate cookie-jar)\n    (\"privacy.userContext.enabled\", True)\n\n    ### misc\n    (\"devtools.cache.disabled\", True)\n    (\"browser.aboutConfig.showWarning\", False)\n    (\"browser.tabs.warnOnClose\", False)\n    (\"browser.tabs.warnOnCloseOtherTabs\", False)\n    (\"browser.shell.skipDefaultBrowserCheckOnFirstRun\", True)\n    (\"pdfjs.firstRun\", True)\n    (\"doh-rollout.doneFirstRun\", True)\n    (\"browser.startup.firstrunSkipsHomepage\", True)\n    (\"browser.tabs.warnOnOpen\", False)\n    (\"browser.warnOnQuit\", False)\n    (\"toolkit.telemetry.reportingpolicy.firstRun\", False)\n    (\"trailhead.firstrun.didSeeAboutWelcome\", True)\n\n<!-- SEPARATOR -->\nOnce the new profile was created, Firefox can be started with it.\nHowever, actors need to be initialized at first.\n\nSome actors need to call additional functions to get initialized on server-side.\nBut this is not always necessary and depends on what is actually needed.\nThese required functions and its actors are initialized respectively used in this order according to the [pcap-dumps](https://github.com/jpramosi/geckordp/blob/master/dev).\n\n\n| Browser initialization:\n\n    RDPClient()                 -> .connect()\n        v\n    RootActor()                 -> .get_root()\n        v\n    DeviceActor()               -> .get_description()\n        v\n    ProcessActor()              -> .get_target()\n        v\n    WebConsoleActor()           -> .start_listeners([])\n        v\n    ContentProcessActor()       -> .list_workers()\n\n| Tab initialization:\n\n    TabActor()                  -> .get_target()*\n        v\n    WebConsoleActor()           -> .start_listeners([])*\n        v\n    ThreadActor()               -> .attach()*\n        v\n    WatcherActor()              -> .watch_resources(...)*\n        v\n    TargetConfigurationActor()\n\n\n\\**required if this actor will be used or events are wanted*\n\n<!-- SEPARATOR -->\nThe following hierarchy [diagram](https://github.com/jpramosi/geckordp/blob/master/actor-hierarchy.pdf) shows dependencies between the actors and how to initialize individual actors: [](#diagram)\n\n![](https://raw.githubusercontent.com/jpramosi/geckordp/master/actor-hierarchy.png)\n\nFor debugging purposes, Geckordp can be configured to print out requests and responses to better understand the structure of the json packets.\nTo enable it use:\n\n```python\nfrom geckordp.settings import GECKORDP\nGECKORDP.DEBUG = 1\nGECKORDP.DEBUG_REQUEST = 1\nGECKORDP.DEBUG_RESPONSE = 1\n# environment variables can also be used for e.g.\n# GECKORDP_DEBUG_RESPONSE=1\n```\n\n<!-- SEPARATOR -->\n\nOther noteworthy general hints, issues or experiences:\n\n* actor initialization (plus the related functions like attach, watch or listening) on blank new tabs may get detached after visiting a new url and must be reinitiated (can be avoided if the page got a html header & body)\n* received messages are just plain python dictionaries and most of the time it has consistent fields which can be directly accessed\n* failed requests will return 'None'\n* actors can have multiple contexts, that means different actor IDs can have the same actor model (for e.g. WebConsoleActor for process or tab)\n* called functions within manually registered **async** handlers on RDPClient can not call functions which emitting 'RDPClient.send_receive()' later in its execution path (instead use non-async handlers in this case)\n* on a new Firefox update it can happen that a few events doesn't get caught by the RDPClient handler or requests getting a wrong response, unfortunately a few event/response packets doesn't follow the same pattern and events must be manually specified in Geckordp which can have the implied side effects\n\n\n## License\n<!-- SEPARATOR -->\n```\nMIT License\n\nCopyright (c) 2024 jpramosi\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n\n<!-- CLASS_INDEX -->\n",
    "bugtrack_url": null,
    "license": "MIT License  Copyright 2023 jpramosi  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
    "summary": "A client implementation of Firefox DevTools over remote debug protocol.",
    "version": "1.0.3",
    "project_urls": {
        "Changelog": "https://github.com/jpramosi/geckordp/blob/master/CHANGELOG.md",
        "Documentation": "https://jpramosi.github.io/geckordp",
        "Homepage": "https://github.com/jpramosi/geckordp",
        "Issues": "https://github.com/jpramosi/geckordp/issues",
        "Repository": "https://github.com/jpramosi/geckordp.git"
    },
    "split_keywords": [
        "crawler",
        " debug",
        " firefox",
        " rdp",
        " remote-debug-protocol",
        " ui-testing",
        " webconsole"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8ad627de8788f3e7c2a28efa4d7e71198e88dee14c232655605cfdb80831a0d9",
                "md5": "04df6634672a7016136fdb3a1ec88664",
                "sha256": "dd93dc6111b339d5919a1e8390a36c88bc0f2eb6f7b546c6d5b1ade66e57c13b"
            },
            "downloads": -1,
            "filename": "geckordp-1.0.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "04df6634672a7016136fdb3a1ec88664",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 55924,
            "upload_time": "2024-09-03T09:22:10",
            "upload_time_iso_8601": "2024-09-03T09:22:10.353314Z",
            "url": "https://files.pythonhosted.org/packages/8a/d6/27de8788f3e7c2a28efa4d7e71198e88dee14c232655605cfdb80831a0d9/geckordp-1.0.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0513cb61ea488c7d10e6ea304ad7c5e3075110b88910b5b831bc4456701eea8a",
                "md5": "35f9110ea1e3af1a72bcb7be1cc2fdf9",
                "sha256": "333a15d2eb284019c6323e2436ffc850e762129fb647b19eacdb8d650064c8dc"
            },
            "downloads": -1,
            "filename": "geckordp-1.0.3.tar.gz",
            "has_sig": false,
            "md5_digest": "35f9110ea1e3af1a72bcb7be1cc2fdf9",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 188713,
            "upload_time": "2024-09-03T09:22:12",
            "upload_time_iso_8601": "2024-09-03T09:22:12.451233Z",
            "url": "https://files.pythonhosted.org/packages/05/13/cb61ea488c7d10e6ea304ad7c5e3075110b88910b5b831bc4456701eea8a/geckordp-1.0.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-09-03 09:22:12",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jpramosi",
    "github_project": "geckordp",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "geckordp"
}
        
Elapsed time: 0.43050s