pylibyaml


Namepylibyaml JSON
Version 0.1.0 PyPI version JSON
download
home_pagehttps://github.com/philsphicas/pylibyaml
SummarySpeed up PyYAML by automatically enabling LibYAML bindings.
upload_time2020-09-21 08:33:32
maintainer
docs_urlNone
authorPhil Sphicas
requires_python
license
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # pylibyaml

pylibyaml is a simple Python module that monkey patches PyYAML to
automatically enable the fast LibYAML-based parser and emitter if they
are installed.

## Installation

To install, run:

    pip install pylibyaml

There is no explicit requirement for PyYAML or LibYAML to be installed
in advance, but this package will be useless without them. Please refer
to the PyYAML installation documentation, especially the points about
installing the LibYAML bindings.

- https://pyyaml.org/wiki/PyYAMLDocumentation
- https://pyyaml.org/wiki/LibYAML

## Usage

Run `import pylibyaml` **BEFORE** `import yaml`, and enjoy!

```python
import pylibyaml
import yaml

yaml.safe_load(stream)
yaml.load(stream, Loader=yaml.SafeLoader)

yaml.safe_dump(data)
yaml.dump(data, Dumper=yaml.SafeDumper)
```

Most existing code should run without modification. Any references to
`yaml.Loader` and `yaml.Dumper` (including `Safe`, `Unsafe`, and `Full`
flavors) will automatically point to their `yaml.cyaml.CLoader` and
`yaml.cyaml.CDumper` equivalents. The convenience methods (`safe_load`,
`safe_dump`, etc.) will all use the C classes, as well as the methods
for adding resolvers, constructors, or representers. Objects that
inherit from `YAMLObject` should work as intended.

## Details

### Background

PyYAML is the canonical YAML parser and emitter library for Python. It
is not particularly fast.

LibYAML is a C library for parsing and emitting YAML. It is very fast.

By default, the setup.py script for PyYAML checks whether LibYAML is
installed and if so, builds and installs LibYAML bindings.

For the bindings to actually be used, they need to be explicitly
selected. The PyYAML documentation suggests some variations of the
following:

> When LibYAML bindings are installed, you may use fast LibYAML-based
parser and emitter as follows:

    >>> yaml.load(stream, Loader=yaml.CLoader)
    >>> yaml.dump(data, Dumper=yaml.CDumper)

> In order to use LibYAML based parser and emitter, use the classes
> CParser and CEmitter. For instance,

    from yaml import load, dump
    try:
        from yaml import CLoader as Loader, CDumper as Dumper
    except ImportError:
        from yaml import Loader, Dumper
    # ...
    data = load(stream, Loader=Loader)
    # ...
    output = dump(data, Dumper=Dumper)    

This approach is repetitive, inconvenient, and ineffectual when dealing
with third-party libraries that also use PyYAML.

### Implementation

The approach taken by `pylibyaml` is to rebind the global names of the
Loaders and Dumpers in the `yaml` module to the LibYAML versions if they
are available, before the various functions and classes are defined.

For example, compare the following.

Without pylibyaml:

    >>> import yaml
    >>> yaml.Loader
    <class 'yaml.loader.Loader'>
    >>> yaml.Dumper
    <class 'yaml.dumper.Dumper'>
    >>> help(yaml.dump)
    Help on function dump in module yaml:

    dump(data, stream=None, Dumper=<class 'yaml.dumper.Dumper'>, **kwds)
        Serialize a Python object into a YAML stream.
        If stream is None, return the produced string instead.

Using pylibyaml (with LibYAML bindings available):

    >>> import pylibyaml
    >>> import yaml
    >>> yaml.Loader
    <class 'yaml.cyaml.CLoader'>
    >>> yaml.Dumper
    <class 'yaml.cyaml.CDumper'>
    >>> help(yaml.dump)
    Help on function dump in module yaml:

    dump(data, stream=None, Dumper=<class 'yaml.cyaml.CDumper'>, **kwds)
        Serialize a Python object into a YAML stream.
        If stream is None, return the produced string instead.

Note that the top-level names now point to the cyaml versions, and that
the default function arguments have changed.

The code samples above will still run without modification, but the second
can be simplified - the logic of determining the best loader and dumper is
not longer required.

    import pylibyaml
    from yaml import load, dump
    from yaml import Loader, Dumper
    # ...
    data = load(stream, Loader=Loader)
    # ...
    output = dump(data, Dumper=Dumper)

## Caveats

### This is a rather ugly hack.

In order need to rebind the names of the default loaders and dumpers
prior to the function and class definitions in PyYAML's `__init__.py`,
we use `inspect` to get the source, edit it, and reload it with
`importlib`. This works for now (the current version of PyYAML is
5.3.1), and as far back as 3.11, but it may not always.

### LibYAML and PyYAML are not 100% interchangeable.

From the [PyYAML docs](https://pyyaml.org/wiki/PyYAMLDocumentation):

> Note that there are some subtle (but not really significant)
> differences between pure Python and
> [LibYAML](https://pyyaml.org/wiki/LibYAML) based parsers and emitters.
            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/philsphicas/pylibyaml",
    "name": "pylibyaml",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "",
    "author": "Phil Sphicas",
    "author_email": "phil.sphicas@att.com",
    "download_url": "https://files.pythonhosted.org/packages/c9/1a/3ae773a0d4cc0b787d1b7307786c666de0729df2c4159ec964e8ba45d06d/pylibyaml-0.1.0.tar.gz",
    "platform": "",
    "description": "# pylibyaml\n\npylibyaml is a simple Python module that monkey patches PyYAML to\nautomatically enable the fast LibYAML-based parser and emitter if they\nare installed.\n\n## Installation\n\nTo install, run:\n\n    pip install pylibyaml\n\nThere is no explicit requirement for PyYAML or LibYAML to be installed\nin advance, but this package will be useless without them. Please refer\nto the PyYAML installation documentation, especially the points about\ninstalling the LibYAML bindings.\n\n- https://pyyaml.org/wiki/PyYAMLDocumentation\n- https://pyyaml.org/wiki/LibYAML\n\n## Usage\n\nRun `import pylibyaml` **BEFORE** `import yaml`, and enjoy!\n\n```python\nimport pylibyaml\nimport yaml\n\nyaml.safe_load(stream)\nyaml.load(stream, Loader=yaml.SafeLoader)\n\nyaml.safe_dump(data)\nyaml.dump(data, Dumper=yaml.SafeDumper)\n```\n\nMost existing code should run without modification. Any references to\n`yaml.Loader` and `yaml.Dumper` (including `Safe`, `Unsafe`, and `Full`\nflavors) will automatically point to their `yaml.cyaml.CLoader` and\n`yaml.cyaml.CDumper` equivalents. The convenience methods (`safe_load`,\n`safe_dump`, etc.) will all use the C classes, as well as the methods\nfor adding resolvers, constructors, or representers. Objects that\ninherit from `YAMLObject` should work as intended.\n\n## Details\n\n### Background\n\nPyYAML is the canonical YAML parser and emitter library for Python. It\nis not particularly fast.\n\nLibYAML is a C library for parsing and emitting YAML. It is very fast.\n\nBy default, the setup.py script for PyYAML checks whether LibYAML is\ninstalled and if so, builds and installs LibYAML bindings.\n\nFor the bindings to actually be used, they need to be explicitly\nselected. The PyYAML documentation suggests some variations of the\nfollowing:\n\n> When LibYAML bindings are installed, you may use fast LibYAML-based\nparser and emitter as follows:\n\n    >>> yaml.load(stream, Loader=yaml.CLoader)\n    >>> yaml.dump(data, Dumper=yaml.CDumper)\n\n> In order to use LibYAML based parser and emitter, use the classes\n> CParser and CEmitter. For instance,\n\n    from yaml import load, dump\n    try:\n        from yaml import CLoader as Loader, CDumper as Dumper\n    except ImportError:\n        from yaml import Loader, Dumper\n    # ...\n    data = load(stream, Loader=Loader)\n    # ...\n    output = dump(data, Dumper=Dumper)    \n\nThis approach is repetitive, inconvenient, and ineffectual when dealing\nwith third-party libraries that also use PyYAML.\n\n### Implementation\n\nThe approach taken by `pylibyaml` is to rebind the global names of the\nLoaders and Dumpers in the `yaml` module to the LibYAML versions if they\nare available, before the various functions and classes are defined.\n\nFor example, compare the following.\n\nWithout pylibyaml:\n\n    >>> import yaml\n    >>> yaml.Loader\n    <class 'yaml.loader.Loader'>\n    >>> yaml.Dumper\n    <class 'yaml.dumper.Dumper'>\n    >>> help(yaml.dump)\n    Help on function dump in module yaml:\n\n    dump(data, stream=None, Dumper=<class 'yaml.dumper.Dumper'>, **kwds)\n        Serialize a Python object into a YAML stream.\n        If stream is None, return the produced string instead.\n\nUsing pylibyaml (with LibYAML bindings available):\n\n    >>> import pylibyaml\n    >>> import yaml\n    >>> yaml.Loader\n    <class 'yaml.cyaml.CLoader'>\n    >>> yaml.Dumper\n    <class 'yaml.cyaml.CDumper'>\n    >>> help(yaml.dump)\n    Help on function dump in module yaml:\n\n    dump(data, stream=None, Dumper=<class 'yaml.cyaml.CDumper'>, **kwds)\n        Serialize a Python object into a YAML stream.\n        If stream is None, return the produced string instead.\n\nNote that the top-level names now point to the cyaml versions, and that\nthe default function arguments have changed.\n\nThe code samples above will still run without modification, but the second\ncan be simplified - the logic of determining the best loader and dumper is\nnot longer required.\n\n    import pylibyaml\n    from yaml import load, dump\n    from yaml import Loader, Dumper\n    # ...\n    data = load(stream, Loader=Loader)\n    # ...\n    output = dump(data, Dumper=Dumper)\n\n## Caveats\n\n### This is a rather ugly hack.\n\nIn order need to rebind the names of the default loaders and dumpers\nprior to the function and class definitions in PyYAML's `__init__.py`,\nwe use `inspect` to get the source, edit it, and reload it with\n`importlib`. This works for now (the current version of PyYAML is\n5.3.1), and as far back as 3.11, but it may not always.\n\n### LibYAML and PyYAML are not 100% interchangeable.\n\nFrom the [PyYAML docs](https://pyyaml.org/wiki/PyYAMLDocumentation):\n\n> Note that there are some subtle (but not really significant)\n> differences between pure Python and\n> [LibYAML](https://pyyaml.org/wiki/LibYAML) based parsers and emitters.",
    "bugtrack_url": null,
    "license": "",
    "summary": "Speed up PyYAML by automatically enabling LibYAML bindings.",
    "version": "0.1.0",
    "project_urls": {
        "Homepage": "https://github.com/philsphicas/pylibyaml"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c91a3ae773a0d4cc0b787d1b7307786c666de0729df2c4159ec964e8ba45d06d",
                "md5": "825ea77151d7e91e3d5f2143712ece50",
                "sha256": "3b58dea061903c04689e35fab63ec149f7cf5e82f0808bd3425fb3ab3950623e"
            },
            "downloads": -1,
            "filename": "pylibyaml-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "825ea77151d7e91e3d5f2143712ece50",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 4743,
            "upload_time": "2020-09-21T08:33:32",
            "upload_time_iso_8601": "2020-09-21T08:33:32.121057Z",
            "url": "https://files.pythonhosted.org/packages/c9/1a/3ae773a0d4cc0b787d1b7307786c666de0729df2c4159ec964e8ba45d06d/pylibyaml-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2020-09-21 08:33:32",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "philsphicas",
    "github_project": "pylibyaml",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "pylibyaml"
}
        
Elapsed time: 0.09442s