gramlab 0.1.0a1__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.
- gramlab-0.1.0a1/LICENSE +24 -0
- gramlab-0.1.0a1/LICENSES/BSL-1.0.txt +23 -0
- gramlab-0.1.0a1/NOTICE +40 -0
- gramlab-0.1.0a1/PKG-INFO +124 -0
- gramlab-0.1.0a1/README.md +97 -0
- gramlab-0.1.0a1/pyproject.toml +98 -0
- gramlab-0.1.0a1/pyproject.toml.orig +77 -0
- gramlab-0.1.0a1/src/gramlab/README.md +6 -0
- gramlab-0.1.0a1/src/gramlab/__init__.py +36 -0
- gramlab-0.1.0a1/src/gramlab/__main__.py +46 -0
- gramlab-0.1.0a1/src/gramlab/_android.py +714 -0
- gramlab-0.1.0a1/src/gramlab/_android_rich_buttons.py +946 -0
- gramlab-0.1.0a1/src/gramlab/_captures.py +123 -0
- gramlab-0.1.0a1/src/gramlab/_client_bridge_schema.py +477 -0
- gramlab-0.1.0a1/src/gramlab/_composer.py +79 -0
- gramlab-0.1.0a1/src/gramlab/_control.py +238 -0
- gramlab-0.1.0a1/src/gramlab/_document_metadata.py +314 -0
- gramlab-0.1.0a1/src/gramlab/_emoji_media.py +431 -0
- gramlab-0.1.0a1/src/gramlab/_emoji_text.py +66 -0
- gramlab-0.1.0a1/src/gramlab/_emulator.py +72 -0
- gramlab-0.1.0a1/src/gramlab/_interactions.py +185 -0
- gramlab-0.1.0a1/src/gramlab/_media_group_topology.py +303 -0
- gramlab-0.1.0a1/src/gramlab/_message_publication.py +220 -0
- gramlab-0.1.0a1/src/gramlab/_processes.py +247 -0
- gramlab-0.1.0a1/src/gramlab/_rich_button_journal.py +966 -0
- gramlab-0.1.0a1/src/gramlab/_rich_buttons.py +231 -0
- gramlab-0.1.0a1/src/gramlab/_rich_interactions.py +427 -0
- gramlab-0.1.0a1/src/gramlab/_run.py +143 -0
- gramlab-0.1.0a1/src/gramlab/bot_api.py +796 -0
- gramlab-0.1.0a1/src/gramlab/client_bridge.py +351 -0
- gramlab-0.1.0a1/src/gramlab/documents.py +97 -0
- gramlab-0.1.0a1/src/gramlab/entities.py +135 -0
- gramlab-0.1.0a1/src/gramlab/media.py +51 -0
- gramlab-0.1.0a1/src/gramlab/py.typed +0 -0
- gramlab-0.1.0a1/src/gramlab/reports.py +464 -0
- gramlab-0.1.0a1/src/gramlab/rich_messages.py +764 -0
- gramlab-0.1.0a1/src/gramlab/runner.py +292 -0
- gramlab-0.1.0a1/src/gramlab/runtime.py +298 -0
- gramlab-0.1.0a1/src/gramlab/scenario.py +520 -0
- gramlab-0.1.0a1/src/gramlab/scenario_flow.py +470 -0
- gramlab-0.1.0a1/src/gramlab/world.py +2056 -0
gramlab-0.1.0a1/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Scope: original GramLab work only. Separately licensed components are listed
|
|
2
|
+
in NOTICE and retain their own terms.
|
|
3
|
+
|
|
4
|
+
MIT License
|
|
5
|
+
|
|
6
|
+
Copyright (c) 2026 GramLab contributors
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
in the Software without restriction, including without limitation the rights
|
|
11
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
furnished to do so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
SOFTWARE.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Boost Software License - Version 1.0 - August 17th, 2003
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person or organization
|
|
4
|
+
obtaining a copy of the software and accompanying documentation covered by
|
|
5
|
+
this license (the "Software") to use, reproduce, display, distribute,
|
|
6
|
+
execute, and transmit the Software, and to prepare derivative works of the
|
|
7
|
+
Software, and to permit third-parties to whom the Software is furnished to
|
|
8
|
+
do so, all subject to the following:
|
|
9
|
+
|
|
10
|
+
The copyright notices in the Software and this entire statement, including
|
|
11
|
+
the above license grant, this restriction and the following disclaimer,
|
|
12
|
+
must be included in all copies of the Software, in whole or in part, and
|
|
13
|
+
all derivative works of the Software, unless such copies or derivative
|
|
14
|
+
works are solely in the form of machine-executable object code generated by
|
|
15
|
+
a source language processor.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
|
20
|
+
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
|
21
|
+
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
|
22
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
23
|
+
DEALINGS IN THE SOFTWARE.
|
gramlab-0.1.0a1/NOTICE
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
GramLab source and license notices
|
|
2
|
+
=================================
|
|
3
|
+
|
|
4
|
+
Original GramLab core, SDK, tools, documentation and original generated media
|
|
5
|
+
fixtures are licensed under MIT (LICENSE), except where a file or directory
|
|
6
|
+
identifies different terms below. The root MIT license does not relicense
|
|
7
|
+
third-party works or the Android-derived components.
|
|
8
|
+
|
|
9
|
+
Python package: MIT AND BSL-1.0
|
|
10
|
+
-----------------------------
|
|
11
|
+
src/gramlab/_emoji_text.py and src/gramlab/_document_metadata.py adapt TDLib
|
|
12
|
+
code/data under the Boost Software License 1.0. Each module retains the upstream
|
|
13
|
+
copyright and full license. LICENSES/BSL-1.0.txt supplies a separate license copy.
|
|
14
|
+
Document metadata reference fixtures retain their notice in
|
|
15
|
+
tests/fixtures/document_metadata/LICENSE_1_0.txt.
|
|
16
|
+
Exact upstream revisions, hashes and adaptation scope are recorded in:
|
|
17
|
+
docs/development/tdlib-emoji-provenance.json
|
|
18
|
+
docs/development/tdlib-document-metadata-provenance.json
|
|
19
|
+
|
|
20
|
+
Android-derived source: GPL-2.0-or-later
|
|
21
|
+
--------------------------------------
|
|
22
|
+
clients/android/patches/ contains patches to Telegram Android, including upstream
|
|
23
|
+
context. Android-derived Java/C++ test fixtures under tests/fixtures/ retain their
|
|
24
|
+
per-file GPL-2.0-or-later headers. These are separate from the Python package;
|
|
25
|
+
their license text is clients/android/patches/COPYING. Preserve the original
|
|
26
|
+
copyright notices and source/build information when redistributing them.
|
|
27
|
+
The patch README and docs/development/licensing.md explain this boundary.
|
|
28
|
+
The original renderer screenshot docs/assets/gramlab-preview.png includes upstream
|
|
29
|
+
interface artwork; its attribution and capture record are in the adjacent
|
|
30
|
+
gramlab-preview.md. It is not original MIT fixture artwork.
|
|
31
|
+
|
|
32
|
+
Acquired dependencies and application binaries
|
|
33
|
+
---------------------------------------------
|
|
34
|
+
External dependency sources and built Android applications are not included in
|
|
35
|
+
this source repository or Python package. They retain their own licenses.
|
|
36
|
+
The upstream lock is a provenance record, not a completed dependency/license
|
|
37
|
+
audit. An Android binary release requires its own corresponding-source,
|
|
38
|
+
dependency, asset and notice review. This repository offers no APK release.
|
|
39
|
+
|
|
40
|
+
GramLab is unofficial and is not affiliated with or endorsed by Telegram.
|
gramlab-0.1.0a1/PKG-INFO
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gramlab
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: Offline Telegram bot laboratory — experimental runtime foundation
|
|
5
|
+
Keywords: telegram,bot,testing,offline,android
|
|
6
|
+
Author: Ali Mohammadzadeh
|
|
7
|
+
License-Expression: MIT AND BSL-1.0
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
License-File: LICENSES/BSL-1.0.txt
|
|
10
|
+
License-File: NOTICE
|
|
11
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Software Development :: Testing
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Dist: pillow==12.3.0
|
|
20
|
+
Requires-Python: >=3.13, <3.14
|
|
21
|
+
Project-URL: Homepage, https://github.com/tholoo/GramLab
|
|
22
|
+
Project-URL: Documentation, https://github.com/tholoo/GramLab/tree/main/docs
|
|
23
|
+
Project-URL: Repository, https://github.com/tholoo/GramLab
|
|
24
|
+
Project-URL: Issues, https://github.com/tholoo/GramLab/issues
|
|
25
|
+
Project-URL: Changelog, https://github.com/tholoo/GramLab/blob/main/CHANGELOG.md
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# GramLab
|
|
29
|
+
|
|
30
|
+
<p align="center">
|
|
31
|
+
<img src="https://raw.githubusercontent.com/tholoo/GramLab/main/docs/assets/gramlab-preview.png" width="320" alt="An English GramLab conversation in the Telegram Android renderer, with rich text, buttons and glass effects." />
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
[Original Android capture](https://github.com/tholoo/GramLab/blob/main/docs/assets/gramlab-preview.md), with glass effects enabled.
|
|
35
|
+
|
|
36
|
+
Test Telegram bots locally and inspect their messages in the actual Telegram Android client.
|
|
37
|
+
No Telegram account or production token is needed.
|
|
38
|
+
|
|
39
|
+
**Experimental.** Text, callbacks, rich messages, photos, documents, albums and custom emoji have
|
|
40
|
+
tested original-Android workflows. Mini Apps, HTML parse modes, grouped-media edits, external
|
|
41
|
+
Telegram conformance and interactive Android mode remain unfinished.
|
|
42
|
+
See the
|
|
43
|
+
[compatibility matrix](https://github.com/tholoo/GramLab/blob/main/docs/compatibility/matrix.md)
|
|
44
|
+
for the supported scope.
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
GramLab currently requires Python 3.13 on a supported Linux host. Install the experimental
|
|
49
|
+
prerelease explicitly:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
uv add "gramlab==0.1.0a1"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The package includes the `gramlab` command and typed Python scenario interface. Android captures
|
|
56
|
+
require separately prepared local tooling and are not distributed in the Python package.
|
|
57
|
+
|
|
58
|
+
## Write a scenario
|
|
59
|
+
|
|
60
|
+
Create a user, talk to a real local bot, check its reply and capture the conversation:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from gramlab import Scenario
|
|
64
|
+
|
|
65
|
+
lab = Scenario.from_environment()
|
|
66
|
+
chat = lab.conversation(user=lab.user("Alex", language_code="en"), bot="echo")
|
|
67
|
+
chat.send("Hello!")
|
|
68
|
+
history = chat.wait_for_messages(2, timeout=5)
|
|
69
|
+
|
|
70
|
+
if history[1].text != "Echo: Hello!":
|
|
71
|
+
raise AssertionError("Unexpected bot reply")
|
|
72
|
+
chat.capture("hello", contains=["Echo: Hello!"])
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
This runs inside a scenario process. The
|
|
76
|
+
[English echo example](https://github.com/tholoo/GramLab/blob/main/examples/echo/hello.toml) uses
|
|
77
|
+
this exact [scenario](https://github.com/tholoo/GramLab/blob/main/examples/echo/hello.py),
|
|
78
|
+
with the bundled bot and manifest, and the runner supplies the environment. Simulation records the conversation state;
|
|
79
|
+
headless Android also captures the original client. Both modes produce a local HTML report.
|
|
80
|
+
The typed handles are additive: advanced scenarios can still use the raw JSON-shaped operations
|
|
81
|
+
on `Scenario`. The Python interface is still experimental.
|
|
82
|
+
|
|
83
|
+
## Try it
|
|
84
|
+
|
|
85
|
+
Start with the
|
|
86
|
+
[development environment](https://github.com/tholoo/GramLab/blob/main/docs/development/environment.md).
|
|
87
|
+
On a supported Linux
|
|
88
|
+
host with Nix and user namespaces:
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
nix develop
|
|
92
|
+
uv sync --locked
|
|
93
|
+
mkdir -p artifacts
|
|
94
|
+
uv run --locked --offline gramlab run examples/echo/hello.toml --output artifacts/echo-demo
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Open `artifacts/echo-demo/report.html`. Use a new output directory for each run.
|
|
98
|
+
The runner isolates bot and scenario processes; dependency setup happens before execution.
|
|
99
|
+
Android captures require the separate
|
|
100
|
+
[Android setup](https://github.com/tholoo/GramLab/blob/main/docs/development/android-build.md).
|
|
101
|
+
|
|
102
|
+
More examples: [button presses](https://github.com/tholoo/GramLab/tree/main/examples/inline),
|
|
103
|
+
[rich messages](https://github.com/tholoo/GramLab/tree/main/examples/rich),
|
|
104
|
+
[rich buttons](https://github.com/tholoo/GramLab/tree/main/examples/rich_inline), and
|
|
105
|
+
[bot restart](https://github.com/tholoo/GramLab/tree/main/examples/recovery).
|
|
106
|
+
|
|
107
|
+
## Work on GramLab
|
|
108
|
+
|
|
109
|
+
- [Contributor setup and checks](https://github.com/tholoo/GramLab/blob/main/CONTRIBUTING.md)
|
|
110
|
+
- [Current handoff and remaining work](https://github.com/tholoo/GramLab/blob/main/docs/development/handoff.md)
|
|
111
|
+
- [Architecture](https://github.com/tholoo/GramLab/blob/main/docs/architecture/overview.md) and [product scope](https://github.com/tholoo/GramLab/blob/main/docs/product/requirements.md)
|
|
112
|
+
- [Offline execution rules](https://github.com/tholoo/GramLab/blob/main/docs/development/offline-safety.md)
|
|
113
|
+
- [Working in parallel](https://github.com/tholoo/GramLab/blob/main/docs/development/parallel-work.md)
|
|
114
|
+
- [Release history](https://github.com/tholoo/GramLab/blob/main/CHANGELOG.md)
|
|
115
|
+
|
|
116
|
+
Original core and SDK code uses [MIT](https://github.com/tholoo/GramLab/blob/main/LICENSE). Two
|
|
117
|
+
TDLib-derived Python modules retain
|
|
118
|
+
[BSL-1.0](https://github.com/tholoo/GramLab/blob/main/LICENSES/BSL-1.0.txt). Android-derived patches
|
|
119
|
+
and fixtures retain GPL-2.0-or-later. See the
|
|
120
|
+
[license map](https://github.com/tholoo/GramLab/blob/main/NOTICE) and
|
|
121
|
+
[licensing boundaries](https://github.com/tholoo/GramLab/blob/main/docs/development/licensing.md).
|
|
122
|
+
This is a source repository. No Android APK release or completed dependency license audit is offered.
|
|
123
|
+
|
|
124
|
+
GramLab is unofficial and is not affiliated with or endorsed by Telegram.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# GramLab
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/tholoo/GramLab/main/docs/assets/gramlab-preview.png" width="320" alt="An English GramLab conversation in the Telegram Android renderer, with rich text, buttons and glass effects." />
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
[Original Android capture](https://github.com/tholoo/GramLab/blob/main/docs/assets/gramlab-preview.md), with glass effects enabled.
|
|
8
|
+
|
|
9
|
+
Test Telegram bots locally and inspect their messages in the actual Telegram Android client.
|
|
10
|
+
No Telegram account or production token is needed.
|
|
11
|
+
|
|
12
|
+
**Experimental.** Text, callbacks, rich messages, photos, documents, albums and custom emoji have
|
|
13
|
+
tested original-Android workflows. Mini Apps, HTML parse modes, grouped-media edits, external
|
|
14
|
+
Telegram conformance and interactive Android mode remain unfinished.
|
|
15
|
+
See the
|
|
16
|
+
[compatibility matrix](https://github.com/tholoo/GramLab/blob/main/docs/compatibility/matrix.md)
|
|
17
|
+
for the supported scope.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
GramLab currently requires Python 3.13 on a supported Linux host. Install the experimental
|
|
22
|
+
prerelease explicitly:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
uv add "gramlab==0.1.0a1"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The package includes the `gramlab` command and typed Python scenario interface. Android captures
|
|
29
|
+
require separately prepared local tooling and are not distributed in the Python package.
|
|
30
|
+
|
|
31
|
+
## Write a scenario
|
|
32
|
+
|
|
33
|
+
Create a user, talk to a real local bot, check its reply and capture the conversation:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from gramlab import Scenario
|
|
37
|
+
|
|
38
|
+
lab = Scenario.from_environment()
|
|
39
|
+
chat = lab.conversation(user=lab.user("Alex", language_code="en"), bot="echo")
|
|
40
|
+
chat.send("Hello!")
|
|
41
|
+
history = chat.wait_for_messages(2, timeout=5)
|
|
42
|
+
|
|
43
|
+
if history[1].text != "Echo: Hello!":
|
|
44
|
+
raise AssertionError("Unexpected bot reply")
|
|
45
|
+
chat.capture("hello", contains=["Echo: Hello!"])
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This runs inside a scenario process. The
|
|
49
|
+
[English echo example](https://github.com/tholoo/GramLab/blob/main/examples/echo/hello.toml) uses
|
|
50
|
+
this exact [scenario](https://github.com/tholoo/GramLab/blob/main/examples/echo/hello.py),
|
|
51
|
+
with the bundled bot and manifest, and the runner supplies the environment. Simulation records the conversation state;
|
|
52
|
+
headless Android also captures the original client. Both modes produce a local HTML report.
|
|
53
|
+
The typed handles are additive: advanced scenarios can still use the raw JSON-shaped operations
|
|
54
|
+
on `Scenario`. The Python interface is still experimental.
|
|
55
|
+
|
|
56
|
+
## Try it
|
|
57
|
+
|
|
58
|
+
Start with the
|
|
59
|
+
[development environment](https://github.com/tholoo/GramLab/blob/main/docs/development/environment.md).
|
|
60
|
+
On a supported Linux
|
|
61
|
+
host with Nix and user namespaces:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
nix develop
|
|
65
|
+
uv sync --locked
|
|
66
|
+
mkdir -p artifacts
|
|
67
|
+
uv run --locked --offline gramlab run examples/echo/hello.toml --output artifacts/echo-demo
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Open `artifacts/echo-demo/report.html`. Use a new output directory for each run.
|
|
71
|
+
The runner isolates bot and scenario processes; dependency setup happens before execution.
|
|
72
|
+
Android captures require the separate
|
|
73
|
+
[Android setup](https://github.com/tholoo/GramLab/blob/main/docs/development/android-build.md).
|
|
74
|
+
|
|
75
|
+
More examples: [button presses](https://github.com/tholoo/GramLab/tree/main/examples/inline),
|
|
76
|
+
[rich messages](https://github.com/tholoo/GramLab/tree/main/examples/rich),
|
|
77
|
+
[rich buttons](https://github.com/tholoo/GramLab/tree/main/examples/rich_inline), and
|
|
78
|
+
[bot restart](https://github.com/tholoo/GramLab/tree/main/examples/recovery).
|
|
79
|
+
|
|
80
|
+
## Work on GramLab
|
|
81
|
+
|
|
82
|
+
- [Contributor setup and checks](https://github.com/tholoo/GramLab/blob/main/CONTRIBUTING.md)
|
|
83
|
+
- [Current handoff and remaining work](https://github.com/tholoo/GramLab/blob/main/docs/development/handoff.md)
|
|
84
|
+
- [Architecture](https://github.com/tholoo/GramLab/blob/main/docs/architecture/overview.md) and [product scope](https://github.com/tholoo/GramLab/blob/main/docs/product/requirements.md)
|
|
85
|
+
- [Offline execution rules](https://github.com/tholoo/GramLab/blob/main/docs/development/offline-safety.md)
|
|
86
|
+
- [Working in parallel](https://github.com/tholoo/GramLab/blob/main/docs/development/parallel-work.md)
|
|
87
|
+
- [Release history](https://github.com/tholoo/GramLab/blob/main/CHANGELOG.md)
|
|
88
|
+
|
|
89
|
+
Original core and SDK code uses [MIT](https://github.com/tholoo/GramLab/blob/main/LICENSE). Two
|
|
90
|
+
TDLib-derived Python modules retain
|
|
91
|
+
[BSL-1.0](https://github.com/tholoo/GramLab/blob/main/LICENSES/BSL-1.0.txt). Android-derived patches
|
|
92
|
+
and fixtures retain GPL-2.0-or-later. See the
|
|
93
|
+
[license map](https://github.com/tholoo/GramLab/blob/main/NOTICE) and
|
|
94
|
+
[licensing boundaries](https://github.com/tholoo/GramLab/blob/main/docs/development/licensing.md).
|
|
95
|
+
This is a source repository. No Android APK release or completed dependency license audit is offered.
|
|
96
|
+
|
|
97
|
+
GramLab is unofficial and is not affiliated with or endorsed by Telegram.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "gramlab"
|
|
3
|
+
version = "0.1.0a1"
|
|
4
|
+
description = "Offline Telegram bot laboratory — experimental runtime foundation"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13,<3.14"
|
|
7
|
+
license = "MIT AND BSL-1.0"
|
|
8
|
+
license-files = [
|
|
9
|
+
"LICENSE",
|
|
10
|
+
"LICENSES/BSL-1.0.txt",
|
|
11
|
+
"NOTICE",
|
|
12
|
+
]
|
|
13
|
+
keywords = [
|
|
14
|
+
"telegram",
|
|
15
|
+
"bot",
|
|
16
|
+
"testing",
|
|
17
|
+
"offline",
|
|
18
|
+
"android",
|
|
19
|
+
]
|
|
20
|
+
classifiers = [
|
|
21
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
22
|
+
"Environment :: Console",
|
|
23
|
+
"Intended Audience :: Developers",
|
|
24
|
+
"Operating System :: POSIX :: Linux",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Topic :: Software Development :: Testing",
|
|
28
|
+
"Typing :: Typed",
|
|
29
|
+
]
|
|
30
|
+
dependencies = ["pillow==12.3.0"]
|
|
31
|
+
|
|
32
|
+
[[project.authors]]
|
|
33
|
+
name = "Ali Mohammadzadeh"
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://github.com/tholoo/GramLab"
|
|
37
|
+
Documentation = "https://github.com/tholoo/GramLab/tree/main/docs"
|
|
38
|
+
Repository = "https://github.com/tholoo/GramLab"
|
|
39
|
+
Issues = "https://github.com/tholoo/GramLab/issues"
|
|
40
|
+
Changelog = "https://github.com/tholoo/GramLab/blob/main/CHANGELOG.md"
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
gramlab = "gramlab.__main__:main"
|
|
44
|
+
|
|
45
|
+
[dependency-groups]
|
|
46
|
+
dev = [
|
|
47
|
+
"coverage==7.16.0",
|
|
48
|
+
"hypothesis==6.167.1",
|
|
49
|
+
"mypy==1.20.2",
|
|
50
|
+
"pytest==8.4.2",
|
|
51
|
+
"pytest-asyncio==1.4.0",
|
|
52
|
+
"pytest-cov==6.3.0",
|
|
53
|
+
"pytest-xdist==3.8.0",
|
|
54
|
+
"ruff==0.16.5",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[build-system]
|
|
58
|
+
requires = ["uv_build==0.12.5"]
|
|
59
|
+
build-backend = "uv_build"
|
|
60
|
+
|
|
61
|
+
[tool.ruff]
|
|
62
|
+
line-length = 100
|
|
63
|
+
target-version = "py313"
|
|
64
|
+
extend-exclude = ["clients/android/upstream"]
|
|
65
|
+
|
|
66
|
+
[tool.ruff.lint]
|
|
67
|
+
select = [
|
|
68
|
+
"E",
|
|
69
|
+
"F",
|
|
70
|
+
"I",
|
|
71
|
+
"UP",
|
|
72
|
+
"B",
|
|
73
|
+
"ASYNC",
|
|
74
|
+
"S",
|
|
75
|
+
"RUF",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
[tool.ruff.lint.per-file-ignores]
|
|
79
|
+
"tests/**" = [
|
|
80
|
+
"S101",
|
|
81
|
+
"S106",
|
|
82
|
+
"S311",
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
[tool.mypy]
|
|
86
|
+
python_version = "3.13"
|
|
87
|
+
strict = true
|
|
88
|
+
warn_unreachable = true
|
|
89
|
+
|
|
90
|
+
[tool.pytest.ini_options]
|
|
91
|
+
addopts = "--strict-markers --strict-config -q"
|
|
92
|
+
testpaths = ["tests"]
|
|
93
|
+
asyncio_mode = "strict"
|
|
94
|
+
markers = [
|
|
95
|
+
"android: requires the isolated Android runtime",
|
|
96
|
+
"stress: explicitly selected randomized or load tests",
|
|
97
|
+
"conformance: requires separately reviewed external compatibility evidence",
|
|
98
|
+
]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "gramlab"
|
|
3
|
+
version = "0.1.0a1"
|
|
4
|
+
description = "Offline Telegram bot laboratory — experimental runtime foundation"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13,<3.14"
|
|
7
|
+
license = "MIT AND BSL-1.0"
|
|
8
|
+
license-files = ["LICENSE", "LICENSES/BSL-1.0.txt", "NOTICE"]
|
|
9
|
+
authors = [
|
|
10
|
+
{ name = "Ali Mohammadzadeh" },
|
|
11
|
+
]
|
|
12
|
+
keywords = ["telegram", "bot", "testing", "offline", "android"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
15
|
+
"Environment :: Console",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Operating System :: POSIX :: Linux",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Topic :: Software Development :: Testing",
|
|
21
|
+
"Typing :: Typed",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"pillow==12.3.0",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://github.com/tholoo/GramLab"
|
|
29
|
+
Documentation = "https://github.com/tholoo/GramLab/tree/main/docs"
|
|
30
|
+
Repository = "https://github.com/tholoo/GramLab"
|
|
31
|
+
Issues = "https://github.com/tholoo/GramLab/issues"
|
|
32
|
+
Changelog = "https://github.com/tholoo/GramLab/blob/main/CHANGELOG.md"
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
gramlab = "gramlab.__main__:main"
|
|
36
|
+
|
|
37
|
+
[dependency-groups]
|
|
38
|
+
dev = [
|
|
39
|
+
"coverage==7.16.0",
|
|
40
|
+
"hypothesis==6.167.1",
|
|
41
|
+
"mypy==1.20.2",
|
|
42
|
+
"pytest==8.4.2",
|
|
43
|
+
"pytest-asyncio==1.4.0",
|
|
44
|
+
"pytest-cov==6.3.0",
|
|
45
|
+
"pytest-xdist==3.8.0",
|
|
46
|
+
"ruff==0.16.5",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[build-system]
|
|
50
|
+
requires = ["uv_build==0.12.5"]
|
|
51
|
+
build-backend = "uv_build"
|
|
52
|
+
|
|
53
|
+
[tool.ruff]
|
|
54
|
+
line-length = 100
|
|
55
|
+
target-version = "py313"
|
|
56
|
+
extend-exclude = ["clients/android/upstream"]
|
|
57
|
+
|
|
58
|
+
[tool.ruff.lint]
|
|
59
|
+
select = ["E", "F", "I", "UP", "B", "ASYNC", "S", "RUF"]
|
|
60
|
+
|
|
61
|
+
[tool.ruff.lint.per-file-ignores]
|
|
62
|
+
"tests/**" = ["S101", "S106", "S311"]
|
|
63
|
+
|
|
64
|
+
[tool.mypy]
|
|
65
|
+
python_version = "3.13"
|
|
66
|
+
strict = true
|
|
67
|
+
warn_unreachable = true
|
|
68
|
+
|
|
69
|
+
[tool.pytest.ini_options]
|
|
70
|
+
addopts = "--strict-markers --strict-config -q"
|
|
71
|
+
testpaths = ["tests"]
|
|
72
|
+
asyncio_mode = "strict"
|
|
73
|
+
markers = [
|
|
74
|
+
"android: requires the isolated Android runtime",
|
|
75
|
+
"stress: explicitly selected randomized or load tests",
|
|
76
|
+
"conformance: requires separately reviewed external compatibility evidence",
|
|
77
|
+
]
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Python core and SDK
|
|
2
|
+
|
|
3
|
+
Reserved for independently written MIT-licensed simulation, Bot API transport, scenario control
|
|
4
|
+
and reporting code. The package exports the experimental typed scenario-authoring interface;
|
|
5
|
+
`runtime.py` implements its Linux process boundary. No stable simulator interface exists yet. Keep Android-derived
|
|
6
|
+
classes and generated client-derived code outside this boundary.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""GramLab's experimental scenario-authoring interface."""
|
|
2
|
+
|
|
3
|
+
from gramlab.scenario import Scenario, ScenarioError
|
|
4
|
+
from gramlab.scenario_flow import (
|
|
5
|
+
Bot,
|
|
6
|
+
BotState,
|
|
7
|
+
BotStatus,
|
|
8
|
+
Callback,
|
|
9
|
+
Capture,
|
|
10
|
+
Conversation,
|
|
11
|
+
InlineAction,
|
|
12
|
+
InlineButton,
|
|
13
|
+
InteractionReceipt,
|
|
14
|
+
Message,
|
|
15
|
+
ScenarioFlowError,
|
|
16
|
+
ScenarioWaitTimeout,
|
|
17
|
+
User,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"Bot",
|
|
22
|
+
"BotState",
|
|
23
|
+
"BotStatus",
|
|
24
|
+
"Callback",
|
|
25
|
+
"Capture",
|
|
26
|
+
"Conversation",
|
|
27
|
+
"InlineAction",
|
|
28
|
+
"InlineButton",
|
|
29
|
+
"InteractionReceipt",
|
|
30
|
+
"Message",
|
|
31
|
+
"Scenario",
|
|
32
|
+
"ScenarioError",
|
|
33
|
+
"ScenarioFlowError",
|
|
34
|
+
"ScenarioWaitTimeout",
|
|
35
|
+
"User",
|
|
36
|
+
]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Public command entry point; consumer code is only executed inside the runtime."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from gramlab.runner import run
|
|
9
|
+
from gramlab.runtime import RuntimeProfile
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def main() -> int:
|
|
13
|
+
parser = argparse.ArgumentParser(prog="gramlab")
|
|
14
|
+
commands = parser.add_subparsers(dest="command", required=True)
|
|
15
|
+
execute = commands.add_parser("run", help="Run a declared scenario and bots offline")
|
|
16
|
+
execute.add_argument("manifest", type=Path)
|
|
17
|
+
execute.add_argument("--output", type=Path, required=True, help="Fresh run directory")
|
|
18
|
+
execute.add_argument("--profile", type=Path, default=os.environ.get("GRAMLAB_RUNTIME_PROFILE"))
|
|
19
|
+
execute.add_argument(
|
|
20
|
+
"--android-profile", type=Path, default=os.environ.get("GRAMLAB_ANDROID_RUNTIME_PROFILE")
|
|
21
|
+
)
|
|
22
|
+
execute.add_argument("--android-apk", type=Path, default=os.environ.get("GRAMLAB_ANDROID_APK"))
|
|
23
|
+
execute.add_argument("--bridge-version", type=int, choices=(3, 4, 5, 6), default=3)
|
|
24
|
+
args = parser.parse_args()
|
|
25
|
+
if args.profile is None:
|
|
26
|
+
parser.error("Enter the provisioned Nix shell or supply --profile")
|
|
27
|
+
try:
|
|
28
|
+
outcome = run(
|
|
29
|
+
args.manifest,
|
|
30
|
+
args.output,
|
|
31
|
+
profile=RuntimeProfile.load(args.profile),
|
|
32
|
+
android_profile=RuntimeProfile.load(args.android_profile)
|
|
33
|
+
if args.android_profile
|
|
34
|
+
else None,
|
|
35
|
+
android_apk=args.android_apk,
|
|
36
|
+
bridge_version=args.bridge_version,
|
|
37
|
+
)
|
|
38
|
+
except (OSError, ValueError, KeyError, TypeError) as error:
|
|
39
|
+
print(f"gramlab: cannot prepare run ({type(error).__name__}): {error}", file=sys.stderr)
|
|
40
|
+
return 2
|
|
41
|
+
print(f"{outcome}: {args.output / 'report.html'}")
|
|
42
|
+
return 0 if outcome == "passed" else 1
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
raise SystemExit(main())
|