lokate 1.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.
- lokate-1.0.0/.gitignore +153 -0
- lokate-1.0.0/PKG-INFO +120 -0
- lokate-1.0.0/README.md +108 -0
- lokate-1.0.0/lokate/__init__.py +20 -0
- lokate-1.0.0/lokate/api/project.json +120 -0
- lokate-1.0.0/lokate/api/schema.graphql +224 -0
- lokate-1.0.0/lokate/api/schema.py +687 -0
- lokate-1.0.0/lokate/arkitekt.py +65 -0
- lokate-1.0.0/lokate/lokate.py +112 -0
- lokate-1.0.0/lokate/py.typed +0 -0
- lokate-1.0.0/lokate/rath.py +41 -0
- lokate-1.0.0/pyproject.toml +106 -0
lokate-1.0.0/.gitignore
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
**/__pycache__
|
|
4
|
+
*.py[cod]
|
|
5
|
+
*$py.class
|
|
6
|
+
*.pyc
|
|
7
|
+
|
|
8
|
+
# C extensions
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# Distribution / packaging
|
|
12
|
+
.Python
|
|
13
|
+
build/
|
|
14
|
+
develop-eggs/
|
|
15
|
+
dist/
|
|
16
|
+
downloads/
|
|
17
|
+
eggs/
|
|
18
|
+
.eggs/
|
|
19
|
+
lib/
|
|
20
|
+
lib64/
|
|
21
|
+
parts/
|
|
22
|
+
sdist/
|
|
23
|
+
var/
|
|
24
|
+
wheels/
|
|
25
|
+
pip-wheel-metadata/
|
|
26
|
+
share/python-wheels/
|
|
27
|
+
*.egg-info/
|
|
28
|
+
.installed.cfg
|
|
29
|
+
*.egg
|
|
30
|
+
MANIFEST
|
|
31
|
+
|
|
32
|
+
# PyInstaller
|
|
33
|
+
# Usually these files are written by a python script from a template
|
|
34
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
35
|
+
*.manifest
|
|
36
|
+
*.spec
|
|
37
|
+
|
|
38
|
+
# Installer logs
|
|
39
|
+
pip-log.txt
|
|
40
|
+
pip-delete-this-directory.txt
|
|
41
|
+
|
|
42
|
+
# Unit test / coverage reports
|
|
43
|
+
htmlcov/
|
|
44
|
+
.tox/
|
|
45
|
+
.nox/
|
|
46
|
+
.coverage
|
|
47
|
+
.coverage.*
|
|
48
|
+
.cache
|
|
49
|
+
nosetests.xml
|
|
50
|
+
coverage.xml
|
|
51
|
+
*.cover
|
|
52
|
+
*.py,cover
|
|
53
|
+
.hypothesis/
|
|
54
|
+
.pytest_cache/
|
|
55
|
+
cover/
|
|
56
|
+
|
|
57
|
+
# Translations
|
|
58
|
+
*.mo
|
|
59
|
+
*.pot
|
|
60
|
+
|
|
61
|
+
# Django stuff:
|
|
62
|
+
*.log
|
|
63
|
+
local_settings.py
|
|
64
|
+
db.sqlite3
|
|
65
|
+
db.sqlite3-journal
|
|
66
|
+
|
|
67
|
+
# Flask stuff:
|
|
68
|
+
instance/
|
|
69
|
+
.webassets-cache
|
|
70
|
+
|
|
71
|
+
# Scrapy stuff:
|
|
72
|
+
.scrapy
|
|
73
|
+
|
|
74
|
+
# Sphinx documentation
|
|
75
|
+
docs/_build/
|
|
76
|
+
|
|
77
|
+
# PyBuilder
|
|
78
|
+
.pybuilder/
|
|
79
|
+
target/
|
|
80
|
+
|
|
81
|
+
# Jupyter Notebook
|
|
82
|
+
.ipynb_checkpoints
|
|
83
|
+
|
|
84
|
+
# IPython
|
|
85
|
+
profile_default/
|
|
86
|
+
ipython_config.py
|
|
87
|
+
|
|
88
|
+
# pyenv
|
|
89
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
90
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
91
|
+
# .python-version
|
|
92
|
+
|
|
93
|
+
# pipenv
|
|
94
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
95
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
96
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
97
|
+
# install all needed dependencies.
|
|
98
|
+
#Pipfile.lock
|
|
99
|
+
|
|
100
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
101
|
+
__pypackages__/
|
|
102
|
+
|
|
103
|
+
# Celery stuff
|
|
104
|
+
celerybeat-schedule
|
|
105
|
+
celerybeat.pid
|
|
106
|
+
|
|
107
|
+
# SageMath parsed files
|
|
108
|
+
*.sage.py
|
|
109
|
+
|
|
110
|
+
# Environments
|
|
111
|
+
.env
|
|
112
|
+
.venv
|
|
113
|
+
env/
|
|
114
|
+
venv/
|
|
115
|
+
ENV/
|
|
116
|
+
env.bak/
|
|
117
|
+
venv.bak/
|
|
118
|
+
|
|
119
|
+
# Spyder project settings
|
|
120
|
+
.spyderproject
|
|
121
|
+
.spyproject
|
|
122
|
+
|
|
123
|
+
# Rope project settings
|
|
124
|
+
.ropeproject
|
|
125
|
+
|
|
126
|
+
# mkdocs documentation
|
|
127
|
+
/site
|
|
128
|
+
|
|
129
|
+
# mypy
|
|
130
|
+
.mypy_cache/
|
|
131
|
+
.dmypy.json
|
|
132
|
+
dmypy.json
|
|
133
|
+
|
|
134
|
+
# Pyre type checker
|
|
135
|
+
.pyre/
|
|
136
|
+
|
|
137
|
+
# pytype static type analyzer
|
|
138
|
+
.pytype/
|
|
139
|
+
|
|
140
|
+
# Cython debug symbols
|
|
141
|
+
cython_debug/
|
|
142
|
+
|
|
143
|
+
# static files generated from Django application using `collectstatic`
|
|
144
|
+
media
|
|
145
|
+
export
|
|
146
|
+
static_collected
|
|
147
|
+
data
|
|
148
|
+
|
|
149
|
+
*.token.temp
|
|
150
|
+
*.fakts.yaml
|
|
151
|
+
fakts.yaml
|
|
152
|
+
# Local-source override for the integration stack (see tests/conftest.py)
|
|
153
|
+
tests/integration/docker-compose.local.yml
|
lokate-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: lokate
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: The python client for lokate, the arkitekt backup of a phone's location timeline
|
|
5
|
+
Author-email: jhnnsrs <jhnnsrs@gmail.com>
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: aiohttp<4,>=3.9.5
|
|
8
|
+
Requires-Dist: koil>=1.0.0
|
|
9
|
+
Requires-Dist: rath>=4.1.1
|
|
10
|
+
Requires-Dist: websockets>=15.0.1
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# lokate
|
|
14
|
+
|
|
15
|
+
The python client for [lokate](https://github.com/arkitektio/lokate-server), the
|
|
16
|
+
[Arkitekt](https://arkitekt.live) backup of a phone's location timeline: points,
|
|
17
|
+
visits, trips and places, uploaded idempotently and restorable page by page.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
pip install lokate
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
Every lokate operation is a method of the `Lokate` client, in a blocking and an
|
|
28
|
+
`a`-prefixed async flavour. The server keys everything by the token's user and
|
|
29
|
+
writes by its device (`client_device` claim).
|
|
30
|
+
|
|
31
|
+
### In an arkitekt app
|
|
32
|
+
|
|
33
|
+
The client is injected by annotation. Add the service to your app and ask for
|
|
34
|
+
`lokate: Lokate`:
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from arkitekt import App, run
|
|
38
|
+
from lokate import Lokate, lokate_service
|
|
39
|
+
|
|
40
|
+
app = App("where-was-i", "0.1.0", services=[lokate_service])
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@app.action
|
|
44
|
+
async def places_i_keep(lokate: Lokate) -> list[str]:
|
|
45
|
+
"""The names of my places, from the server copy."""
|
|
46
|
+
names, cursor = [], None
|
|
47
|
+
while True:
|
|
48
|
+
page = await lokate.aget_changes(cursor=cursor)
|
|
49
|
+
names += [place.name for place in page.places]
|
|
50
|
+
cursor = page.next_cursor
|
|
51
|
+
if not page.has_more:
|
|
52
|
+
return names
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
if __name__ == "__main__":
|
|
56
|
+
run(app)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### From a script
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from arkitekt import easy
|
|
63
|
+
from lokate import lokate_service
|
|
64
|
+
|
|
65
|
+
with easy("my-script", lokate_service) as lokate:
|
|
66
|
+
state = lokate.get_sync_state()
|
|
67
|
+
print(state.point_count, state.last_point_ts)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Standalone
|
|
71
|
+
|
|
72
|
+
Without arkitekt, build the client over a rath link of your own:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
import datetime
|
|
76
|
+
from lokate import Lokate
|
|
77
|
+
from lokate.api.schema import PointInput
|
|
78
|
+
from lokate.rath import LokateRath
|
|
79
|
+
|
|
80
|
+
lokate = Lokate(rath=LokateRath(link=...))
|
|
81
|
+
|
|
82
|
+
with lokate:
|
|
83
|
+
result = lokate.upload_points([
|
|
84
|
+
PointInput(client_id="fix-1", ts=datetime.datetime.now(datetime.UTC), lat=48.2, lon=16.37),
|
|
85
|
+
])
|
|
86
|
+
print(result.accepted, result.duplicates)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
What the protocol guarantees:
|
|
90
|
+
|
|
91
|
+
- **Every write can be retried.** `upload_points` counts points it already has as
|
|
92
|
+
`duplicates`. `replace_segments(from_=...)` and `merge_places` leave unchanged
|
|
93
|
+
rows alone.
|
|
94
|
+
- **A point is keyed by `(device, client_id, ts)`.** Never send one `client_id`
|
|
95
|
+
with two different timestamps.
|
|
96
|
+
- **Batches hold at most 1000 rows**, and so does a `get_changes` page.
|
|
97
|
+
- **Leave defaulted arguments out** rather than passing `None`. For `set_retention`,
|
|
98
|
+
though, `days=None` is meaningful: it means keep forever.
|
|
99
|
+
|
|
100
|
+
## Development
|
|
101
|
+
|
|
102
|
+
The generated API (`lokate/api/schema.py`) comes from the checked-in
|
|
103
|
+
`schema.graphql` and the documents in `graphql/`. The config comment in
|
|
104
|
+
`graphql.config.yaml` has the command that refreshes the schema from a
|
|
105
|
+
lokate-server checkout. Then regenerate with turms:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
uvx --with 'graphql-core<3.3' --with-editable . --from <path to turms> turms gen
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```sh
|
|
112
|
+
uv run pytest -m "not integration" # no server needed
|
|
113
|
+
uv run pytest -m integration # a real lokate + postgres/PostGIS via dokker
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Until the server's first image is published, the integration suite needs a
|
|
117
|
+
gitignored `tests/integration/docker-compose.local.yml` that builds
|
|
118
|
+
`jhnnsrs/lokate` from a local lokate-server checkout.
|
|
119
|
+
|
|
120
|
+
See [RELEASING.md](RELEASING.md) for how versions are cut.
|
lokate-1.0.0/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# lokate
|
|
2
|
+
|
|
3
|
+
The python client for [lokate](https://github.com/arkitektio/lokate-server), the
|
|
4
|
+
[Arkitekt](https://arkitekt.live) backup of a phone's location timeline: points,
|
|
5
|
+
visits, trips and places, uploaded idempotently and restorable page by page.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pip install lokate
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Every lokate operation is a method of the `Lokate` client, in a blocking and an
|
|
16
|
+
`a`-prefixed async flavour. The server keys everything by the token's user and
|
|
17
|
+
writes by its device (`client_device` claim).
|
|
18
|
+
|
|
19
|
+
### In an arkitekt app
|
|
20
|
+
|
|
21
|
+
The client is injected by annotation. Add the service to your app and ask for
|
|
22
|
+
`lokate: Lokate`:
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from arkitekt import App, run
|
|
26
|
+
from lokate import Lokate, lokate_service
|
|
27
|
+
|
|
28
|
+
app = App("where-was-i", "0.1.0", services=[lokate_service])
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@app.action
|
|
32
|
+
async def places_i_keep(lokate: Lokate) -> list[str]:
|
|
33
|
+
"""The names of my places, from the server copy."""
|
|
34
|
+
names, cursor = [], None
|
|
35
|
+
while True:
|
|
36
|
+
page = await lokate.aget_changes(cursor=cursor)
|
|
37
|
+
names += [place.name for place in page.places]
|
|
38
|
+
cursor = page.next_cursor
|
|
39
|
+
if not page.has_more:
|
|
40
|
+
return names
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
if __name__ == "__main__":
|
|
44
|
+
run(app)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### From a script
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from arkitekt import easy
|
|
51
|
+
from lokate import lokate_service
|
|
52
|
+
|
|
53
|
+
with easy("my-script", lokate_service) as lokate:
|
|
54
|
+
state = lokate.get_sync_state()
|
|
55
|
+
print(state.point_count, state.last_point_ts)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Standalone
|
|
59
|
+
|
|
60
|
+
Without arkitekt, build the client over a rath link of your own:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
import datetime
|
|
64
|
+
from lokate import Lokate
|
|
65
|
+
from lokate.api.schema import PointInput
|
|
66
|
+
from lokate.rath import LokateRath
|
|
67
|
+
|
|
68
|
+
lokate = Lokate(rath=LokateRath(link=...))
|
|
69
|
+
|
|
70
|
+
with lokate:
|
|
71
|
+
result = lokate.upload_points([
|
|
72
|
+
PointInput(client_id="fix-1", ts=datetime.datetime.now(datetime.UTC), lat=48.2, lon=16.37),
|
|
73
|
+
])
|
|
74
|
+
print(result.accepted, result.duplicates)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
What the protocol guarantees:
|
|
78
|
+
|
|
79
|
+
- **Every write can be retried.** `upload_points` counts points it already has as
|
|
80
|
+
`duplicates`. `replace_segments(from_=...)` and `merge_places` leave unchanged
|
|
81
|
+
rows alone.
|
|
82
|
+
- **A point is keyed by `(device, client_id, ts)`.** Never send one `client_id`
|
|
83
|
+
with two different timestamps.
|
|
84
|
+
- **Batches hold at most 1000 rows**, and so does a `get_changes` page.
|
|
85
|
+
- **Leave defaulted arguments out** rather than passing `None`. For `set_retention`,
|
|
86
|
+
though, `days=None` is meaningful: it means keep forever.
|
|
87
|
+
|
|
88
|
+
## Development
|
|
89
|
+
|
|
90
|
+
The generated API (`lokate/api/schema.py`) comes from the checked-in
|
|
91
|
+
`schema.graphql` and the documents in `graphql/`. The config comment in
|
|
92
|
+
`graphql.config.yaml` has the command that refreshes the schema from a
|
|
93
|
+
lokate-server checkout. Then regenerate with turms:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
uvx --with 'graphql-core<3.3' --with-editable . --from <path to turms> turms gen
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
uv run pytest -m "not integration" # no server needed
|
|
101
|
+
uv run pytest -m integration # a real lokate + postgres/PostGIS via dokker
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Until the server's first image is published, the integration suite needs a
|
|
105
|
+
gitignored `tests/integration/docker-compose.local.yml` that builds
|
|
106
|
+
`jhnnsrs/lokate` from a local lokate-server checkout.
|
|
107
|
+
|
|
108
|
+
See [RELEASING.md](RELEASING.md) for how versions are cut.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from .lokate import Lokate
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
from .arkitekt import lokate as lokate_service
|
|
5
|
+
except ImportError as e:
|
|
6
|
+
# Only "rekuest is not installed" may pass silently. Anything else that fails
|
|
7
|
+
# to import here (a renamed query, a rekuest too old for what the module
|
|
8
|
+
# needs) is a bug, and hiding it makes this package's service vanish
|
|
9
|
+
# without a word. Whether it is installed is asked the plain way.
|
|
10
|
+
try:
|
|
11
|
+
import rekuest # noqa: F401 -- presence is the question
|
|
12
|
+
except ImportError:
|
|
13
|
+
pass
|
|
14
|
+
else:
|
|
15
|
+
raise e
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"Lokate",
|
|
19
|
+
"lokate_service",
|
|
20
|
+
]
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "schema.graphql",
|
|
3
|
+
"documents": "graphql/**/**.graphql",
|
|
4
|
+
"extensions": {
|
|
5
|
+
"turms": {
|
|
6
|
+
"domain": null,
|
|
7
|
+
"out_dir": "lokate/api",
|
|
8
|
+
"dump_configuration": true,
|
|
9
|
+
"configuration_name": "project.json",
|
|
10
|
+
"dump_schema": true,
|
|
11
|
+
"schema_name": "schema.graphql",
|
|
12
|
+
"generated_name": "schema.py",
|
|
13
|
+
"documents": "graphql/**/**.graphql",
|
|
14
|
+
"verbose": false,
|
|
15
|
+
"exit_on_error": true,
|
|
16
|
+
"allow_introspection": true,
|
|
17
|
+
"object_bases": [
|
|
18
|
+
"pydantic.BaseModel"
|
|
19
|
+
],
|
|
20
|
+
"interface_bases": null,
|
|
21
|
+
"always_resolve_interfaces": true,
|
|
22
|
+
"exclude_typenames": true,
|
|
23
|
+
"scalar_definitions": {
|
|
24
|
+
"uuid": "str",
|
|
25
|
+
"Callback": "str",
|
|
26
|
+
"Any": "typing.Any",
|
|
27
|
+
"JSON": "typing.Any",
|
|
28
|
+
"ID": "rath.scalars.ID",
|
|
29
|
+
"_Any": "typing.Any",
|
|
30
|
+
"ByteCount": "int"
|
|
31
|
+
},
|
|
32
|
+
"coercible_scalars": {},
|
|
33
|
+
"coercible_inputs": {},
|
|
34
|
+
"graphql_default_class": null,
|
|
35
|
+
"deprecated_class": null,
|
|
36
|
+
"document_field_metadata": true,
|
|
37
|
+
"unset_type_class": null,
|
|
38
|
+
"unset_instance": null,
|
|
39
|
+
"freeze": {
|
|
40
|
+
"enabled": true,
|
|
41
|
+
"types": [
|
|
42
|
+
"input",
|
|
43
|
+
"fragment",
|
|
44
|
+
"object"
|
|
45
|
+
],
|
|
46
|
+
"exclude": null,
|
|
47
|
+
"include": null,
|
|
48
|
+
"convert_list_to_tuple": true
|
|
49
|
+
},
|
|
50
|
+
"create_catchall": true,
|
|
51
|
+
"options": {
|
|
52
|
+
"enabled": true,
|
|
53
|
+
"extra": "forbid",
|
|
54
|
+
"populate_by_name": true,
|
|
55
|
+
"from_attributes": null,
|
|
56
|
+
"use_enum_values": true,
|
|
57
|
+
"validate_assignment": null,
|
|
58
|
+
"alias_mode": "split",
|
|
59
|
+
"types": [
|
|
60
|
+
"input"
|
|
61
|
+
],
|
|
62
|
+
"exclude": null,
|
|
63
|
+
"include": null
|
|
64
|
+
},
|
|
65
|
+
"skip_forwards": false,
|
|
66
|
+
"min_python_version": "3.10",
|
|
67
|
+
"type_annotation_style": "auto",
|
|
68
|
+
"external_modules": [],
|
|
69
|
+
"additional_bases": {},
|
|
70
|
+
"additional_config": {},
|
|
71
|
+
"force_plugin_order": true,
|
|
72
|
+
"omitted_document_rules": [],
|
|
73
|
+
"parsers": [],
|
|
74
|
+
"plugins": [
|
|
75
|
+
{
|
|
76
|
+
"type": "turms.plugins.enums.EnumsPlugin"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"type": "turms.plugins.inputs.InputsPlugin"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"type": "turms.plugins.fragments.FragmentsPlugin"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"type": "turms.plugins.operations.OperationsPlugin"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"type": "turms.plugins.client.ClientPlugin",
|
|
89
|
+
"client_class": "LokateApi",
|
|
90
|
+
"global_kwargs": [
|
|
91
|
+
{
|
|
92
|
+
"key": "task",
|
|
93
|
+
"type": "rath.task.TaskLike",
|
|
94
|
+
"description": "The task this call is made for; the ambient one by default."
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
"reserved_from": [
|
|
98
|
+
"lokate.lokate.Lokate"
|
|
99
|
+
],
|
|
100
|
+
"coercible_scalars": {
|
|
101
|
+
"ID": "rath.scalars.IDCoercible"
|
|
102
|
+
},
|
|
103
|
+
"expand_input_types": [
|
|
104
|
+
"input"
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
"processors": [],
|
|
109
|
+
"stylers": [
|
|
110
|
+
{
|
|
111
|
+
"type": "turms.stylers.default.DefaultStyler"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"type": "turms.stylers.appender.AppenderStyler",
|
|
115
|
+
"append_fragment": ""
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|