dukpy_timeout
=============
.. image:: https://img.shields.io/pypi/v/dukpy_timeout.svg
:target: https://pypi.org/p/dukpy_timeout
dukpy_timeout is a fork of dukpy_, adding the timeout control for evaluating script.
.. _dukpy: https://github.com/amol-/dukpy
Timeout support
---------------------
Add a new parameter for JSInterpreter's evaljs method, you can use it as follow:
.. code:: python
>>> import dukpy
>>> import traceback
>>> import time
>>>
>>> print(time.time())
1670057825.0522335
>>> i = dukpy.JSInterpreter()
>>> try:
... i.evaljs('while(1){}', timeout=3)
... except Exception:
... traceback.print_exc()
... print(time.time())
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File ".../venv/lib/python3.10/site-packages/dukpy-0.2.4-py3.10-linux-x86_64.egg/dukpy/evaljs.py", line 57, in evaljs
res = _dukpy.eval_string(self, jscode, timeout, jsvars)
_dukpy.JSRuntimeError: RangeError: execution timeout
at [anon] (duk_js_executor.c:2042) internal
at eval (eval:1) preventsyield
1670057829.0066872
>>>
**NOTE**: The unit of time is second, and if timeout = 0, it means no time limit.
CoffeeScript Compiler
---------------------
Using the coffeescript compiler is as easy as running:
.. code:: python
>>> import dukpy
>>> dukpy.coffee_compile('''
... fill = (container, liquid = "coffee") ->
... "Filling the #{container} with #{liquid}..."
... ''')
'(function() {\n var fill;\n\n fill = function*(container, liquid) {\n if (liquid == null) {\n liquid = "coffee";\n }\n return "Filling the " + container + " with " + liquid + "...";\n };\n\n}).call(this);\n'
TypeScript Transpiler
---------------------
The TypeScript compiler can be used through the
``dukpy.typescript_compile`` function:
.. code:: python
>>> import dukpy
>>> dukpy.typescript_compile('''
... class Greeter {
... constructor(public greeting: string) { }
... greet() {
... return "<h1>" + this.greeting + "</h1>";
... }
... };
...
... var greeter = new Greeter("Hello, world!");
... ''')
'var Greeter = (function () {\n function Greeter(greeting) {\n this.greeting = greeting;\n }\n Greeter.prototype.greet = function () {\n return "<h1>" + this.greeting + "</h1>";\n };\n return Greeter;\n})();\n;\nvar greeter = new Greeter("Hello, world!");\n'
Currently the compiler has built-in options and doesn't accept additional ones,
The DukPY based TypeScript compiler also provides a WebAssets (
http://webassets.readthedocs.org/en/latest/ ) filter to automatically
compile TypeScript code in your assets pipeline. You register this filter as
``typescript`` within WebAssets using:
.. code:: python
from webassets.filter import register_filter
from dukpy.webassets import TypeScript
register_filter(TypeScript)
Which makes the filter available with the ``typescript`` name.
**NOTE:** When using the TypeScript compiler for code that needs to run
in the browser, make sure to add
https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.24/system.js
dependency. As ``import`` statements are resolved using SystemJS.
EcmaScript6 BabelJS Transpiler
------------------------------
To compile ES6 code to ES5 for everyday usage you can use
``dukpy.babel_compile``:
.. code:: python
>>> import dukpy
>>> dukpy.babel_compile('''
... class Point {
... constructor(x, y) {
... this.x = x;
... this.y = y;
... }
... toString() {
... return '(' + this.x + ', ' + this.y + ')';
... }
... }
... ''')
'"use strict";\n\nvar _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); };\n\nvar _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };\n\nvar Point = (function () {\n function Point(x, y) {\n _classCallCheck(this, Point);\n\n this.x = x;\n this.y = y;\n }\n\n _prototypeProperties(Point, null, {\n toString: {\n value: function toString() {\n return "(" + this.x + ", " + this.y + ")";\n },\n writable: true,\n configurable: true\n }\n });\n\n return Point;\n})();\n'
You can pass `options`__ to the BabelJS compiler just as keywords on
the call to ``babel_compile()``.
__ http://babeljs.io/docs/usage/options/
The DukPY based BabelJS compiler also provides a WebAssets (
http://webassets.readthedocs.org/en/latest/ ) filter to automatically
compile ES6 code in your assets pipeline. You register this filter as
``babeljs`` within WebAssets using:
.. code:: python
from webassets.filter import register_filter
from dukpy.webassets import BabelJS
register_filter(BabelJS)
Which makes the filter available with the ``babeljs`` name.
Only supported filter option is currently `BABEL_MODULES_LOADER` with value
``systemjs`` or ``umd`` to specify that compiled code should use SystemJS
or UMD instead of CommonJS for modules.
**NOTE:** When using the BabelJS compiler for code that needs to run
in the browser, make sure to add
https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.26.0/polyfill.min.js
dependency.
JSX to React Transpiling
------------------------
DukPy provides a built-in compiler from JSX to React, this is available as
``dukpy.jsx_compile``:
.. code:: python
>>> import dukpy
>>> dukpy.jsx_compile('var react_hello = <h1>Hello, world!</h1>;')
u'"use strict";\n\nvar react_hello = React.createElement(\n "h1",\n null,\n "Hello, world!"\n);'
The DukPY based JSX compiler also provides a WebAssets (
http://webassets.readthedocs.org/en/latest/ ) filter to automatically
compile JSX+ES6 code in your assets pipeline. You register this filter as
``babeljsx`` within WebAssets using:
.. code:: python
from webassets.filter import register_filter
from dukpy.webassets import BabelJSX
register_filter(BabelJSX)
Which makes the filter available with the ``babeljsx`` name.
This filter supports the same options as the babel one.
Less Transpiling
----------------
DukPy provides a built-in distribution of the less compiler available
through `dukpy.less_compile`:
.. code:: python
>>> import dukpy
>>> dukpy.less_compile('.class { width: (1 + 1) }')
'.class {\n width: 2;\n}\n'
The DukPY based LESS compiler also provides a WebAssets (
http://webassets.readthedocs.org/en/latest/ ) filter to automatically
compile LESS code in your assets pipeline. You register this filter as
``lessc`` within WebAssets using:
.. code:: python
from webassets.filter import register_filter
from dukpy.webassets import CompileLess
register_filter(CompileLess)
Which makes the filter available with the ``lessc`` name.
Using the JavaScript Interpreter
--------------------------------
Using dukpy is as simple as calling the ``dukpy.evaljs`` function with
the javascript code:
.. code:: python
>>> import dukpy
>>> dukpy.evaljs("var o = {'value': 5}; o['value'] += 3; o")
{'value': 8}
The ``evaljs`` function executes the javascript and returns the
resulting value as far as it is possible to encode it in JSON.
If execution fails a ``dukpy.JSRuntimeError`` exception is raised
with the failure reason.
Passing Arguments
~~~~~~~~~~~~~~~~~
Any argument passed to ``evaljs`` is available in JavaScript inside
the ``dukpy`` object in javascript. It must be possible to encode
the arguments using JSON for them to be available in Javascript:
.. code:: python
>>> import dukpy
>>>
>>> def sum3(value):
... return dukpy.evaljs("dukpy['value'] + 3", value=value)
...
>>> sum3(7)
10
Running Multiple Scripts
~~~~~~~~~~~~~~~~~~~~~~~~
The ``evaljs`` function supports providing multiple source codes to
be executed in the same context.
Multiple script can be passed in a list or tuple:
.. code:: python
>>> import dukpy
>>> dukpy.evaljs(["var o = {'value': 5}",
... "o['value'] += 3",
... "o"])
{'value': 8}
This is useful when your code requires dependencies to work,
as you can load the dependency and then your code.
This is actually how the coffeescript compiler is implemented
by DukPy itself:
.. code:: python
def coffee_compile(source):
with open(COFFEE_COMPILER, 'r') as coffeescript_js:
return evaljs((coffeescript_js.read(), 'CoffeeScript.compile(dukpy.coffeecode)'),
coffeecode=source)
Using a persistent JavaScript Interpreter
-----------------------------------------
The ``evaljs`` function creates a new interpreter on each call,
this is usually convenient and avoid errors due to dirt global variables
or unexpected execution status.
In some cases you might want to run code that has a slow bootstrap, so
it's convenient to reuse the same interpreter between two different calls
so that the bootstrap cost has already been paid during the first execution.
This can be achieved by using the ``dukpy.JSInterpreter`` object.
Creating a ``dukpy.JSInterpreter`` permits to evaluate code inside that interpreter
and multiple ``eval`` calls will share the same interpreter and global status:
.. code:: python
>>> import dukpy
>>> interpreter = dukpy.JSInterpreter()
>>> interpreter.evaljs("var o = {'value': 5}; o")
{u'value': 5}
>>> interpreter.evaljs("o.value += 1; o")
{u'value': 6}
Loading modules with require
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When using the ``dukpy.JSInterpreter`` object it is possible to use
the ``require('modulename')`` instruction to load a module inside javascript.
Modules are looked up in all directories registered with
``dukpy.JSInterpreter.loader.register_path``:
.. code:: python
>>> import dukpy
>>> jsi = dukpy.JSInterpreter()
>>> jsi.loader.register_path('./js_modules')
>>> jsi.evaljs("isEmpty = require('fbjs/lib/isEmpty'); isEmpty([1])")
False
Installing packages from npmjs.org
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When using the persistent javascript interpreter it is also possible to install packages
from *npmjs.org* through the ``dukpy.install_jspackage`` function:
.. code:: python
>>> import dukpy
>>> jsi = dukpy.JSInterpreter()
>>> dukpy.install_jspackage('promise', None, './js_modules')
Packages going to be installed: promise->7.1.1, asap->2.0.3
Fetching https://registry.npmjs.org/promise/-/promise-7.1.1.tgz..........................
Fetching https://registry.npmjs.org/asap/-/asap-2.0.3.tgz............
Installing promise in ./js_modules Done!
The same functionality is also provided by the ``dukpy-install`` shell command::
$ dukpy-install -d ./js_modules promise
Packages going to be installed: promise->7.1.1, asap->2.0.3
Fetching https://registry.npmjs.org/promise/-/promise-7.1.1.tgz..........................
Fetching https://registry.npmjs.org/asap/-/asap-2.0.3.tgz............
Installing promise in ./js_modules Done!
Please note that currently `install_jspackage` is not able to resolve conflicting
dependencies.
Raw data
{
"_id": null,
"home_page": "https://github.com/rmb122/dukpy_timeout",
"name": "dukpy-timeout",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "javascript compiler babeljs jsx coffeescript typescript timeout",
"author": "rmb122",
"author_email": "pypi@rmb122.com",
"download_url": "https://files.pythonhosted.org/packages/7c/95/8050b35de0a4e7fdaa8013453697e196e5dde28a0fa2287f76279bbf8206/dukpy_timeout-0.0.1.tar.gz",
"platform": null,
"description": "dukpy_timeout\n=============\n\n.. image:: https://img.shields.io/pypi/v/dukpy_timeout.svg\n :target: https://pypi.org/p/dukpy_timeout\n\ndukpy_timeout is a fork of dukpy_, adding the timeout control for evaluating script.\n\n.. _dukpy: https://github.com/amol-/dukpy\n\nTimeout support\n---------------------\n\nAdd a new parameter for JSInterpreter's evaljs method, you can use it as follow:\n\n.. code:: python\n\n >>> import dukpy\n >>> import traceback\n >>> import time\n >>>\n >>> print(time.time())\n 1670057825.0522335\n >>> i = dukpy.JSInterpreter()\n >>> try:\n ... i.evaljs('while(1){}', timeout=3)\n ... except Exception:\n ... traceback.print_exc()\n ... print(time.time())\n ...\n Traceback (most recent call last):\n File \"<stdin>\", line 2, in <module>\n File \".../venv/lib/python3.10/site-packages/dukpy-0.2.4-py3.10-linux-x86_64.egg/dukpy/evaljs.py\", line 57, in evaljs\n res = _dukpy.eval_string(self, jscode, timeout, jsvars)\n _dukpy.JSRuntimeError: RangeError: execution timeout\n at [anon] (duk_js_executor.c:2042) internal\n at eval (eval:1) preventsyield\n 1670057829.0066872\n >>>\n\n**NOTE**: The unit of time is second, and if timeout = 0, it means no time limit.\n\nCoffeeScript Compiler\n---------------------\n\nUsing the coffeescript compiler is as easy as running:\n\n.. code:: python\n\n >>> import dukpy\n >>> dukpy.coffee_compile('''\n ... fill = (container, liquid = \"coffee\") ->\n ... \"Filling the #{container} with #{liquid}...\"\n ... ''')\n '(function() {\\n var fill;\\n\\n fill = function*(container, liquid) {\\n if (liquid == null) {\\n liquid = \"coffee\";\\n }\\n return \"Filling the \" + container + \" with \" + liquid + \"...\";\\n };\\n\\n}).call(this);\\n'\n\nTypeScript Transpiler\n---------------------\n\nThe TypeScript compiler can be used through the\n``dukpy.typescript_compile`` function:\n\n.. code:: python\n\n >>> import dukpy\n >>> dukpy.typescript_compile('''\n ... class Greeter {\n ... constructor(public greeting: string) { }\n ... greet() {\n ... return \"<h1>\" + this.greeting + \"</h1>\";\n ... }\n ... };\n ...\n ... var greeter = new Greeter(\"Hello, world!\");\n ... ''')\n 'var Greeter = (function () {\\n function Greeter(greeting) {\\n this.greeting = greeting;\\n }\\n Greeter.prototype.greet = function () {\\n return \"<h1>\" + this.greeting + \"</h1>\";\\n };\\n return Greeter;\\n})();\\n;\\nvar greeter = new Greeter(\"Hello, world!\");\\n'\n\nCurrently the compiler has built-in options and doesn't accept additional ones,\n\nThe DukPY based TypeScript compiler also provides a WebAssets (\nhttp://webassets.readthedocs.org/en/latest/ ) filter to automatically\ncompile TypeScript code in your assets pipeline. You register this filter as\n``typescript`` within WebAssets using:\n\n.. code:: python\n\n from webassets.filter import register_filter\n from dukpy.webassets import TypeScript\n\n register_filter(TypeScript)\n\nWhich makes the filter available with the ``typescript`` name.\n\n**NOTE:** When using the TypeScript compiler for code that needs to run\nin the browser, make sure to add\nhttps://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.24/system.js\ndependency. As ``import`` statements are resolved using SystemJS.\n\nEcmaScript6 BabelJS Transpiler\n------------------------------\n\nTo compile ES6 code to ES5 for everyday usage you can use\n``dukpy.babel_compile``:\n\n.. code:: python\n\n >>> import dukpy\n >>> dukpy.babel_compile('''\n ... class Point {\n ... constructor(x, y) {\n ... this.x = x;\n ... this.y = y;\n ... }\n ... toString() {\n ... return '(' + this.x + ', ' + this.y + ')';\n ... }\n ... }\n ... ''')\n '\"use strict\";\\n\\nvar _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); };\\n\\nvar _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } };\\n\\nvar Point = (function () {\\n function Point(x, y) {\\n _classCallCheck(this, Point);\\n\\n this.x = x;\\n this.y = y;\\n }\\n\\n _prototypeProperties(Point, null, {\\n toString: {\\n value: function toString() {\\n return \"(\" + this.x + \", \" + this.y + \")\";\\n },\\n writable: true,\\n configurable: true\\n }\\n });\\n\\n return Point;\\n})();\\n'\n\nYou can pass `options`__ to the BabelJS compiler just as keywords on\nthe call to ``babel_compile()``.\n\n__ http://babeljs.io/docs/usage/options/\n\nThe DukPY based BabelJS compiler also provides a WebAssets (\nhttp://webassets.readthedocs.org/en/latest/ ) filter to automatically\ncompile ES6 code in your assets pipeline. You register this filter as\n``babeljs`` within WebAssets using:\n\n.. code:: python\n\n from webassets.filter import register_filter\n from dukpy.webassets import BabelJS\n\n register_filter(BabelJS)\n\nWhich makes the filter available with the ``babeljs`` name.\nOnly supported filter option is currently `BABEL_MODULES_LOADER` with value\n``systemjs`` or ``umd`` to specify that compiled code should use SystemJS\nor UMD instead of CommonJS for modules.\n\n**NOTE:** When using the BabelJS compiler for code that needs to run\nin the browser, make sure to add\nhttps://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.26.0/polyfill.min.js\ndependency.\n\nJSX to React Transpiling\n------------------------\n\nDukPy provides a built-in compiler from JSX to React, this is available as\n``dukpy.jsx_compile``:\n\n.. code:: python\n\n >>> import dukpy\n >>> dukpy.jsx_compile('var react_hello = <h1>Hello, world!</h1>;')\n u'\"use strict\";\\n\\nvar react_hello = React.createElement(\\n \"h1\",\\n null,\\n \"Hello, world!\"\\n);'\n\nThe DukPY based JSX compiler also provides a WebAssets (\nhttp://webassets.readthedocs.org/en/latest/ ) filter to automatically\ncompile JSX+ES6 code in your assets pipeline. You register this filter as\n``babeljsx`` within WebAssets using:\n\n.. code:: python\n\n from webassets.filter import register_filter\n from dukpy.webassets import BabelJSX\n\n register_filter(BabelJSX)\n\nWhich makes the filter available with the ``babeljsx`` name.\nThis filter supports the same options as the babel one.\n\nLess Transpiling\n----------------\n\nDukPy provides a built-in distribution of the less compiler available\nthrough `dukpy.less_compile`:\n\n.. code:: python\n\n >>> import dukpy\n >>> dukpy.less_compile('.class { width: (1 + 1) }')\n '.class {\\n width: 2;\\n}\\n'\n\n\nThe DukPY based LESS compiler also provides a WebAssets (\nhttp://webassets.readthedocs.org/en/latest/ ) filter to automatically\ncompile LESS code in your assets pipeline. You register this filter as\n``lessc`` within WebAssets using:\n\n.. code:: python\n\n from webassets.filter import register_filter\n from dukpy.webassets import CompileLess\n\n register_filter(CompileLess)\n\nWhich makes the filter available with the ``lessc`` name.\n\n\nUsing the JavaScript Interpreter\n--------------------------------\n\nUsing dukpy is as simple as calling the ``dukpy.evaljs`` function with\nthe javascript code:\n\n.. code:: python\n\n >>> import dukpy\n >>> dukpy.evaljs(\"var o = {'value': 5}; o['value'] += 3; o\")\n {'value': 8}\n\n\nThe ``evaljs`` function executes the javascript and returns the\nresulting value as far as it is possible to encode it in JSON.\n\nIf execution fails a ``dukpy.JSRuntimeError`` exception is raised\nwith the failure reason.\n\nPassing Arguments\n~~~~~~~~~~~~~~~~~\n\nAny argument passed to ``evaljs`` is available in JavaScript inside\nthe ``dukpy`` object in javascript. It must be possible to encode\nthe arguments using JSON for them to be available in Javascript:\n\n.. code:: python\n\n >>> import dukpy\n >>>\n >>> def sum3(value):\n ... return dukpy.evaljs(\"dukpy['value'] + 3\", value=value)\n ...\n >>> sum3(7)\n 10\n\nRunning Multiple Scripts\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe ``evaljs`` function supports providing multiple source codes to\nbe executed in the same context.\n\nMultiple script can be passed in a list or tuple:\n\n.. code:: python\n\n >>> import dukpy\n >>> dukpy.evaljs([\"var o = {'value': 5}\",\n ... \"o['value'] += 3\",\n ... \"o\"])\n {'value': 8}\n\nThis is useful when your code requires dependencies to work,\nas you can load the dependency and then your code.\n\nThis is actually how the coffeescript compiler is implemented\nby DukPy itself:\n\n.. code:: python\n\n def coffee_compile(source):\n with open(COFFEE_COMPILER, 'r') as coffeescript_js:\n return evaljs((coffeescript_js.read(), 'CoffeeScript.compile(dukpy.coffeecode)'),\n coffeecode=source)\n\nUsing a persistent JavaScript Interpreter\n-----------------------------------------\n\nThe ``evaljs`` function creates a new interpreter on each call,\nthis is usually convenient and avoid errors due to dirt global variables\nor unexpected execution status.\n\nIn some cases you might want to run code that has a slow bootstrap, so\nit's convenient to reuse the same interpreter between two different calls\nso that the bootstrap cost has already been paid during the first execution.\n\nThis can be achieved by using the ``dukpy.JSInterpreter`` object.\n\nCreating a ``dukpy.JSInterpreter`` permits to evaluate code inside that interpreter\nand multiple ``eval`` calls will share the same interpreter and global status:\n\n\n.. code:: python\n\n >>> import dukpy\n >>> interpreter = dukpy.JSInterpreter()\n >>> interpreter.evaljs(\"var o = {'value': 5}; o\")\n {u'value': 5}\n >>> interpreter.evaljs(\"o.value += 1; o\")\n {u'value': 6}\n\nLoading modules with require\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nWhen using the ``dukpy.JSInterpreter`` object it is possible to use\nthe ``require('modulename')`` instruction to load a module inside javascript.\n\nModules are looked up in all directories registered with\n``dukpy.JSInterpreter.loader.register_path``:\n\n.. code:: python\n\n >>> import dukpy\n >>> jsi = dukpy.JSInterpreter()\n >>> jsi.loader.register_path('./js_modules')\n >>> jsi.evaljs(\"isEmpty = require('fbjs/lib/isEmpty'); isEmpty([1])\")\n False\n\nInstalling packages from npmjs.org\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nWhen using the persistent javascript interpreter it is also possible to install packages\nfrom *npmjs.org* through the ``dukpy.install_jspackage`` function:\n\n.. code:: python\n\n >>> import dukpy\n >>> jsi = dukpy.JSInterpreter()\n >>> dukpy.install_jspackage('promise', None, './js_modules')\n Packages going to be installed: promise->7.1.1, asap->2.0.3\n Fetching https://registry.npmjs.org/promise/-/promise-7.1.1.tgz..........................\n Fetching https://registry.npmjs.org/asap/-/asap-2.0.3.tgz............\n Installing promise in ./js_modules Done!\n\nThe same functionality is also provided by the ``dukpy-install`` shell command::\n\n $ dukpy-install -d ./js_modules promise\n Packages going to be installed: promise->7.1.1, asap->2.0.3\n Fetching https://registry.npmjs.org/promise/-/promise-7.1.1.tgz..........................\n Fetching https://registry.npmjs.org/asap/-/asap-2.0.3.tgz............\n Installing promise in ./js_modules Done!\n\nPlease note that currently `install_jspackage` is not able to resolve conflicting\ndependencies.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Fork of dukpy, patched with timeout support",
"version": "0.0.1",
"split_keywords": [
"javascript",
"compiler",
"babeljs",
"jsx",
"coffeescript",
"typescript",
"timeout"
],
"urls": [
{
"comment_text": "",
"digests": {
"md5": "fee4a7aedb8cb9d70bca711ee204d0ff",
"sha256": "7ed6c76a6c85e79e3e9a5fc25c6b6bb39fad4f0991e3588fed9e1ff8ac1cfa21"
},
"downloads": -1,
"filename": "dukpy_timeout-0.0.1.tar.gz",
"has_sig": false,
"md5_digest": "fee4a7aedb8cb9d70bca711ee204d0ff",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 1982566,
"upload_time": "2022-12-03T09:39:01",
"upload_time_iso_8601": "2022-12-03T09:39:01.644525Z",
"url": "https://files.pythonhosted.org/packages/7c/95/8050b35de0a4e7fdaa8013453697e196e5dde28a0fa2287f76279bbf8206/dukpy_timeout-0.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-12-03 09:39:01",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "rmb122",
"github_project": "dukpy_timeout",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "dukpy-timeout"
}