bitccl


Namebitccl JSON
Version 0.4.3 PyPI version JSON
download
home_pagehttps://github.com/bitcart/bitccl
SummaryThe BitCCL scripting language compiler package
upload_time2024-01-10 21:08:17
maintainer
docs_urlNone
authorMrNaif2018
requires_python>=3.8
licenseMIT
keywords bitcart bitccl programminglanguage compiler
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <p align="center">
  <a href="https://bitcart.ai"><img src="https://raw.githubusercontent.com/bitcart/bitccl/master/logo.png" alt="BitCCL"></a>
</p>

---

[![CircleCI](https://circleci.com/gh/bitcart/bitccl.svg?style=svg)](https://circleci.com/gh/bitcart/bitccl)
![Codecov](https://img.shields.io/codecov/c/github/bitcart/bitccl?style=flat-square)
![PyPI](https://img.shields.io/pypi/v/bitccl?style=flat-square)
![PyPI - Downloads](https://img.shields.io/pypi/dm/bitccl?style=flat-square)

---

BitCCL is a [Bitcart](https://bitcart.ai) scripting language used for automating checkout flow and more.

It is currently in alpha stage, being separated from the [main Bitcart repository](https://github.com/bitcart/bitcart).

## Architechture

BitCCL is basically Python, but:

- Safe, with disabled import system
- Robust, with many built-in functions
- Optimized for running in Bitcart environment

Language file extension is `.bccl`.

## Running

```
pip install -r requirements.txt
./compiler example.bitccl
```

## Built-in functions

Current built-in functions list can be always seen in `functions.py` file.

Table of built-in functions:

| Signature                                 | Description                                                                                                                           | Return value                                         |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| `add_event_listener(event, func)`         | Adds event listener `func` to be called when `event` is dispatched                                                                    | None                                                 |
| `@on(event)`                              | A decorator used for registering functions to be called when `event` is dispatched. Example: `@on(ProductBought(1)) def func(): pass` | Wrapper function                                     |
| `dispatch_event(event, *args, **kwargs)`  | Dispatch `event`, optionally passing positional or named arguments to event handlers                                                  | None                                                 |
| `template(name, data={})`                 | Render template `name`, optionally passing `data` to it                                                                               | Template text on success, empty string("") otherwise |
| `send_email(to, subject, text)`           | Sends email to email address `to`, with `subject` and `text`. Uses email server configuration from `config.json`                      | True on success, False otherwise                     |
| `password(length=SECURE_PASSWORD_LENGTH)` | Generate cryptographically unique password of `length` if provided, otherwise uses safe enough length.                                | Generated password                                   |

Also a http client is available.

To send http request with it, use:

`http.method(url)`

To send HTTP method (get, post, delete, patch, etc.) to url.
You can also optionally pass additional query parameters (params argument), request body data (data argument),
files (files argument), headers (headers argument), cookies (cookie argument) and more.

Here is how the most complex request might look like:

```python
http.method(url, params={}, headers={}, cookies={}, auth=None, allow_redirects=True, cert="", verify=True, timeout=5.0)
```

All arguments except for url are optional.

After sending a request, you can retrieve response data:

If res is response got from calling `http.method(...)`, then:

`res.text` will return text data from response (for example, html)

`res.content` will return binary data from response (for example, file contents)

`res.json()` will return json data from response (for example, when accessing different web APIs)

Response status code can be got as `res.status_code`.

For convenience, you are provided with http request codes to easily check if request is successful without remembering the numbers.

For example, `http_codes.OK` is status code 200 (success).
So, to check if request has succeeded, you can check like so:

```python
res = http.get("https://example.com")
if res.status_code == http_codes.OK:
    print("Success")
```

For additional information about built-in http client, you can read it's full [documentation](https://www.python-httpx.org/quickstart)

Also, [Bitcart SDK](https://sdk.bitcart.ai) is available to use.

To access coins without xpub to get transaction, fiat rate or anything else not requiring a wallet, you can access each coin by
it's lowercase symbol, for example:

```python
print(btc.rate())
print(ltc.rate())
print(bch.rate())
print(xrg.rate())
print(bsty.rate())
```

**Note**: running coins' commands require it's daemon running if you are not using BitCCL from Bitcart deployment.

To perform operations requiring a wallet, use upper-case coin symbol, passing xpub/ypub/zpub/xprv/yprv/zprv/electrum seed in it:

```python
coin = BTC(xpub="my xpub")
print(coin.balance())
# or if using only once:
print(BTC(xpub="my xpub").balance())
```

## Built-in events

Refer to [events.md](events.md).

It is generated automatically from BitCCL code.

## Plugin system

If using BitCCL programmatically, you can extend it's execution context with plugins.

Pass a list of plugin-like objects to `run` function, like so:

```python
from bitccl import run

run("print(x)", plugins=[TestPlugin()])
```

Each plugin can be anything: class, object, module object, it must have two methods:

`startup()` method returning dictionary, which will be used to update execution context with new variables

`shutdown(context)` method which should perform a clean-up of injected variables if needed

Here's TestPlugin code from above's example:

```python
class TestPlugin:
    def startup(self):
        return {"x": 5}

    def shutdown(self, context):
        pass
```

## How does BitCCL secure the users

BitCCL uses [RestrictedPython](https://pypi.org/project/RestrictedPython/) project with some modifications.

Before executing arbitrary code, which could possibly be copied by a merchant from unknown source, we parse it into AST tree.

Then, by AST transformation, we delete dangerous operations or replace them to non-existing names (for example getattr to `_getattr_`)

The following code:

```python
x.foo = x.foo + x[0]
```

is transformed to:

```python
_write(x).foo = _getattr(x, 'foo') + _getitem(x, 0)
```

That way, our built-in functions have access to what they need, but user code is restricted.

If some dangerous operations are found at AST transforming stage, `CompilationRestrictedError` is raised with a list of errors.

That way, in many cases code won't even be executed if it is dangerous.

Afterwards, we execute the bytecode with a pretty limited `globals` object, with safer replacements for built-in functions.

3 main points making it secure:

- Imports are disabled (`import os; os.removedirs("/")` or similar won't work)
- The main one: accessing magic attributes is disallowed, like `__class__`, `__base__`, `__subclasses__` and similar
  It is not useful for user code, but opens many possible security holes
  The worst example is this:

  ```python
  print((1).__class__.__base__.__subclasses__())
  ```

  It could be used to access any class in your program, but accessing `__class__` and further is disallowed.
  It also disallowed such cases as `template.__globals__['os'].listdir('/')` and many others

- Also, by providing a limited amount of globals, unsafe ones are excluded, so you are provided only with useful, but safe tools

## Contributing

You can contribute to BitCCL language by suggesting new built-in functions and events to be added, as well as any ideas for improving it.
Open an [issue](https://github.com/bitcart/bitccl/issues/new/choose) to suggest new features

Also see our [contributing guidelines](CONTRIBUTING.md).

## Copyright and License

Copyright (C) 2020 MrNaif2018

Licensed under the [MIT license](LICENSE)



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/bitcart/bitccl",
    "name": "bitccl",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "",
    "keywords": "bitcart,bitccl,programminglanguage,compiler",
    "author": "MrNaif2018",
    "author_email": "chuff184@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/62/f7/a67c6f6e935a69e262ddea7defdf25120739bf2a0b3881de94217de67607/bitccl-0.4.3.tar.gz",
    "platform": null,
    "description": "<p align=\"center\">\n  <a href=\"https://bitcart.ai\"><img src=\"https://raw.githubusercontent.com/bitcart/bitccl/master/logo.png\" alt=\"BitCCL\"></a>\n</p>\n\n---\n\n[![CircleCI](https://circleci.com/gh/bitcart/bitccl.svg?style=svg)](https://circleci.com/gh/bitcart/bitccl)\n![Codecov](https://img.shields.io/codecov/c/github/bitcart/bitccl?style=flat-square)\n![PyPI](https://img.shields.io/pypi/v/bitccl?style=flat-square)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/bitccl?style=flat-square)\n\n---\n\nBitCCL is a [Bitcart](https://bitcart.ai) scripting language used for automating checkout flow and more.\n\nIt is currently in alpha stage, being separated from the [main Bitcart repository](https://github.com/bitcart/bitcart).\n\n## Architechture\n\nBitCCL is basically Python, but:\n\n- Safe, with disabled import system\n- Robust, with many built-in functions\n- Optimized for running in Bitcart environment\n\nLanguage file extension is `.bccl`.\n\n## Running\n\n```\npip install -r requirements.txt\n./compiler example.bitccl\n```\n\n## Built-in functions\n\nCurrent built-in functions list can be always seen in `functions.py` file.\n\nTable of built-in functions:\n\n| Signature                                 | Description                                                                                                                           | Return value                                         |\n| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |\n| `add_event_listener(event, func)`         | Adds event listener `func` to be called when `event` is dispatched                                                                    | None                                                 |\n| `@on(event)`                              | A decorator used for registering functions to be called when `event` is dispatched. Example: `@on(ProductBought(1)) def func(): pass` | Wrapper function                                     |\n| `dispatch_event(event, *args, **kwargs)`  | Dispatch `event`, optionally passing positional or named arguments to event handlers                                                  | None                                                 |\n| `template(name, data={})`                 | Render template `name`, optionally passing `data` to it                                                                               | Template text on success, empty string(\"\") otherwise |\n| `send_email(to, subject, text)`           | Sends email to email address `to`, with `subject` and `text`. Uses email server configuration from `config.json`                      | True on success, False otherwise                     |\n| `password(length=SECURE_PASSWORD_LENGTH)` | Generate cryptographically unique password of `length` if provided, otherwise uses safe enough length.                                | Generated password                                   |\n\nAlso a http client is available.\n\nTo send http request with it, use:\n\n`http.method(url)`\n\nTo send HTTP method (get, post, delete, patch, etc.) to url.\nYou can also optionally pass additional query parameters (params argument), request body data (data argument),\nfiles (files argument), headers (headers argument), cookies (cookie argument) and more.\n\nHere is how the most complex request might look like:\n\n```python\nhttp.method(url, params={}, headers={}, cookies={}, auth=None, allow_redirects=True, cert=\"\", verify=True, timeout=5.0)\n```\n\nAll arguments except for url are optional.\n\nAfter sending a request, you can retrieve response data:\n\nIf res is response got from calling `http.method(...)`, then:\n\n`res.text` will return text data from response (for example, html)\n\n`res.content` will return binary data from response (for example, file contents)\n\n`res.json()` will return json data from response (for example, when accessing different web APIs)\n\nResponse status code can be got as `res.status_code`.\n\nFor convenience, you are provided with http request codes to easily check if request is successful without remembering the numbers.\n\nFor example, `http_codes.OK` is status code 200 (success).\nSo, to check if request has succeeded, you can check like so:\n\n```python\nres = http.get(\"https://example.com\")\nif res.status_code == http_codes.OK:\n    print(\"Success\")\n```\n\nFor additional information about built-in http client, you can read it's full [documentation](https://www.python-httpx.org/quickstart)\n\nAlso, [Bitcart SDK](https://sdk.bitcart.ai) is available to use.\n\nTo access coins without xpub to get transaction, fiat rate or anything else not requiring a wallet, you can access each coin by\nit's lowercase symbol, for example:\n\n```python\nprint(btc.rate())\nprint(ltc.rate())\nprint(bch.rate())\nprint(xrg.rate())\nprint(bsty.rate())\n```\n\n**Note**: running coins' commands require it's daemon running if you are not using BitCCL from Bitcart deployment.\n\nTo perform operations requiring a wallet, use upper-case coin symbol, passing xpub/ypub/zpub/xprv/yprv/zprv/electrum seed in it:\n\n```python\ncoin = BTC(xpub=\"my xpub\")\nprint(coin.balance())\n# or if using only once:\nprint(BTC(xpub=\"my xpub\").balance())\n```\n\n## Built-in events\n\nRefer to [events.md](events.md).\n\nIt is generated automatically from BitCCL code.\n\n## Plugin system\n\nIf using BitCCL programmatically, you can extend it's execution context with plugins.\n\nPass a list of plugin-like objects to `run` function, like so:\n\n```python\nfrom bitccl import run\n\nrun(\"print(x)\", plugins=[TestPlugin()])\n```\n\nEach plugin can be anything: class, object, module object, it must have two methods:\n\n`startup()` method returning dictionary, which will be used to update execution context with new variables\n\n`shutdown(context)` method which should perform a clean-up of injected variables if needed\n\nHere's TestPlugin code from above's example:\n\n```python\nclass TestPlugin:\n    def startup(self):\n        return {\"x\": 5}\n\n    def shutdown(self, context):\n        pass\n```\n\n## How does BitCCL secure the users\n\nBitCCL uses [RestrictedPython](https://pypi.org/project/RestrictedPython/) project with some modifications.\n\nBefore executing arbitrary code, which could possibly be copied by a merchant from unknown source, we parse it into AST tree.\n\nThen, by AST transformation, we delete dangerous operations or replace them to non-existing names (for example getattr to `_getattr_`)\n\nThe following code:\n\n```python\nx.foo = x.foo + x[0]\n```\n\nis transformed to:\n\n```python\n_write(x).foo = _getattr(x, 'foo') + _getitem(x, 0)\n```\n\nThat way, our built-in functions have access to what they need, but user code is restricted.\n\nIf some dangerous operations are found at AST transforming stage, `CompilationRestrictedError` is raised with a list of errors.\n\nThat way, in many cases code won't even be executed if it is dangerous.\n\nAfterwards, we execute the bytecode with a pretty limited `globals` object, with safer replacements for built-in functions.\n\n3 main points making it secure:\n\n- Imports are disabled (`import os; os.removedirs(\"/\")` or similar won't work)\n- The main one: accessing magic attributes is disallowed, like `__class__`, `__base__`, `__subclasses__` and similar\n  It is not useful for user code, but opens many possible security holes\n  The worst example is this:\n\n  ```python\n  print((1).__class__.__base__.__subclasses__())\n  ```\n\n  It could be used to access any class in your program, but accessing `__class__` and further is disallowed.\n  It also disallowed such cases as `template.__globals__['os'].listdir('/')` and many others\n\n- Also, by providing a limited amount of globals, unsafe ones are excluded, so you are provided only with useful, but safe tools\n\n## Contributing\n\nYou can contribute to BitCCL language by suggesting new built-in functions and events to be added, as well as any ideas for improving it.\nOpen an [issue](https://github.com/bitcart/bitccl/issues/new/choose) to suggest new features\n\nAlso see our [contributing guidelines](CONTRIBUTING.md).\n\n## Copyright and License\n\nCopyright (C) 2020 MrNaif2018\n\nLicensed under the [MIT license](LICENSE)\n\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "The BitCCL scripting language compiler package",
    "version": "0.4.3",
    "project_urls": {
        "Homepage": "https://github.com/bitcart/bitccl"
    },
    "split_keywords": [
        "bitcart",
        "bitccl",
        "programminglanguage",
        "compiler"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2209131d8dc83987b4c89f4c02c8c97e360ff99e379d7d30669c5e2a49f64d84",
                "md5": "eb916a83a8e3d8909a43904b2d7d885c",
                "sha256": "8df6dbf00911c95e10d88785232a5b6f6cd798bd772c41115013fb5cc383261e"
            },
            "downloads": -1,
            "filename": "bitccl-0.4.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "eb916a83a8e3d8909a43904b2d7d885c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 13603,
            "upload_time": "2024-01-10T21:08:16",
            "upload_time_iso_8601": "2024-01-10T21:08:16.405854Z",
            "url": "https://files.pythonhosted.org/packages/22/09/131d8dc83987b4c89f4c02c8c97e360ff99e379d7d30669c5e2a49f64d84/bitccl-0.4.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "62f7a67c6f6e935a69e262ddea7defdf25120739bf2a0b3881de94217de67607",
                "md5": "01eabdd6d075c12653eff34f2d62372e",
                "sha256": "e73792f8dc1ced69be8fb9bed04d9567c755746fab6cffb028e168c4fba2326f"
            },
            "downloads": -1,
            "filename": "bitccl-0.4.3.tar.gz",
            "has_sig": false,
            "md5_digest": "01eabdd6d075c12653eff34f2d62372e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 19963,
            "upload_time": "2024-01-10T21:08:17",
            "upload_time_iso_8601": "2024-01-10T21:08:17.490788Z",
            "url": "https://files.pythonhosted.org/packages/62/f7/a67c6f6e935a69e262ddea7defdf25120739bf2a0b3881de94217de67607/bitccl-0.4.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-10 21:08:17",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "bitcart",
    "github_project": "bitccl",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "circle": true,
    "requirements": [],
    "lcname": "bitccl"
}
        
Elapsed time: 0.16923s