Skip to content

Commit

Permalink
Support for scientific notation in Float and Double tokens. U…
Browse files Browse the repository at this point in the history
…pdate documentation and docstrings.
  • Loading branch information
peunsu committed May 4, 2024
1 parent b5bc3e4 commit e5c75aa
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 36 deletions.
28 changes: 16 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![GitHub Release](https://img.shields.io/github/v/release/peunsu/ftb-snbt-lib?style=for-the-badge)

A python library to parse, edit, and save FTB snbt tag.
**A python library to parse, edit, and save FTB snbt tag.**

The FTB snbt tag is a variant of the "vanilla" snbt tag. It has no commas at end of lines, different suffixes for numeric values, and no support for array data type.

Expand Down Expand Up @@ -30,30 +30,30 @@ $ pip install ftb-snbt-lib
## Getting Started
* Import the library.
```python
>>> import ftb_snbt_lib
>>> import ftb_snbt_lib as slib
```

* ``load(fp)``: Load the ftb snbt tag from a file (``fp``).
```python
>>> some_snbt = ftb_snbt_lib.load(open("tests/some_file.snbt", "r", encoding="utf-8"))
>>> some_snbt = slib.load(open("tests/some_file.snbt", "r", encoding="utf-8"))
```
* The type of returned value is ``Compound``, a dictionary-like object.<br>
The ``Compound`` is containing values with **[tag data types](#data-types)** provided by this library.
```python
>>> type(some_snbt)
<class 'ftb_snbt.tag.Compound'>
<class 'ftb_snbt_lib.tag.Compound'>
>>> print(some_snbt)
Compound({'some_tag': String('some_value'), 'another_tag': Byte(1)})
```

* ``dump(tag, fp)``: Dump the ftb snbt tag to a file (``fp``).
```python
>>> ftb_snbt_lib.dump(some_snbt, open("tests/some_file_copy.snbt", "w", encoding="utf-8"))
>>> slib.dump(some_snbt, open("tests/some_file_copy.snbt", "w", encoding="utf-8"))
```

* ``loads(s)``: Load the ftb snbt tag from a string ``s``.
```python
>>> another_snbt = ftb_snbt_lib.loads('''
>>> another_snbt = slib.loads('''
... {
... some_tag: "some_value"
... another_tag: 1b
Expand All @@ -63,7 +63,7 @@ Compound({'some_tag': String('some_value'), 'another_tag': Byte(1)})

* ``dumps(tag)``: Dump the ftb snbt tag to a string.
```python
>>> dumped_snbt = ftb_snbt_lib.dumps(another_snbt)
>>> dumped_snbt = slib.dumps(another_snbt)
>>> print(dumped_snbt)
{
some_tag: "some_value"
Expand All @@ -74,12 +74,15 @@ Compound({'some_tag': String('some_value'), 'another_tag': Byte(1)})
* Edit the snbt tag. As its type is ``Compound``, it can be edited like a dictionary.<br>
The inserted or replace values should be any of **[tag data types](#data-types)** provided by this library.
```python
>>> another_snbt["some_tag"] = ftb_snbt_lib.String("another_value")
>>> another_snbt["some_tag"] = slib.String("another_value")
```

* When editing the ``List``, a list-like object, its elements must have **the same type**.<br>
For instance, ``List[Byte(1), Byte(2), Byte(3)]`` must contain **only** the ``Byte`` type object, so the other types like ``Integer`` or ``String`` **cannot be added or replaced** in it.

* When editing the ``Array``, a list-like object with **a fixed length**, its elements must have **the same type**, and that type must **match the element type defined in the array**.<br>
For instance, ``IntArray`` with a length of 3 must contain **three** ``Integer`` type objects, so **adding new objects, removing existing objects, and replacing with other type objects are not allowed**.

* Save the edited snbt tag to a json file.
```python
>>> import json
Expand All @@ -93,14 +96,15 @@ For instance, ``List[Byte(1), Byte(2), Byte(3)]`` must contain **only** the ``By
| Short | A signed 16-bit integer.<br>Range: ``-32,768`` ~ ``32,767`` | ``<number>s`` | ``132s``, ``-243s`` |
| Integer | A signed 32-bit integer.<br>Range: ``-2,147,483,647`` ~ ``2,147,483,647`` | ``<number>`` | ``12345`` |
| Long | A signed 64-bit integer.<br>Range: ``9,223,372,036,854,775,808`` ~ ``9,223,372,036,854,775,807`` | ``<number>L`` | ``12345L`` |
| Float | A 32-bit, single-precision floating-point number.<br>Range: ``-3.4E+38`` ~ ``+3.4E+38`` | ``<number>f`` | ``12.345f`` |
| Double | A 64-bit, double-precision floating-point number.<br>Range: ``-1.7E+308`` ~ ``+1.7E+308`` | ``<number>d`` | ``12.345d`` |
| Float | A 32-bit, single-precision floating-point number.<br>Range: ``-3.4E+38`` ~ ``+3.4E+38`` | ``<number>f`` | ``12.345f``, ``1.0E-6f`` |
| Double | A 64-bit, double-precision floating-point number.<br>Range: ``-1.7E+308`` ~ ``+1.7E+308`` | ``<number>d`` | ``12.345d``, ``1.0E-6d`` |
| Bool | A boolean data type.<br>``0`` for ``false``, ``1`` for ``true``. | ``false``, ``true`` | ``true`` |
| String | A sequence of characters. | A string enclosed in **double quotes ``""``**.<br>Nested double quotes can be included within a string using a **escaping character ``\"``**. | `"Hello, World!"`,<br>`"Say \"Hello, World!\""` |
| List | An ordered list of tags.<br>The tags must be of **the same type**, determined by the first tag in the list. | Unnamed tags enclosed in square brackets and delimited by **newline** characters (``\n``). | <pre>[<br> 3.2d<br> 1.4d<br> ...<br>]</pre> |
| Array | An ordered list of 8-bit(ByteArray), 32-bit(IntArray), 64-bit(LongArray) integers. | ``<array_prefix>;`` followed by an ordered list of tags enclosed in square brackets and delimited by **newline** characters (``\n``).<br>Valid array prefixes are ``B``(Byte), ``I``(Integer), and ``L``(Long). | <pre>[B;<br> 12b<br> -35b<br> ...<br>]</pre> |
| Array | An ordered list of 8-bit(``ByteArray``), 32-bit(``IntArray``), 64-bit(``LongArray``) integers. | ``<array_prefix>;`` followed by an ordered list of tags enclosed in square brackets and delimited by **newline** characters (``\n``).<br>Valid array prefixes are ``B``(Byte), ``I``(Integer), and ``L``(Long). | <pre>[B;<br> 12b<br> -35b<br> ...<br>]</pre> |
| Compound | An ordered list of attribute-value pairs.<br>Each tag can be of **any type**. | Named tags enclosed in curly braces and delimited by commas or **newline** characters (``\n``).<br>The key (tag name) can be unquoted if it contains only ``0-9``, ``A-Z``, ``a-z``, ``_``, ``-``, ``.``, and ``+``. Otherwise the key should be quoted, using the format of ``String`` type. | <pre>[<br> tag1: "string"<br> tag2: 12b<br> \"quoted:tag\": 3.5d<br> ...<br>]</pre> |

## References
* [PLY - Python Lex-Yacc](https://github.com/dabeaz/ply) by [David Beazley](https://www.dabeaz.com)
* [nbtlib](https://github.com/vberlier/nbtlib) by [vberlier](https://github.com/vberlier)
* [nbtlib](https://github.com/vberlier/nbtlib) by [vberlier](https://github.com/vberlier)
* [NBT format - Minecraft Wiki (fandom)](https://minecraft.fandom.com/wiki/NBT_format)
12 changes: 6 additions & 6 deletions example.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import ftb_snbt_lib
import ftb_snbt_lib as slib
import json

# Load the ftb snbt tag from a file.
some_snbt = ftb_snbt_lib.load(open("tests/some_file.snbt", "r", encoding="utf-8"))
some_snbt = slib.load(open("tests/some_file.snbt", "r", encoding="utf-8"))

# Dump the ftb snbt tag to a file.
ftb_snbt_lib.dump(some_snbt, open("tests/some_file_copy.snbt", "w", encoding="utf-8"))
slib.dump(some_snbt, open("tests/some_file_copy.snbt", "w", encoding="utf-8"))

# Load the ftb snbt tag from a string.
another_snbt = ftb_snbt_lib.loads('''
another_snbt = slib.loads('''
{
some_tag: "some_value"
another_tag: 1b
}
''')

# Dump the ftb snbt tag to a string.
dumped_snbt = ftb_snbt_lib.dumps(another_snbt)
dumped_snbt = slib.dumps(another_snbt)

# Print the dumped snbt string.
print(dumped_snbt)
Expand All @@ -27,7 +27,7 @@
# }

# Edit the snbt tag. Since the snbt tag is a Compound, it can be edited like a dictionary but only with custom types provided by this library.
another_snbt["some_tag"] = ftb_snbt_lib.String("another_value")
another_snbt["some_tag"] = slib.String("another_value")

# Save the edited snbt tag to a json file.
json.dump(another_snbt, open("tests/test.json", "w", encoding="utf-8"), indent=4, ensure_ascii=False)
2 changes: 1 addition & 1 deletion ftb_snbt_lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
from .tag import *
from .write import *

__version__ = '0.2.2'
__version__ = '0.2.3'
__all__ = ['parse', 'tag', 'write']
18 changes: 9 additions & 9 deletions ftb_snbt_lib/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ def get_parser():
Example
-------
>>> import ftb_snbt
>>> parser = ftb_snbt.get_parser()
>>> import ftb_snbt_lib as slib
>>> parser = slib.get_parser()
>>> snbt = parser.parse('''
{
some_tag: "some_value"
Expand All @@ -99,7 +99,7 @@ def get_parser():
def loads(s: str) -> Compound:
"""Load an FTB snbt string and return the result as a Compound object.
The loaded SNBT object consists of custom types: ``Compound``, ``List``, ``Numeric``, ``Bool``, and ``String``.
The loaded SNBT object consists of custom types: ``Compound``, ``List``, ``Array``, ``Numeric``, ``Bool``, and ``String``.
When modifying the loaded object, use the provided custom types to ensure that the object is valid.
Expand All @@ -113,8 +113,8 @@ def loads(s: str) -> Compound:
Example
-------
>>> import ftb_snbt
>>> snbt = ftb_snbt.loads('''
>>> import ftb_snbt_lib as slib
>>> snbt = slib.loads('''
{
some_tag: "some_value"
another_tag: 1b
Expand All @@ -130,7 +130,7 @@ def load(fp) -> Compound:
"""
Load an FTB snbt file and return the result as a Compound object.
The loaded SNBT object consists of custom types: ``Compound``, ``List``, ``Numeric``, ``Bool``, and ``String``.
The loaded SNBT object consists of custom types: ``Compound``, ``List``, ``Array``, ``Numeric``, ``Bool``, and ``String``.
When modifying the loaded object, use the provided custom types to ensure that the object is valid.
Expand All @@ -144,10 +144,10 @@ def load(fp) -> Compound:
Example
-------
>>> import ftb_snbt
>>> snbt = ftb_snbt.load(open("path/to/file/some_file.snbt", "r", encoding="utf-8"))
>>> import ftb_snbt_lib as slib
>>> snbt = slib.load(open("path/to/file/some_file.snbt", "r", encoding="utf-8"))
>>> type(snbt)
<class 'ftb_snbt.tag.Compound'>
<class 'ftb_snbt_lib.tag.Compound'>
"""
parser = get_parser()
return parser.parse(fp.read())
4 changes: 2 additions & 2 deletions ftb_snbt_lib/token.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ def t_SHORT(t):
return t

def t_FLOAT(t):
r'\-?[0-9]+\.[0-9]+f'
r'\-?[0-9]+(?:\.[0-9]+)?(?:[eE][\+\-]?[0-9]+)?f'
t.value = Float(t.value[:-1])
return t

def t_DOUBLE(t):
r'\-?[0-9]+\.[0-9]+d'
r'\-?[0-9]+(?:\.[0-9]+)?(?:[eE][\+\-]?[0-9]+)?d'
t.value = Double(t.value[:-1])
return t

Expand Down
12 changes: 6 additions & 6 deletions ftb_snbt_lib/write.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ def get_writer():
Example
-------
>>> import ftb_snbt
>>> writer = ftb_snbt.get_writer()
>>> import ftb_snbt_lib as slib
>>> writer = slib.get_writer()
>>> snbt = Compound({
... 'some_tag': String('some_value'),
... 'another_tag': Byte(1)
Expand Down Expand Up @@ -45,12 +45,12 @@ def dumps(tag: Base) -> str:
Example
-------
>>> import ftb_snbt
>>> import ftb_snbt_lib as slib
>>> snbt = Compound({
... 'some_tag': String('some_value'),
... 'another_tag': Byte(1)
... })
>>> dumped_snbt = ftb_snbt.dumps(snbt)
>>> dumped_snbt = slib.dumps(snbt)
>>> print(dumped_snbt)
{
some_tag: "some_value"
Expand All @@ -69,12 +69,12 @@ def dump(tag: Base, fp) -> None:
Example
-------
>>> import ftb_snbt
>>> import ftb_snbt_lib as slib
>>> snbt = Compound({
... 'some_tag': String('some_value'),
... 'another_tag': Byte(1)
... })
>>> ftb_snbt.dump(snbt, open('some_file.snbt', 'w', encoding='utf-8'))
>>> slib.dump(snbt, open('some_file.snbt', 'w', encoding='utf-8'))
"""
fp.write(dumps(tag))

Expand Down

0 comments on commit e5c75aa

Please sign in to comment.