pyfracturedjson 0.1.4__tar.gz → 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,13 +4,30 @@ on:
4
4
  push:
5
5
  tags:
6
6
  - 'v[0-9]+.[0-9]+.[0-9]+'
7
+ branches:
8
+ - dev
9
+ - develop
7
10
 
8
11
  permissions:
9
12
  contents: read
10
13
 
11
14
  jobs:
15
+ test:
16
+ name: Test
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v6
20
+ - uses: actions/setup-python@v6
21
+ with:
22
+ python-version: '3.11'
23
+ - name: Install uv
24
+ uses: astral-sh/setup-uv@v7
25
+ - name: Run tests
26
+ run: uv run python -m pytest tests/
27
+
12
28
  linux:
13
29
  runs-on: ${{ matrix.platform.runner }}
30
+ needs: test
14
31
  strategy:
15
32
  matrix:
16
33
  platform:
@@ -44,8 +61,47 @@ jobs:
44
61
  name: wheels-linux-${{ matrix.platform.target }}
45
62
  path: dist
46
63
 
64
+ test_install:
65
+ name: Test Install
66
+ runs-on: ubuntu-latest
67
+ needs: linux
68
+ steps:
69
+ - uses: actions/setup-python@v6
70
+ with:
71
+ python-version: '3.11'
72
+
73
+ - name: Download wheel
74
+ uses: actions/download-artifact@v4
75
+ with:
76
+ pattern: wheels-linux-*
77
+ path: dist/
78
+ merge-multiple: true
79
+
80
+ - name: Install local wheel
81
+ run: pip install --no-index --find-links=dist/ pyfracturedjson
82
+
83
+ - name: Import and smoke test
84
+ run: |
85
+ python -c '
86
+ from fracturedjson import dumps
87
+
88
+ expected="""{
89
+ "abcd" : "abcd",
90
+ "long_list": [
91
+ "thing_0", "thing_1", "thing_2", "thing_3", "thing_4", "thing_5", "thing_6", "thing_7", "thing_8",
92
+ "thing_9", "thing_10", "thing_11", "thing_12", "thing_13", "thing_14", "thing_15", "thing_16", "thing_17",
93
+ "thing_18", "thing_19"
94
+ ]
95
+ }
96
+ """
97
+ long_list = [f"thing_{i}" for i in range(20)]
98
+ actual = dumps({"abcd": "abcd", "long_list": long_list})
99
+ assert actual == expected, f"unexpected format:\n\nexpected:\n{expected}\nactual:\n{actual}"
100
+ '
101
+
47
102
  musllinux:
48
103
  runs-on: ${{ matrix.platform.runner }}
104
+ needs: test_install
49
105
  strategy:
50
106
  matrix:
51
107
  platform:
@@ -77,6 +133,7 @@ jobs:
77
133
 
78
134
  windows:
79
135
  runs-on: ${{ matrix.platform.runner }}
136
+ needs: test_install
80
137
  strategy:
81
138
  matrix:
82
139
  platform:
@@ -93,7 +150,7 @@ jobs:
93
150
  - uses: actions/checkout@v6
94
151
  - uses: actions/setup-python@v6
95
152
  with:
96
- python-version: 3.13
153
+ python-version: '3.13'
97
154
  architecture: ${{ matrix.platform.python_arch }}
98
155
  - name: Build wheels
99
156
  uses: PyO3/maturin-action@v1
@@ -109,6 +166,7 @@ jobs:
109
166
 
110
167
  macos:
111
168
  runs-on: ${{ matrix.platform.runner }}
169
+ needs: test_install
112
170
  strategy:
113
171
  matrix:
114
172
  platform:
@@ -135,6 +193,7 @@ jobs:
135
193
 
136
194
  sdist:
137
195
  runs-on: ubuntu-latest
196
+ needs: test_install
138
197
  steps:
139
198
  - uses: actions/checkout@v6
140
199
  - name: Build sdist
@@ -151,11 +210,13 @@ jobs:
151
210
  release:
152
211
  name: Release
153
212
  runs-on: ubuntu-latest
154
- needs: [linux, musllinux, windows, macos, sdist]
213
+ needs: [linux, musllinux, windows, macos, sdist, test_install]
214
+ if: startsWith(github.ref, 'refs/tags/v')
155
215
  permissions:
156
216
  id-token: write
157
217
  contents: write
158
218
  attestations: write
219
+
159
220
  steps:
160
221
  - name: Download wheels
161
222
  uses: actions/download-artifact@v5
@@ -175,4 +236,4 @@ jobs:
175
236
  - name: Publish to PyPI
176
237
  run: uv publish dist/*
177
238
  env:
178
- UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
239
+ UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
@@ -1,4 +1,5 @@
1
1
  /target
2
+ test_env/
2
3
 
3
4
  # Byte-compiled / optimized / DLL files
4
5
  __pycache__/
@@ -168,7 +168,7 @@ dependencies = [
168
168
 
169
169
  [[package]]
170
170
  name = "pyfracturedjson"
171
- version = "0.1.4"
171
+ version = "2.0.0"
172
172
  dependencies = [
173
173
  "fracturedjson",
174
174
  "pyo3",
@@ -1,12 +1,11 @@
1
1
  [package]
2
2
  name = "pyfracturedjson"
3
- version = "0.1.4"
3
+ version = "2.0.0"
4
4
  edition = "2024"
5
5
  readme = "README.md"
6
6
 
7
- # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
7
  [lib]
9
- name = "fractured_json_rust_wrapper"
8
+ name = "_rust_wrapper"
10
9
  crate-type = ["cdylib"]
11
10
 
12
11
  [dependencies]
@@ -0,0 +1,57 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyfracturedjson
3
+ Version: 2.0.0
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
7
+ Summary: A compact yet readable JSON formatter
8
+ Keywords: json,formatter,fracturedjson,compact,readable
9
+ Requires-Python: >=3.9
10
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
11
+ Project-URL: Repository, https://github.com/g-b-f/pyFracturedJSON
12
+
13
+ # pyFracturedJSON
14
+
15
+ Adds [FracturedJSON](https://github.com/j-brooke/FracturedJson) support to python,
16
+ allowing you to create JSON that is both compact and readable.
17
+
18
+ Using it is easy:
19
+
20
+ ```python
21
+ import json
22
+ from fracturedjson import Encoder
23
+
24
+ long_list = [f"thing_{i}" for i in range(20)]
25
+ data = {"abcd": "abcd", "long_list": long_list}
26
+
27
+ print(json.dumps(data, cls=Encoder))
28
+ print(json.dumps(data, cls=Encoder, line_length=50))
29
+ print(json.dumps(data, cls=Encoder, indent=2))
30
+
31
+ with open("file.json", "w") as f:
32
+ json.dump(data, f, cls=Encoder)
33
+ ```
34
+
35
+ You can also use it as a drop-in replacement for the `json` module:
36
+
37
+ ```python
38
+ import fracturedjson as json
39
+
40
+ long_list = [f"thing_{i}" for i in range(20)]
41
+ data = {"abcd": "abcd", "long_list": long_list}
42
+
43
+ print(json.dumps(data))
44
+ print(json.dumps(data, line_length=50))
45
+ print(json.dumps(data, indent=2))
46
+
47
+ with open("file.json", "w") as f:
48
+ json.dump(data, f)
49
+
50
+ with open("file.json") as f:
51
+ json.load(f)
52
+
53
+ json.loads('{"foo":"bar"}')
54
+ ```
55
+
56
+ This is mostly a wrapper around [fracturedjson-rs](https://github.com/fcoury/fracturedjson-rs),
57
+ so all credit goes to the creator.
@@ -7,7 +7,7 @@ Using it is easy:
7
7
 
8
8
  ```python
9
9
  import json
10
- from FracturedJSON import Encoder
10
+ from fracturedjson import Encoder
11
11
 
12
12
  long_list = [f"thing_{i}" for i in range(20)]
13
13
  data = {"abcd": "abcd", "long_list": long_list}
@@ -20,5 +20,26 @@ with open("file.json", "w") as f:
20
20
  json.dump(data, f, cls=Encoder)
21
21
  ```
22
22
 
23
+ You can also use it as a drop-in replacement for the `json` module:
24
+
25
+ ```python
26
+ import fracturedjson as json
27
+
28
+ long_list = [f"thing_{i}" for i in range(20)]
29
+ data = {"abcd": "abcd", "long_list": long_list}
30
+
31
+ print(json.dumps(data))
32
+ print(json.dumps(data, line_length=50))
33
+ print(json.dumps(data, indent=2))
34
+
35
+ with open("file.json", "w") as f:
36
+ json.dump(data, f)
37
+
38
+ with open("file.json") as f:
39
+ json.load(f)
40
+
41
+ json.loads('{"foo":"bar"}')
42
+ ```
43
+
23
44
  This is mostly a wrapper around [fracturedjson-rs](https://github.com/fcoury/fracturedjson-rs),
24
45
  so all credit goes to the creator.
@@ -0,0 +1,219 @@
1
+ import json
2
+ from collections.abc import Iterator
3
+ from typing import Callable
4
+
5
+ import _rust_wrapper
6
+
7
+
8
+ class Encoder(json.encoder.JSONEncoder):
9
+ def __init__(
10
+ self,
11
+ *,
12
+ skipkeys: bool = False,
13
+ ensure_ascii: bool = True,
14
+ check_circular: bool = True,
15
+ allow_nan: bool = True,
16
+ sort_keys: bool = False,
17
+ indent = 4,
18
+ separators: tuple[str, str] | None = None,
19
+ default: Callable | None = None,
20
+ **kwargs
21
+ ):
22
+ super().__init__(
23
+ skipkeys=skipkeys,
24
+ ensure_ascii=ensure_ascii,
25
+ check_circular=check_circular,
26
+ allow_nan=allow_nan,
27
+ sort_keys=sort_keys,
28
+ indent=indent,
29
+ separators=separators,
30
+ default=default
31
+ )
32
+
33
+ if indent is None:
34
+ indent = 4
35
+ self._indent = indent
36
+ self.line_length = kwargs.get("line_length", 120)
37
+
38
+
39
+ def encode(self, o) -> str:
40
+ unformatted = json.dumps(o)
41
+ formatted = _rust_wrapper.reformat_string(
42
+ unformatted,
43
+ indent=self._indent,
44
+ line_length=self.line_length
45
+ )
46
+ return formatted
47
+
48
+ def iterencode(self, o, *args, **kwargs) -> Iterator[str]:
49
+ return iter(self.encode(o))
50
+
51
+
52
+ def dump(
53
+ obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True,
54
+ allow_nan=True, cls=None, indent=None, separators=None,
55
+ default=None, sort_keys=False, **kw
56
+ ):
57
+ """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
58
+ ``.write()``-supporting file-like object).
59
+
60
+ If ``skipkeys`` is true then ``dict`` keys that are not basic types
61
+ (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped
62
+ instead of raising a ``TypeError``.
63
+
64
+ If ``ensure_ascii`` is false, then the strings written to ``fp`` can
65
+ contain non-ASCII characters if they appear in strings contained in
66
+ ``obj``. Otherwise, all such characters are escaped in JSON strings.
67
+
68
+ If ``check_circular`` is false, then the circular reference check
69
+ for container types will be skipped and a circular reference will
70
+ result in an ``RecursionError`` (or worse).
71
+
72
+ If ``allow_nan`` is false, then it will be a ``ValueError`` to
73
+ serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
74
+ in strict compliance of the JSON specification, instead of using the
75
+ JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
76
+
77
+ If ``indent`` is a non-negative integer, then JSON array elements and
78
+ object members will be pretty-printed with that indent level. An indent
79
+ level of 0 will only insert newlines. ``None`` is the most compact
80
+ representation.
81
+
82
+ If specified, ``separators`` should be an ``(item_separator, key_separator)``
83
+ tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and
84
+ ``(',', ': ')`` otherwise. To get the most compact JSON representation,
85
+ you should specify ``(',', ':')`` to eliminate whitespace.
86
+
87
+ ``default(obj)`` is a function that should return a serializable version
88
+ of obj or raise TypeError. The default simply raises TypeError.
89
+
90
+ If *sort_keys* is true (default: ``False``), then the output of
91
+ dictionaries will be sorted by key.
92
+
93
+ To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
94
+ ``.default()`` method to serialize additional types), specify it with
95
+ the ``cls`` kwarg; otherwise ``FracturedJSON.Encoder`` is used.
96
+
97
+ """
98
+ return json.dump(
99
+ obj, fp,
100
+ cls=Encoder if cls is None else cls,
101
+ skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular,
102
+ allow_nan=allow_nan, indent=indent, separators=separators,
103
+ default=default, sort_keys=sort_keys,
104
+ **kw
105
+ )
106
+
107
+ def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
108
+ allow_nan=True, cls=None, indent=None, separators=None,
109
+ default=None, sort_keys=False, **kw):
110
+ """Serialize ``obj`` to a JSON formatted ``str``.
111
+
112
+ If ``skipkeys`` is true then ``dict`` keys that are not basic types
113
+ (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped
114
+ instead of raising a ``TypeError``.
115
+
116
+ If ``ensure_ascii`` is false, then the return value can contain non-ASCII
117
+ characters if they appear in strings contained in ``obj``. Otherwise, all
118
+ such characters are escaped in JSON strings.
119
+
120
+ If ``check_circular`` is false, then the circular reference check
121
+ for container types will be skipped and a circular reference will
122
+ result in an ``RecursionError`` (or worse).
123
+
124
+ If ``allow_nan`` is false, then it will be a ``ValueError`` to
125
+ serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
126
+ strict compliance of the JSON specification, instead of using the
127
+ JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
128
+
129
+ If ``indent`` is a non-negative integer, then JSON array elements and
130
+ object members will be pretty-printed with that indent level. An indent
131
+ level of 0 will only insert newlines. ``None`` is the most compact
132
+ representation.
133
+
134
+ If specified, ``separators`` should be an ``(item_separator, key_separator)``
135
+ tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and
136
+ ``(',', ': ')`` otherwise. To get the most compact JSON representation,
137
+ you should specify ``(',', ':')`` to eliminate whitespace.
138
+
139
+ ``default(obj)`` is a function that should return a serializable version
140
+ of obj or raise TypeError. The default simply raises TypeError.
141
+
142
+ If *sort_keys* is true (default: ``False``), then the output of
143
+ dictionaries will be sorted by key.
144
+
145
+ To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
146
+ ``.default()`` method to serialize additional types), specify it with
147
+ the ``cls`` kwarg; otherwise ``FracturedJSON.Encoder`` is used.
148
+
149
+ """
150
+ return json.dumps(
151
+ obj,
152
+ cls=Encoder if cls is None else cls,
153
+ skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular,
154
+ allow_nan=allow_nan, indent=indent, separators=separators,
155
+ default=default, sort_keys=sort_keys,
156
+ **kw
157
+ )
158
+
159
+ def load(fp, *, cls=None, object_hook=None, parse_float=None,
160
+ parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
161
+ """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
162
+ a JSON document) to a Python object.
163
+
164
+ ``object_hook`` is an optional function that will be called with the
165
+ result of any object literal decode (a ``dict``). The return value of
166
+ ``object_hook`` will be used instead of the ``dict``. This feature
167
+ can be used to implement custom decoders (e.g. JSON-RPC class hinting).
168
+
169
+ ``object_pairs_hook`` is an optional function that will be called with the
170
+ result of any object literal decoded with an ordered list of pairs. The
171
+ return value of ``object_pairs_hook`` will be used instead of the ``dict``.
172
+ This feature can be used to implement custom decoders. If ``object_hook``
173
+ is also defined, the ``object_pairs_hook`` takes priority.
174
+
175
+ To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
176
+ kwarg; otherwise ``JSONDecoder`` is used.
177
+ """
178
+ return json.load(fp, cls=cls, object_hook=object_hook, parse_float=parse_float,
179
+ parse_int=parse_int, parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
180
+
181
+ def loads(fp, *, cls=None, object_hook=None, parse_float=None,
182
+ parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
183
+ """Deserialize ``s`` (a ``str``, ``bytes`` or ``bytearray`` instance
184
+ containing a JSON document) to a Python object.
185
+
186
+ ``object_hook`` is an optional function that will be called with the
187
+ result of any object literal decode (a ``dict``). The return value of
188
+ ``object_hook`` will be used instead of the ``dict``. This feature
189
+ can be used to implement custom decoders (e.g. JSON-RPC class hinting).
190
+
191
+ ``object_pairs_hook`` is an optional function that will be called with the
192
+ result of any object literal decoded with an ordered list of pairs. The
193
+ return value of ``object_pairs_hook`` will be used instead of the ``dict``.
194
+ This feature can be used to implement custom decoders. If ``object_hook``
195
+ is also defined, the ``object_pairs_hook`` takes priority.
196
+
197
+ ``parse_float``, if specified, will be called with the string
198
+ of every JSON float to be decoded. By default this is equivalent to
199
+ float(num_str). This can be used to use another datatype or parser
200
+ for JSON floats (e.g. decimal.Decimal).
201
+
202
+ ``parse_int``, if specified, will be called with the string
203
+ of every JSON int to be decoded. By default this is equivalent to
204
+ int(num_str). This can be used to use another datatype or parser
205
+ for JSON integers (e.g. float).
206
+
207
+ ``parse_constant``, if specified, will be called with one of the
208
+ following strings: -Infinity, Infinity, NaN.
209
+ This can be used to raise an exception if invalid JSON numbers
210
+ are encountered.
211
+
212
+ To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
213
+ kwarg; otherwise ``JSONDecoder`` is used.
214
+ """
215
+ return json.loads(fp, cls=cls, object_hook=object_hook, parse_float=parse_float,
216
+ parse_int=parse_int, parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
217
+
218
+ def detect_encoding(b):
219
+ return json.detect_encoding(b)
@@ -1,7 +1,10 @@
1
1
  [project]
2
2
  name = "pyfracturedjson"
3
- requires-python = ">=3.8"
3
+ requires-python = ">=3.9"
4
4
  description = "A compact yet readable JSON formatter"
5
+ readme = "README.md"
6
+ packages = ["fracturedjson"]
7
+
5
8
  classifiers = [
6
9
  "Programming Language :: Rust",
7
10
  "Programming Language :: Python :: Implementation :: CPython",
@@ -17,6 +20,17 @@ Repository = "https://github.com/g-b-f/pyFracturedJSON"
17
20
  requires = ["maturin>=1.11,<2.0"]
18
21
  build-backend = "maturin"
19
22
 
23
+ [tool.mypy]
24
+ check_untyped_defs = true
25
+ follow_untyped_imports = true
26
+
27
+ [tool.pytest.ini_options]
28
+ filterwarnings = ["error"]
29
+
30
+ [tool.maturin]
31
+
32
+ include = ["fracturedjson/*"]
33
+
20
34
 
21
35
  [tool.ruff.lint]
22
36
  extend-select = [
@@ -29,7 +43,11 @@ extend-select = [
29
43
  "PT", # Pytest
30
44
  "SIM", # Simplifications
31
45
  "TID", # Tidy imports
32
- "PTH", # Use Pathlib instead of os.path etc
33
46
  "I", # isort
34
47
  "C901", # flake8-c901 complexity
35
- ]
48
+ ]
49
+
50
+ [dependency-groups]
51
+ dev = [
52
+ "pytest>=8.3.5",
53
+ ]
@@ -13,7 +13,7 @@ fn reformat_string(input: String, indent:usize, line_length: usize) -> String {
13
13
  }
14
14
 
15
15
  #[pymodule]
16
- fn fractured_json_rust_wrapper(m: &Bound<'_, PyModule>) -> PyResult<()> {
16
+ fn _rust_wrapper(m: &Bound<'_, PyModule>) -> PyResult<()> {
17
17
  m.add_function(wrap_pyfunction!(reformat_string, m)?)?;
18
18
  Ok(())
19
19
  }
@@ -0,0 +1,27 @@
1
+ {
2
+ "BasicObject" : {
3
+ "ModuleId" : "armor",
4
+ "Name" : "",
5
+ "Locations" : [
6
+ [11, 2], [11, 3], [11, 4], [11, 5], [11, 6], [11, 7], [11, 8], [11, 9], [11, 10], [11, 11],
7
+ [11, 12], [11, 13], [11, 14], [ 1, 14], [ 1, 13], [ 1, 12], [ 1, 11], [ 1, 10], [ 1, 9], [ 1, 8],
8
+ [ 1, 7], [ 1, 6], [ 1, 5], [ 1, 4], [ 1, 3], [ 1, 2], [ 4, 2], [ 5, 2], [ 6, 2], [ 7, 2],
9
+ [ 8, 2], [ 8, 3], [ 7, 3], [ 6, 3], [ 5, 3], [ 4, 3], [ 0, 4], [ 0, 5], [ 0, 6], [ 0, 7],
10
+ [ 0, 8], [12, 8], [12, 7], [12, 6], [12, 5], [12, 4]
11
+ ],
12
+ "Orientation": "Fore",
13
+ "Seed" : 272691529
14
+ },
15
+ "SimilarArrays" : {
16
+ "Katherine": ["blue", "lightblue", "black" ],
17
+ "Logan" : ["yellow", "blue", "black", "red"],
18
+ "Erik" : ["red", "purple" ],
19
+ "Jean" : ["lightgreen", "yellow", "black" ]
20
+ },
21
+ "SimilarObjects": [
22
+ { "type": "turret", "hp": 400, "loc": {"x": 47, "y": -4}, "flags": "S" },
23
+ { "type": "assassin", "hp": 80, "loc": {"x": 12, "y": 6}, "flags": "Q" },
24
+ { "type": "berserker", "hp": 150, "loc": {"x": 0, "y": 0} },
25
+ { "type": "pittrap", "loc": {"x": 10, "y": -14}, "flags": "S,I" }
26
+ ]
27
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "BasicObject" : {
3
+ "ModuleId" : "armor",
4
+ "Name" : "",
5
+ "Locations" : [
6
+ [11, 2], [11, 3], [11, 4], [11, 5], [11, 6], [11, 7], [11, 8], [11, 9], [11, 10], [11, 11], [11, 12],
7
+ [11, 13], [11, 14], [ 1, 14], [ 1, 13], [ 1, 12], [ 1, 11], [ 1, 10], [ 1, 9], [ 1, 8], [ 1, 7], [ 1, 6],
8
+ [ 1, 5], [ 1, 4], [ 1, 3], [ 1, 2], [ 4, 2], [ 5, 2], [ 6, 2], [ 7, 2], [ 8, 2], [ 8, 3], [ 7, 3],
9
+ [ 6, 3], [ 5, 3], [ 4, 3], [ 0, 4], [ 0, 5], [ 0, 6], [ 0, 7], [ 0, 8], [12, 8], [12, 7], [12, 6],
10
+ [12, 5], [12, 4]
11
+ ],
12
+ "Orientation": "Fore",
13
+ "Seed" : 272691529
14
+ },
15
+ "SimilarArrays" : {
16
+ "Katherine": ["blue", "lightblue", "black" ],
17
+ "Logan" : ["yellow", "blue", "black", "red"],
18
+ "Erik" : ["red", "purple" ],
19
+ "Jean" : ["lightgreen", "yellow", "black" ]
20
+ },
21
+ "SimilarObjects": [
22
+ { "type": "turret", "hp": 400, "loc": {"x": 47, "y": -4}, "flags": "S" },
23
+ { "type": "assassin", "hp": 80, "loc": {"x": 12, "y": 6}, "flags": "Q" },
24
+ { "type": "berserker", "hp": 150, "loc": {"x": 0, "y": 0} },
25
+ { "type": "pittrap", "loc": {"x": 10, "y": -14}, "flags": "S,I" }
26
+ ]
27
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "BasicObject" : {
3
+ "ModuleId" : "armor",
4
+ "Name" : "",
5
+ "Locations" : [
6
+ [11, 2], [11, 3], [11, 4], [11, 5], [11, 6], [11, 7], [11, 8], [11, 9],
7
+ [11, 10], [11, 11], [11, 12], [11, 13], [11, 14], [ 1, 14], [ 1, 13], [ 1, 12],
8
+ [ 1, 11], [ 1, 10], [ 1, 9], [ 1, 8], [ 1, 7], [ 1, 6], [ 1, 5], [ 1, 4],
9
+ [ 1, 3], [ 1, 2], [ 4, 2], [ 5, 2], [ 6, 2], [ 7, 2], [ 8, 2], [ 8, 3],
10
+ [ 7, 3], [ 6, 3], [ 5, 3], [ 4, 3], [ 0, 4], [ 0, 5], [ 0, 6], [ 0, 7],
11
+ [ 0, 8], [12, 8], [12, 7], [12, 6], [12, 5], [12, 4]
12
+ ],
13
+ "Orientation": "Fore",
14
+ "Seed" : 272691529
15
+ },
16
+ "SimilarArrays" : {
17
+ "Katherine": ["blue", "lightblue", "black" ],
18
+ "Logan" : ["yellow", "blue", "black", "red"],
19
+ "Erik" : ["red", "purple" ],
20
+ "Jean" : ["lightgreen", "yellow", "black" ]
21
+ },
22
+ "SimilarObjects": [
23
+ { "type": "turret", "hp": 400, "loc": {"x": 47, "y": -4}, "flags": "S" },
24
+ { "type": "assassin", "hp": 80, "loc": {"x": 12, "y": 6}, "flags": "Q" },
25
+ { "type": "berserker", "hp": 150, "loc": {"x": 0, "y": 0} },
26
+ { "type": "pittrap", "loc": {"x": 10, "y": -14}, "flags": "S,I" }
27
+ ]
28
+ }
@@ -0,0 +1,37 @@
1
+ import json
2
+ from pathlib import Path
3
+
4
+ import pytest
5
+
6
+ from fracturedjson import Encoder
7
+
8
+ params = [
9
+ ("default_settings.json", {}),
10
+ ("line_len_100.json", {"line_length":100}),
11
+ ("indent_2.json", {"indent":2}),
12
+ ]
13
+
14
+ def read_file(filename) -> tuple[str, dict]:
15
+ file = Path(__file__).parent / filename
16
+ file_contents = file.read_text()
17
+ return (file_contents, json.loads(file_contents))
18
+
19
+ @pytest.mark.parametrize(("filename", "kwargs"), params)
20
+ def test_roundtrip(filename:str, kwargs:dict):
21
+ file_str, file_dict = read_file(filename)
22
+ formatted = json.dumps(file_dict, cls=Encoder, **kwargs)
23
+ assert formatted == file_str
24
+
25
+ @pytest.mark.parametrize(("filename", "kwargs"), params)
26
+ def test_negative_roundtrip(filename:str, kwargs:dict):
27
+ file_str, file_dict = read_file(filename)
28
+ formatted = json.dumps(file_dict)
29
+ assert formatted != file_str
30
+
31
+ @pytest.mark.parametrize(("filename", "kwargs"), params)
32
+ def test_dump(filename:str, kwargs:dict, tmp_path:Path):
33
+ file_str, file_dict = read_file(filename)
34
+ file = tmp_path / "test.json"
35
+ with open(file, "w") as f:
36
+ json.dump(file_dict, f, cls=Encoder, **kwargs)
37
+ assert file.read_text() == file_str
@@ -0,0 +1,44 @@
1
+ import json as builtin_json
2
+ from pathlib import Path
3
+
4
+ import pytest
5
+
6
+ import fracturedjson as json
7
+
8
+ params = [
9
+ ("default_settings.json", {}),
10
+ ("line_len_100.json", {"line_length":100}),
11
+ ("indent_2.json", {"indent":2}),
12
+ ]
13
+
14
+ def read_file(filename) -> tuple[str, dict]:
15
+ file = Path(__file__).parent / filename
16
+ file_contents = file.read_text()
17
+ return (file_contents, builtin_json.loads(file_contents))
18
+
19
+ @pytest.mark.parametrize(("filename", "kwargs"), params)
20
+ def test_dumps(filename:str, kwargs:dict):
21
+ file_str, file_dict = read_file(filename)
22
+ formatted = json.dumps(file_dict, **kwargs)
23
+ assert formatted == file_str
24
+
25
+ @pytest.mark.parametrize(("filename", "kwargs"), params)
26
+ def test_dump(filename:str, kwargs:dict, tmp_path:Path):
27
+ file_str, file_dict = read_file(filename)
28
+ file = tmp_path / "test.json"
29
+ with open(file, "w") as f:
30
+ json.dump(file_dict, f, **kwargs)
31
+ assert file.read_text() == file_str
32
+
33
+ @pytest.mark.parametrize(("filename", "kwargs"), params)
34
+ def test_load(filename:str, kwargs:dict, tmp_path:Path):
35
+ file_str, file_dict = read_file(filename)
36
+ with open(Path(__file__).parent / filename) as f:
37
+ data = json.load(f)
38
+ assert file_dict == data
39
+
40
+ @pytest.mark.parametrize(("filename", "kwargs"), params)
41
+ def test_loads(filename:str, kwargs:dict, tmp_path:Path):
42
+ file_str, file_dict = read_file(filename)
43
+ data = json.loads(file_str)
44
+ assert file_dict == data
@@ -0,0 +1,199 @@
1
+ version = 1
2
+ revision = 2
3
+ requires-python = ">=3.9"
4
+ resolution-markers = [
5
+ "python_full_version >= '3.10'",
6
+ "python_full_version < '3.10'",
7
+ ]
8
+
9
+ [[package]]
10
+ name = "colorama"
11
+ version = "0.4.6"
12
+ source = { registry = "https://pypi.org/simple" }
13
+ sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
14
+ wheels = [
15
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
16
+ ]
17
+
18
+ [[package]]
19
+ name = "exceptiongroup"
20
+ version = "1.3.1"
21
+ source = { registry = "https://pypi.org/simple" }
22
+ dependencies = [
23
+ { name = "typing-extensions", marker = "python_full_version < '3.13'" },
24
+ ]
25
+ sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
26
+ wheels = [
27
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
28
+ ]
29
+
30
+ [[package]]
31
+ name = "iniconfig"
32
+ version = "2.1.0"
33
+ source = { registry = "https://pypi.org/simple" }
34
+ resolution-markers = [
35
+ "python_full_version < '3.10'",
36
+ ]
37
+ sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" }
38
+ wheels = [
39
+ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" },
40
+ ]
41
+
42
+ [[package]]
43
+ name = "iniconfig"
44
+ version = "2.3.0"
45
+ source = { registry = "https://pypi.org/simple" }
46
+ resolution-markers = [
47
+ "python_full_version >= '3.10'",
48
+ ]
49
+ sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
50
+ wheels = [
51
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
52
+ ]
53
+
54
+ [[package]]
55
+ name = "packaging"
56
+ version = "26.0"
57
+ source = { registry = "https://pypi.org/simple" }
58
+ sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" }
59
+ wheels = [
60
+ { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" },
61
+ ]
62
+
63
+ [[package]]
64
+ name = "pluggy"
65
+ version = "1.6.0"
66
+ source = { registry = "https://pypi.org/simple" }
67
+ sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
68
+ wheels = [
69
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
70
+ ]
71
+
72
+ [[package]]
73
+ name = "pyfracturedjson"
74
+ source = { editable = "." }
75
+
76
+ [package.dev-dependencies]
77
+ dev = [
78
+ { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
79
+ { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
80
+ ]
81
+
82
+ [package.metadata]
83
+
84
+ [package.metadata.requires-dev]
85
+ dev = [{ name = "pytest", specifier = ">=8.3.5" }]
86
+
87
+ [[package]]
88
+ name = "pygments"
89
+ version = "2.19.2"
90
+ source = { registry = "https://pypi.org/simple" }
91
+ sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
92
+ wheels = [
93
+ { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
94
+ ]
95
+
96
+ [[package]]
97
+ name = "pytest"
98
+ version = "8.4.2"
99
+ source = { registry = "https://pypi.org/simple" }
100
+ resolution-markers = [
101
+ "python_full_version < '3.10'",
102
+ ]
103
+ dependencies = [
104
+ { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" },
105
+ { name = "exceptiongroup", marker = "python_full_version < '3.10'" },
106
+ { name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
107
+ { name = "packaging", marker = "python_full_version < '3.10'" },
108
+ { name = "pluggy", marker = "python_full_version < '3.10'" },
109
+ { name = "pygments", marker = "python_full_version < '3.10'" },
110
+ { name = "tomli", marker = "python_full_version < '3.10'" },
111
+ ]
112
+ sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" }
113
+ wheels = [
114
+ { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" },
115
+ ]
116
+
117
+ [[package]]
118
+ name = "pytest"
119
+ version = "9.0.2"
120
+ source = { registry = "https://pypi.org/simple" }
121
+ resolution-markers = [
122
+ "python_full_version >= '3.10'",
123
+ ]
124
+ dependencies = [
125
+ { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" },
126
+ { name = "exceptiongroup", marker = "python_full_version == '3.10.*'" },
127
+ { name = "iniconfig", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
128
+ { name = "packaging", marker = "python_full_version >= '3.10'" },
129
+ { name = "pluggy", marker = "python_full_version >= '3.10'" },
130
+ { name = "pygments", marker = "python_full_version >= '3.10'" },
131
+ { name = "tomli", marker = "python_full_version == '3.10.*'" },
132
+ ]
133
+ sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" }
134
+ wheels = [
135
+ { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" },
136
+ ]
137
+
138
+ [[package]]
139
+ name = "tomli"
140
+ version = "2.4.0"
141
+ source = { registry = "https://pypi.org/simple" }
142
+ sdist = { url = "https://files.pythonhosted.org/packages/82/30/31573e9457673ab10aa432461bee537ce6cef177667deca369efb79df071/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", size = 17477, upload-time = "2026-01-11T11:22:38.165Z" }
143
+ wheels = [
144
+ { url = "https://files.pythonhosted.org/packages/3c/d9/3dc2289e1f3b32eb19b9785b6a006b28ee99acb37d1d47f78d4c10e28bf8/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867", size = 153663, upload-time = "2026-01-11T11:21:45.27Z" },
145
+ { url = "https://files.pythonhosted.org/packages/51/32/ef9f6845e6b9ca392cd3f64f9ec185cc6f09f0a2df3db08cbe8809d1d435/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9", size = 148469, upload-time = "2026-01-11T11:21:46.873Z" },
146
+ { url = "https://files.pythonhosted.org/packages/d6/c2/506e44cce89a8b1b1e047d64bd495c22c9f71f21e05f380f1a950dd9c217/tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95", size = 236039, upload-time = "2026-01-11T11:21:48.503Z" },
147
+ { url = "https://files.pythonhosted.org/packages/b3/40/e1b65986dbc861b7e986e8ec394598187fa8aee85b1650b01dd925ca0be8/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76", size = 243007, upload-time = "2026-01-11T11:21:49.456Z" },
148
+ { url = "https://files.pythonhosted.org/packages/9c/6f/6e39ce66b58a5b7ae572a0f4352ff40c71e8573633deda43f6a379d56b3e/tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d", size = 240875, upload-time = "2026-01-11T11:21:50.755Z" },
149
+ { url = "https://files.pythonhosted.org/packages/aa/ad/cb089cb190487caa80204d503c7fd0f4d443f90b95cf4ef5cf5aa0f439b0/tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576", size = 246271, upload-time = "2026-01-11T11:21:51.81Z" },
150
+ { url = "https://files.pythonhosted.org/packages/0b/63/69125220e47fd7a3a27fd0de0c6398c89432fec41bc739823bcc66506af6/tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a", size = 96770, upload-time = "2026-01-11T11:21:52.647Z" },
151
+ { url = "https://files.pythonhosted.org/packages/1e/0d/a22bb6c83f83386b0008425a6cd1fa1c14b5f3dd4bad05e98cf3dbbf4a64/tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa", size = 107626, upload-time = "2026-01-11T11:21:53.459Z" },
152
+ { url = "https://files.pythonhosted.org/packages/2f/6d/77be674a3485e75cacbf2ddba2b146911477bd887dda9d8c9dfb2f15e871/tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614", size = 94842, upload-time = "2026-01-11T11:21:54.831Z" },
153
+ { url = "https://files.pythonhosted.org/packages/3c/43/7389a1869f2f26dba52404e1ef13b4784b6b37dac93bac53457e3ff24ca3/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", size = 154894, upload-time = "2026-01-11T11:21:56.07Z" },
154
+ { url = "https://files.pythonhosted.org/packages/e9/05/2f9bf110b5294132b2edf13fe6ca6ae456204f3d749f623307cbb7a946f2/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", size = 149053, upload-time = "2026-01-11T11:21:57.467Z" },
155
+ { url = "https://files.pythonhosted.org/packages/e8/41/1eda3ca1abc6f6154a8db4d714a4d35c4ad90adc0bcf700657291593fbf3/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", size = 243481, upload-time = "2026-01-11T11:21:58.661Z" },
156
+ { url = "https://files.pythonhosted.org/packages/d2/6d/02ff5ab6c8868b41e7d4b987ce2b5f6a51d3335a70aa144edd999e055a01/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", size = 251720, upload-time = "2026-01-11T11:22:00.178Z" },
157
+ { url = "https://files.pythonhosted.org/packages/7b/57/0405c59a909c45d5b6f146107c6d997825aa87568b042042f7a9c0afed34/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", size = 247014, upload-time = "2026-01-11T11:22:01.238Z" },
158
+ { url = "https://files.pythonhosted.org/packages/2c/0e/2e37568edd944b4165735687cbaf2fe3648129e440c26d02223672ee0630/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", size = 251820, upload-time = "2026-01-11T11:22:02.727Z" },
159
+ { url = "https://files.pythonhosted.org/packages/5a/1c/ee3b707fdac82aeeb92d1a113f803cf6d0f37bdca0849cb489553e1f417a/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", size = 97712, upload-time = "2026-01-11T11:22:03.777Z" },
160
+ { url = "https://files.pythonhosted.org/packages/69/13/c07a9177d0b3bab7913299b9278845fc6eaaca14a02667c6be0b0a2270c8/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", size = 108296, upload-time = "2026-01-11T11:22:04.86Z" },
161
+ { url = "https://files.pythonhosted.org/packages/18/27/e267a60bbeeee343bcc279bb9e8fbed0cbe224bc7b2a3dc2975f22809a09/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", size = 94553, upload-time = "2026-01-11T11:22:05.854Z" },
162
+ { url = "https://files.pythonhosted.org/packages/34/91/7f65f9809f2936e1f4ce6268ae1903074563603b2a2bd969ebbda802744f/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0", size = 154915, upload-time = "2026-01-11T11:22:06.703Z" },
163
+ { url = "https://files.pythonhosted.org/packages/20/aa/64dd73a5a849c2e8f216b755599c511badde80e91e9bc2271baa7b2cdbb1/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e", size = 149038, upload-time = "2026-01-11T11:22:07.56Z" },
164
+ { url = "https://files.pythonhosted.org/packages/9e/8a/6d38870bd3d52c8d1505ce054469a73f73a0fe62c0eaf5dddf61447e32fa/tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4", size = 242245, upload-time = "2026-01-11T11:22:08.344Z" },
165
+ { url = "https://files.pythonhosted.org/packages/59/bb/8002fadefb64ab2669e5b977df3f5e444febea60e717e755b38bb7c41029/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e", size = 250335, upload-time = "2026-01-11T11:22:09.951Z" },
166
+ { url = "https://files.pythonhosted.org/packages/a5/3d/4cdb6f791682b2ea916af2de96121b3cb1284d7c203d97d92d6003e91c8d/tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c", size = 245962, upload-time = "2026-01-11T11:22:11.27Z" },
167
+ { url = "https://files.pythonhosted.org/packages/f2/4a/5f25789f9a460bd858ba9756ff52d0830d825b458e13f754952dd15fb7bb/tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f", size = 250396, upload-time = "2026-01-11T11:22:12.325Z" },
168
+ { url = "https://files.pythonhosted.org/packages/aa/2f/b73a36fea58dfa08e8b3a268750e6853a6aac2a349241a905ebd86f3047a/tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86", size = 97530, upload-time = "2026-01-11T11:22:13.865Z" },
169
+ { url = "https://files.pythonhosted.org/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87", size = 108227, upload-time = "2026-01-11T11:22:15.224Z" },
170
+ { url = "https://files.pythonhosted.org/packages/22/c3/b386b832f209fee8073c8138ec50f27b4460db2fdae9ffe022df89a57f9b/tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132", size = 94748, upload-time = "2026-01-11T11:22:16.009Z" },
171
+ { url = "https://files.pythonhosted.org/packages/f3/c4/84047a97eb1004418bc10bdbcfebda209fca6338002eba2dc27cc6d13563/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6", size = 154725, upload-time = "2026-01-11T11:22:17.269Z" },
172
+ { url = "https://files.pythonhosted.org/packages/a8/5d/d39038e646060b9d76274078cddf146ced86dc2b9e8bbf737ad5983609a0/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc", size = 148901, upload-time = "2026-01-11T11:22:18.287Z" },
173
+ { url = "https://files.pythonhosted.org/packages/73/e5/383be1724cb30f4ce44983d249645684a48c435e1cd4f8b5cded8a816d3c/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66", size = 243375, upload-time = "2026-01-11T11:22:19.154Z" },
174
+ { url = "https://files.pythonhosted.org/packages/31/f0/bea80c17971c8d16d3cc109dc3585b0f2ce1036b5f4a8a183789023574f2/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d", size = 250639, upload-time = "2026-01-11T11:22:20.168Z" },
175
+ { url = "https://files.pythonhosted.org/packages/2c/8f/2853c36abbb7608e3f945d8a74e32ed3a74ee3a1f468f1ffc7d1cb3abba6/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702", size = 246897, upload-time = "2026-01-11T11:22:21.544Z" },
176
+ { url = "https://files.pythonhosted.org/packages/49/f0/6c05e3196ed5337b9fe7ea003e95fd3819a840b7a0f2bf5a408ef1dad8ed/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8", size = 254697, upload-time = "2026-01-11T11:22:23.058Z" },
177
+ { url = "https://files.pythonhosted.org/packages/f3/f5/2922ef29c9f2951883525def7429967fc4d8208494e5ab524234f06b688b/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776", size = 98567, upload-time = "2026-01-11T11:22:24.033Z" },
178
+ { url = "https://files.pythonhosted.org/packages/7b/31/22b52e2e06dd2a5fdbc3ee73226d763b184ff21fc24e20316a44ccc4d96b/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475", size = 108556, upload-time = "2026-01-11T11:22:25.378Z" },
179
+ { url = "https://files.pythonhosted.org/packages/48/3d/5058dff3255a3d01b705413f64f4306a141a8fd7a251e5a495e3f192a998/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2", size = 96014, upload-time = "2026-01-11T11:22:26.138Z" },
180
+ { url = "https://files.pythonhosted.org/packages/b8/4e/75dab8586e268424202d3a1997ef6014919c941b50642a1682df43204c22/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9", size = 163339, upload-time = "2026-01-11T11:22:27.143Z" },
181
+ { url = "https://files.pythonhosted.org/packages/06/e3/b904d9ab1016829a776d97f163f183a48be6a4deb87304d1e0116a349519/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0", size = 159490, upload-time = "2026-01-11T11:22:28.399Z" },
182
+ { url = "https://files.pythonhosted.org/packages/e3/5a/fc3622c8b1ad823e8ea98a35e3c632ee316d48f66f80f9708ceb4f2a0322/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df", size = 269398, upload-time = "2026-01-11T11:22:29.345Z" },
183
+ { url = "https://files.pythonhosted.org/packages/fd/33/62bd6152c8bdd4c305ad9faca48f51d3acb2df1f8791b1477d46ff86e7f8/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d", size = 276515, upload-time = "2026-01-11T11:22:30.327Z" },
184
+ { url = "https://files.pythonhosted.org/packages/4b/ff/ae53619499f5235ee4211e62a8d7982ba9e439a0fb4f2f351a93d67c1dd2/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f", size = 273806, upload-time = "2026-01-11T11:22:32.56Z" },
185
+ { url = "https://files.pythonhosted.org/packages/47/71/cbca7787fa68d4d0a9f7072821980b39fbb1b6faeb5f5cf02f4a5559fa28/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b", size = 281340, upload-time = "2026-01-11T11:22:33.505Z" },
186
+ { url = "https://files.pythonhosted.org/packages/f5/00/d595c120963ad42474cf6ee7771ad0d0e8a49d0f01e29576ee9195d9ecdf/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087", size = 108106, upload-time = "2026-01-11T11:22:34.451Z" },
187
+ { url = "https://files.pythonhosted.org/packages/de/69/9aa0c6a505c2f80e519b43764f8b4ba93b5a0bbd2d9a9de6e2b24271b9a5/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd", size = 120504, upload-time = "2026-01-11T11:22:35.764Z" },
188
+ { url = "https://files.pythonhosted.org/packages/b3/9f/f1668c281c58cfae01482f7114a4b88d345e4c140386241a1a24dcc9e7bc/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4", size = 99561, upload-time = "2026-01-11T11:22:36.624Z" },
189
+ { url = "https://files.pythonhosted.org/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", size = 14477, upload-time = "2026-01-11T11:22:37.446Z" },
190
+ ]
191
+
192
+ [[package]]
193
+ name = "typing-extensions"
194
+ version = "4.15.0"
195
+ source = { registry = "https://pypi.org/simple" }
196
+ sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
197
+ wheels = [
198
+ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
199
+ ]
@@ -1,45 +0,0 @@
1
- import json
2
- from typing import Callable
3
-
4
- import fractured_json_rust_wrapper
5
-
6
-
7
- class Encoder(json.encoder.JSONEncoder):
8
- def __init__(
9
- self,
10
- *,
11
- skipkeys: bool = False,
12
- ensure_ascii: bool = True,
13
- check_circular: bool = True,
14
- allow_nan: bool = True,
15
- sort_keys: bool = False,
16
- indent = 4,
17
- separators: tuple[str, str] | None = None,
18
- default: Callable | None = None,
19
- **kwargs
20
- ):
21
- super().__init__(
22
- skipkeys=skipkeys,
23
- ensure_ascii=ensure_ascii,
24
- check_circular=check_circular,
25
- allow_nan=allow_nan,
26
- sort_keys=sort_keys,
27
- indent=indent,
28
- separators=separators,
29
- default=default
30
- )
31
-
32
- if indent is None:
33
- indent = 4
34
- self._indent = indent
35
- self.line_length = kwargs.get("line_length", 120)
36
-
37
-
38
- def encode(self, o) -> str:
39
- unformatted = json.dumps(o)
40
- formatted = fractured_json_rust_wrapper.reformat_string(
41
- unformatted,
42
- indent=self._indent,
43
- line_length=self.line_length
44
- )
45
- return formatted
@@ -1,10 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: pyfracturedjson
3
- Version: 0.1.4
4
- Classifier: Programming Language :: Rust
5
- Classifier: Programming Language :: Python :: Implementation :: CPython
6
- Classifier: Programming Language :: Python :: Implementation :: PyPy
7
- Summary: A compact yet readable JSON formatter
8
- Keywords: json,formatter,fracturedjson,compact,readable
9
- Requires-Python: >=3.8
10
- Project-URL: Repository, https://github.com/g-b-f/pyFracturedJSON
@@ -1,7 +0,0 @@
1
- version = 1
2
- revision = 3
3
- requires-python = ">=3.8"
4
-
5
- [[package]]
6
- name = "pyfracturedjson"
7
- source = { editable = "." }