Metadata-Version: 2.1
Name: vdf
Version: 4.0
Summary: Library for working with Valve's VDF text format
Home-page: https://github.com/solsticegamestudios/vdf
Author: Rossen Georgiev / Solstice Game Studios
Author-email: py-vdf@solsticegamestudios.com
License: MIT
Keywords: valve keyvalue vdf tf2 dota2 csgo
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: Implementation :: PyPy
Requires-Python: >=3.6
License-File: LICENSE

| |coverage| |master_build|

Pure python module for (de)serialization to and from VDF that works just like ``json``.

A fork of `ValvePython/vdf <https://github.com/ValvePython/vdf>`_, which has apparently been abandoned.

Supports Python ``3.6+`` and PyPy ``3.10``

VDF is Valve's KeyValue text file format

https://developer.valvesoftware.com/wiki/KeyValues

| Supported versions: ``kv1``
| Unsupported: ``kv2`` and ``kv3``

Install
-------

**WARNING:** Only ValvePython's (out of date) version is on PyPI.

Installing directly from ``github`` repository:

.. code:: bash

	# master
	pip install "git+https://github.com/solsticegamestudios/vdf"

	# specific version
	pip install "git+https://github.com/solsticegamestudios/vdf@v1.0"


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.

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://coveralls.io/repos/github/solsticegamestudios/vdf/badge.svg
    :target: https://coveralls.io/github/solsticegamestudios/vdf
    :alt: Test coverage

.. |master_build| image:: https://github.com/solsticegamestudios/vdf/actions/workflows/testing.yml/badge.svg?branch=master
    :target: https://github.com/solsticegamestudios/vdf/actions/workflows/testing.yml?query=branch%3Amaster
    :alt: Build status of master branch
