{ "info": { "author": "Pavel Sviderski", "author_email": "ps@stepik.org", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "# epicbox\n[![Build Status](https://travis-ci.org/StepicOrg/epicbox.svg?branch=master)](https://travis-ci.org/StepicOrg/epicbox)\n\nA Python library to run untrusted code in secure, isolated [Docker](https://www.docker.com/)\nbased sandboxes. It is used to automatically grade programming assignments\non [Stepik.org](https://stepik.org/).\n\nIt allows to spawn a process inside one-time Docker container, send data\nto stdin, and obtain its exit code and stdout/stderr output. It's very similar\nto what the [`subprocess`](https://docs.python.org/3/library/subprocess.html#module-subprocess)\nmodule does but additionally you can specify a custom environment for the process\n(a Docker [image](https://docs.docker.com/v17.09/engine/userguide/storagedriver/imagesandcontainers/))\nand limit the CPU, memory, disk, and network usage for the running process.\n\n## Usage\nRun a simple Python script in a one-time Docker container using the\n[`python:3.6.5-alpine`](https://hub.docker.com/_/python/) image:\n```python\nimport epicbox\n\nepicbox.configure(\n profiles=[\n epicbox.Profile('python', 'python:3.6.5-alpine')\n ]\n)\nfiles = [{'name': 'main.py', 'content': b'print(42)'}]\nlimits = {'cputime': 1, 'memory': 64}\nresult = epicbox.run('python', 'python3 main.py', files=files, limits=limits)\n\n```\nThe `result` value is:\n```python\n{'exit_code': 0,\n 'stdout': b'42\\n',\n 'stderr': b'',\n 'duration': 0.143358,\n 'timeout': False,\n 'oom_killed': False}\n```\n\n### Available Limit Options\n\nThe available limit options and default values:\n\n```\nDEFAULT_LIMITS = {\n # CPU time in seconds, None for unlimited\n 'cputime': 1,\n # Real time in seconds, None for unlimited\n 'realtime': 5,\n # Memory in megabytes, None for unlimited\n 'memory': 64,\n\n # limit the max processes the sandbox can have\n # -1 or None for unlimited(default)\n 'processes': -1,\n}\n```\n\n### Advanced usage\nA more advanced usage example of `epicbox` is to compile a C++ program and then\nrun it multiple times on different input data. In this example `epicbox` will\nrun containers on a dedicated [Docker Swarm](https://docs.docker.com/swarm/overview/)\ncluster instead of locally installed Docker engine:\n```python\nimport epicbox\n\nPROFILES = {\n 'gcc_compile': {\n 'docker_image': 'stepik/epicbox-gcc:6.3.0',\n 'user': 'root',\n },\n 'gcc_run': {\n 'docker_image': 'stepik/epicbox-gcc:6.3.0',\n # It's safer to run untrusted code as a non-root user (even in a container)\n 'user': 'sandbox',\n 'read_only': True,\n 'network_disabled': False,\n },\n}\nepicbox.configure(profiles=PROFILES, docker_url='tcp://1.2.3.4:2375')\n\nuntrusted_code = b\"\"\"\n// C++ program\n#include \n\nint main() {\n int a, b;\n std::cin >> a >> b;\n std::cout << a + b << std::endl;\n}\n\"\"\"\n# A working directory allows to preserve files created in a one-time container\n# and access them from another one. Internally it is a temporary Docker volume.\nwith epicbox.working_directory() as workdir:\n epicbox.run('gcc_compile', 'g++ -pipe -O2 -static -o main main.cpp',\n files=[{'name': 'main.cpp', 'content': untrusted_code}],\n workdir=workdir)\n epicbox.run('gcc_run', './main', stdin='2 2',\n limits={'cputime': 1, 'memory': 64},\n workdir=workdir)\n # {'exit_code': 0, 'stdout': b'4\\n', 'stderr': b'', 'duration': 0.095318, 'timeout': False, 'oom_killed': False}\n epicbox.run('gcc_run', './main', stdin='14 5',\n limits={'cputime': 1, 'memory': 64},\n workdir=workdir)\n # {'exit_code': 0, 'stdout': b'19\\n', 'stderr': b'', 'duration': 0.10285, 'timeout': False, 'oom_killed': False}\n```\n\n## Installation\n`epicbox` can be installed by running `pip install epicbox`. It's tested on Python 3.4+ and\nDocker 1.12+.\n\nYou can also check the [epicbox-images](https://github.com/StepicOrg/epicbox-images)\nrepository that contains Docker images used to automatically grade programming\nassignments on [Stepik.org](https://stepik.org/).\n\n## Contributing\nContributions are welcome, and they are greatly appreciated!\nMore details can be found in [CONTRIBUTING](CONTRIBUTING.rst).\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/StepicOrg/epicbox", "keywords": "docker,sandbox", "license": "MIT", "maintainer": "Pavel Sviderski", "maintainer_email": "ps@stepik.org", "name": "epicbox", "package_url": "https://pypi.org/project/epicbox/", "platform": "", "project_url": "https://pypi.org/project/epicbox/", "project_urls": { "Homepage": "https://github.com/StepicOrg/epicbox" }, "release_url": "https://pypi.org/project/epicbox/1.1.0/", "requires_dist": [ "docker (>=2)", "python-dateutil (>=2.4,<3.0)", "requests (>=2.14.2,<3.0.0)", "structlog (>=15.3)" ], "requires_python": ">=3.4,<4.0", "summary": "Run untrusted code in secure Docker based sandboxes", "version": "1.1.0" }, "last_serial": 5598891, "releases": { "0.6.2": [ { "comment_text": "", "digests": { "md5": "4a5472e84635fe4037859b16210b143d", "sha256": "f4e205c9b1a93fdf4fa65cce55f99d3c6d53adb96a5e9ff7c0493ba3bec7876b" }, "downloads": -1, "filename": "epicbox-0.6.2-py3-none-any.whl", "has_sig": false, "md5_digest": "4a5472e84635fe4037859b16210b143d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.4,<4.0", "size": 29340, "upload_time": "2018-11-04T21:59:35", "url": "https://files.pythonhosted.org/packages/92/6a/3a487527c5ffcfea8e2157a1c885b0bad9d7720ca6fd59ec640165e5b0c8/epicbox-0.6.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7d03dbc663bb615d217b2f93bf21f4a7", "sha256": "ab8a3fe7366dc45d9e445bc483885016e8ffbe956cb83aa82ee881c39380e210" }, "downloads": -1, "filename": "epicbox-0.6.2.tar.gz", "has_sig": false, "md5_digest": "7d03dbc663bb615d217b2f93bf21f4a7", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4,<4.0", "size": 11964, "upload_time": "2018-11-04T21:59:37", "url": "https://files.pythonhosted.org/packages/28/86/7bae9b7fc1bfc3eb2c8f5ce2623565f79d12013803f8d5a096e7c1cbb951/epicbox-0.6.2.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "29e3c24bf8a35dd9b8172b10ac38d41a", "sha256": "cc8c1766d4c0c5b4d0f7e63da7e7db2fa2d6a4b933eaa83f8e64a4f0949f3cfe" }, "downloads": -1, "filename": "epicbox-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "29e3c24bf8a35dd9b8172b10ac38d41a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.4,<4.0", "size": 29699, "upload_time": "2018-11-10T11:03:46", "url": "https://files.pythonhosted.org/packages/74/bd/bd3794ca16174e77a13dc81dd28cd1cad7334f6461f8b9ca9bf4f501f175/epicbox-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "13e723f4ee99d928cc6683e91815678b", "sha256": "02a5cb149de4a7beb5ff082a002f77d71be728fbd2ee610faa0e757beb67c103" }, "downloads": -1, "filename": "epicbox-1.0.0.tar.gz", "has_sig": false, "md5_digest": "13e723f4ee99d928cc6683e91815678b", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4,<4.0", "size": 12150, "upload_time": "2018-11-10T11:03:48", "url": "https://files.pythonhosted.org/packages/46/80/031f468ced4a33283075f1ebd409a5adf2fc20f1b1f517b131207cf99d13/epicbox-1.0.0.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "ff86c54677e21c1d9b93ca7577dcc253", "sha256": "2a4a7baa4543018372333d3965563dd183d736c93a6b90baeff6b59b105671ea" }, "downloads": -1, "filename": "epicbox-1.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "ff86c54677e21c1d9b93ca7577dcc253", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.4,<4.0", "size": 12462, "upload_time": "2019-07-29T10:56:30", "url": "https://files.pythonhosted.org/packages/f0/87/3269d8bd4bb090b7889a71f4a72606b0aba21cb7fa5e742fc2cff0251d61/epicbox-1.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5beed836172e6979aa892aeae306b631", "sha256": "acfee5bd361f2f6b06be05f5b13a770a76d9618f5ec537e8ae55b9d84a546e5c" }, "downloads": -1, "filename": "epicbox-1.1.0.tar.gz", "has_sig": false, "md5_digest": "5beed836172e6979aa892aeae306b631", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4,<4.0", "size": 12775, "upload_time": "2019-07-29T10:56:32", "url": "https://files.pythonhosted.org/packages/39/b9/ddcb9b5eaf39611b67b004c9dcef3053cba103ccad32acf64e688db7977b/epicbox-1.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "ff86c54677e21c1d9b93ca7577dcc253", "sha256": "2a4a7baa4543018372333d3965563dd183d736c93a6b90baeff6b59b105671ea" }, "downloads": -1, "filename": "epicbox-1.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "ff86c54677e21c1d9b93ca7577dcc253", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.4,<4.0", "size": 12462, "upload_time": "2019-07-29T10:56:30", "url": "https://files.pythonhosted.org/packages/f0/87/3269d8bd4bb090b7889a71f4a72606b0aba21cb7fa5e742fc2cff0251d61/epicbox-1.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5beed836172e6979aa892aeae306b631", "sha256": "acfee5bd361f2f6b06be05f5b13a770a76d9618f5ec537e8ae55b9d84a546e5c" }, "downloads": -1, "filename": "epicbox-1.1.0.tar.gz", "has_sig": false, "md5_digest": "5beed836172e6979aa892aeae306b631", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4,<4.0", "size": 12775, "upload_time": "2019-07-29T10:56:32", "url": "https://files.pythonhosted.org/packages/39/b9/ddcb9b5eaf39611b67b004c9dcef3053cba103ccad32acf64e688db7977b/epicbox-1.1.0.tar.gz" } ] }