| |pypi| |license| |coverage| |master_build|
| |sonar_maintainability| |sonar_reliability| |sonar_security|
Pure python module for (de)serialization to and from VDF that works just like ``json``.
Tested and works on ``py2.7``, ``py3.3+``, ``pypy`` and ``pypy3``.
VDF is Valve's KeyValue text file format
https://developer.valvesoftware.com/wiki/KeyValues
| Supported versions: ``kv1``
| Unsupported: ``kv2`` and ``kv3``
Install
-------
You can grab the latest release from https://pypi.org/project/vdf/ or via ``pip``
.. code:: bash
pip install vdf
Install the current dev version from ``github``
.. code:: bash
pip install git+https://github.com/ValvePython/vdf
Problems & solutions
--------------------
- There are known files that contain duplicate keys. This is supported the format and
makes mapping to ``dict`` impossible. For this case the module provides ``vdf.VDFDict``
that can be used as mapper instead of ``dict``. See the example section for details.
- By default de-serialization will return a ``dict``, which doesn't preserve nor guarantee
key order on Python versions prior to 3.6, due to `hash randomization`_. If key order is
important on old Pythons, I suggest using ``collections.OrderedDict``, or ``vdf.VDFDict``.
Example usage
-------------
For text representation
.. code:: python
import vdf
# parsing vdf from file or string
d = vdf.load(open('file.txt'))
d = vdf.loads(vdf_text)
d = vdf.parse(open('file.txt'))
d = vdf.parse(vdf_text)
# dumping dict as vdf to string
vdf_text = vdf.dumps(d)
indented_vdf = vdf.dumps(d, pretty=True)
# dumping dict as vdf to file
vdf.dump(d, open('file2.txt','w'), pretty=True)
For binary representation
.. code:: python
d = vdf.binary_loads(vdf_bytes)
b = vdf.binary_dumps(d)
# alternative format - VBKV
d = vdf.binary_loads(vdf_bytes, alt_format=True)
b = vdf.binary_dumps(d, alt_format=True)
# VBKV with header and CRC checking
d = vdf.vbkv_loads(vbkv_bytes)
b = vdf.vbkv_dumps(d)
Using an alternative mapper
.. code:: python
d = vdf.loads(vdf_string, mapper=collections.OrderedDict)
d = vdf.loads(vdf_string, mapper=vdf.VDFDict)
``VDFDict`` works much like the regular ``dict``, except it handles duplicates and remembers
insert order. Additionally, keys can only be of type ``str``. The most important difference
is that when trying to assigning a key that already exist it will create a duplicate instead
of reassign the value to the existing key.
.. code:: python
>>> d = vdf.VDFDict()
>>> d['key'] = 111
>>> d['key'] = 222
>>> d
VDFDict([('key', 111), ('key', 222)])
>>> d.items()
[('key', 111), ('key', 222)]
>>> d['key']
111
>>> d[(0, 'key')] # get the first duplicate
111
>>> d[(1, 'key')] # get the second duplicate
222
>>> d.get_all_for('key')
[111, 222]
>>> d[(1, 'key')] = 123 # reassign specific duplicate
>>> d.get_all_for('key')
[111, 123]
>>> d['key'] = 333
>>> d.get_all_for('key')
[111, 123, 333]
>>> del d[(1, 'key')]
>>> d.get_all_for('key')
[111, 333]
>>> d[(1, 'key')]
333
>>> print vdf.dumps(d)
"key" "111"
"key" "333"
>>> d.has_duplicates()
True
>>> d.remove_all_for('key')
>>> len(d)
0
>>> d.has_duplicates()
False
.. |pypi| image:: https://img.shields.io/pypi/v/vdf.svg?style=flat&label=latest%20version
:target: https://pypi.org/project/vdf/
:alt: Latest version released on PyPi
.. |license| image:: https://img.shields.io/pypi/l/vdf.svg?style=flat&label=license
:target: https://pypi.org/project/vdf/
:alt: MIT License
.. |coverage| image:: https://img.shields.io/coveralls/ValvePython/vdf/master.svg?style=flat
:target: https://coveralls.io/r/ValvePython/vdf?branch=master
:alt: Test coverage
.. |sonar_maintainability| image:: https://sonarcloud.io/api/project_badges/measure?project=ValvePython_vdf&metric=sqale_rating
:target: https://sonarcloud.io/dashboard?id=ValvePython_vdf
:alt: SonarCloud Rating
.. |sonar_reliability| image:: https://sonarcloud.io/api/project_badges/measure?project=ValvePython_vdf&metric=reliability_rating
:target: https://sonarcloud.io/dashboard?id=ValvePython_vdf
:alt: SonarCloud Rating
.. |sonar_security| image:: https://sonarcloud.io/api/project_badges/measure?project=ValvePython_vdf&metric=security_rating
:target: https://sonarcloud.io/dashboard?id=ValvePython_vdf
:alt: SonarCloud Rating
.. |master_build| image:: https://github.com/ValvePython/vdf/workflows/Tests/badge.svg?branch=master
:target: https://github.com/ValvePython/vdf/actions?query=workflow%3A%22Tests%22+branch%3Amaster
:alt: Build status of master branch
.. _DuplicateOrderedDict: https://github.com/rossengeorgiev/dota2_notebooks/blob/master/DuplicateOrderedDict_for_VDF.ipynb
.. _hash randomization: https://docs.python.org/2/using/cmdline.html#envvar-PYTHONHASHSEED
Raw data
{
"_id": null,
"home_page": "https://github.com/ValvePython/vdf",
"name": "vdf",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "valve keyvalue vdf tf2 dota2 csgo",
"author": "Rossen Georgiev",
"author_email": "rossen@rgp.io",
"download_url": "https://files.pythonhosted.org/packages/44/7f/74192f47d67c8bf3c47bf0d8487b3457614c2c98d58b6617721d217f3f79/vdf-3.4.tar.gz",
"platform": "",
"description": "| |pypi| |license| |coverage| |master_build|\n| |sonar_maintainability| |sonar_reliability| |sonar_security|\n\nPure python module for (de)serialization to and from VDF that works just like ``json``.\n\nTested and works on ``py2.7``, ``py3.3+``, ``pypy`` and ``pypy3``.\n\nVDF is Valve's KeyValue text file format\n\nhttps://developer.valvesoftware.com/wiki/KeyValues\n\n| Supported versions: ``kv1``\n| Unsupported: ``kv2`` and ``kv3``\n\nInstall\n-------\n\nYou can grab the latest release from https://pypi.org/project/vdf/ or via ``pip``\n\n.. code:: bash\n\n pip install vdf\n\nInstall the current dev version from ``github``\n\n.. code:: bash\n\n pip install git+https://github.com/ValvePython/vdf\n\n\nProblems & solutions\n--------------------\n\n- There are known files that contain duplicate keys. This is supported the format and\n makes mapping to ``dict`` impossible. For this case the module provides ``vdf.VDFDict``\n that can be used as mapper instead of ``dict``. See the example section for details.\n\n- By default de-serialization will return a ``dict``, which doesn't preserve nor guarantee\n key order on Python versions prior to 3.6, due to `hash randomization`_. If key order is\n important on old Pythons, I suggest using ``collections.OrderedDict``, or ``vdf.VDFDict``.\n\nExample usage\n-------------\n\nFor text representation\n\n.. code:: python\n\n import vdf\n\n # parsing vdf from file or string\n d = vdf.load(open('file.txt'))\n d = vdf.loads(vdf_text)\n d = vdf.parse(open('file.txt'))\n d = vdf.parse(vdf_text)\n\n # dumping dict as vdf to string\n vdf_text = vdf.dumps(d)\n indented_vdf = vdf.dumps(d, pretty=True)\n\n # dumping dict as vdf to file\n vdf.dump(d, open('file2.txt','w'), pretty=True)\n\n\nFor binary representation\n\n.. code:: python\n\n d = vdf.binary_loads(vdf_bytes)\n b = vdf.binary_dumps(d)\n\n # alternative format - VBKV\n\n d = vdf.binary_loads(vdf_bytes, alt_format=True)\n b = vdf.binary_dumps(d, alt_format=True)\n\n # VBKV with header and CRC checking\n\n d = vdf.vbkv_loads(vbkv_bytes)\n b = vdf.vbkv_dumps(d)\n\nUsing an alternative mapper\n\n.. code:: python\n\n d = vdf.loads(vdf_string, mapper=collections.OrderedDict)\n d = vdf.loads(vdf_string, mapper=vdf.VDFDict)\n\n``VDFDict`` works much like the regular ``dict``, except it handles duplicates and remembers\ninsert order. Additionally, keys can only be of type ``str``. The most important difference\nis that when trying to assigning a key that already exist it will create a duplicate instead\nof reassign the value to the existing key.\n\n.. code:: python\n\n >>> d = vdf.VDFDict()\n >>> d['key'] = 111\n >>> d['key'] = 222\n >>> d\n VDFDict([('key', 111), ('key', 222)])\n >>> d.items()\n [('key', 111), ('key', 222)]\n >>> d['key']\n 111\n >>> d[(0, 'key')] # get the first duplicate\n 111\n >>> d[(1, 'key')] # get the second duplicate\n 222\n >>> d.get_all_for('key')\n [111, 222]\n\n >>> d[(1, 'key')] = 123 # reassign specific duplicate\n >>> d.get_all_for('key')\n [111, 123]\n\n >>> d['key'] = 333\n >>> d.get_all_for('key')\n [111, 123, 333]\n >>> del d[(1, 'key')]\n >>> d.get_all_for('key')\n [111, 333]\n >>> d[(1, 'key')]\n 333\n\n >>> print vdf.dumps(d)\n \"key\" \"111\"\n \"key\" \"333\"\n\n >>> d.has_duplicates()\n True\n >>> d.remove_all_for('key')\n >>> len(d)\n 0\n >>> d.has_duplicates()\n False\n\n\n.. |pypi| image:: https://img.shields.io/pypi/v/vdf.svg?style=flat&label=latest%20version\n :target: https://pypi.org/project/vdf/\n :alt: Latest version released on PyPi\n\n.. |license| image:: https://img.shields.io/pypi/l/vdf.svg?style=flat&label=license\n :target: https://pypi.org/project/vdf/\n :alt: MIT License\n\n.. |coverage| image:: https://img.shields.io/coveralls/ValvePython/vdf/master.svg?style=flat\n :target: https://coveralls.io/r/ValvePython/vdf?branch=master\n :alt: Test coverage\n\n.. |sonar_maintainability| image:: https://sonarcloud.io/api/project_badges/measure?project=ValvePython_vdf&metric=sqale_rating\n :target: https://sonarcloud.io/dashboard?id=ValvePython_vdf\n :alt: SonarCloud Rating\n\n.. |sonar_reliability| image:: https://sonarcloud.io/api/project_badges/measure?project=ValvePython_vdf&metric=reliability_rating\n :target: https://sonarcloud.io/dashboard?id=ValvePython_vdf\n :alt: SonarCloud Rating\n\n.. |sonar_security| image:: https://sonarcloud.io/api/project_badges/measure?project=ValvePython_vdf&metric=security_rating\n :target: https://sonarcloud.io/dashboard?id=ValvePython_vdf\n :alt: SonarCloud Rating\n\n.. |master_build| image:: https://github.com/ValvePython/vdf/workflows/Tests/badge.svg?branch=master\n :target: https://github.com/ValvePython/vdf/actions?query=workflow%3A%22Tests%22+branch%3Amaster\n :alt: Build status of master branch\n\n.. _DuplicateOrderedDict: https://github.com/rossengeorgiev/dota2_notebooks/blob/master/DuplicateOrderedDict_for_VDF.ipynb\n\n.. _hash randomization: https://docs.python.org/2/using/cmdline.html#envvar-PYTHONHASHSEED\n\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Library for working with Valve's VDF text format",
"version": "3.4",
"split_keywords": [
"valve",
"keyvalue",
"vdf",
"tf2",
"dota2",
"csgo"
],
"urls": [
{
"comment_text": "",
"digests": {
"md5": "b5b53a66edfb2da020e05e26fffff8be",
"sha256": "68c1a125cc49e343d535af2dd25074e9cb0908c6607f073947c4a04bbe234534"
},
"downloads": -1,
"filename": "vdf-3.4-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "b5b53a66edfb2da020e05e26fffff8be",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 10357,
"upload_time": "2021-05-22T09:26:03",
"upload_time_iso_8601": "2021-05-22T09:26:03.948742Z",
"url": "https://files.pythonhosted.org/packages/96/60/6456b687cf55cf60020dcd01f9bc51561c3cc84f05fd8e0feb71ce60f894/vdf-3.4-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"md5": "8d756946693a6cd3ad3b96a02fa39c20",
"sha256": "fd5419f41e07a1009e5ffd027c7dcbe43d1f7e8ef453aeaa90d9d04b807de2af"
},
"downloads": -1,
"filename": "vdf-3.4.tar.gz",
"has_sig": false,
"md5_digest": "8d756946693a6cd3ad3b96a02fa39c20",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 11132,
"upload_time": "2021-05-22T09:26:05",
"upload_time_iso_8601": "2021-05-22T09:26:05.252775Z",
"url": "https://files.pythonhosted.org/packages/44/7f/74192f47d67c8bf3c47bf0d8487b3457614c2c98d58b6617721d217f3f79/vdf-3.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2021-05-22 09:26:05",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "ValvePython",
"github_project": "vdf",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"lcname": "vdf"
}