hud-python 0.1.0b2__tar.gz → 0.1.0b3__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.

Potentially problematic release.


This version of hud-python might be problematic. Click here for more details.

Files changed (50) hide show
  1. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/PKG-INFO +2 -2
  2. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/README.md +1 -1
  3. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/agent/response_agent.py +3 -4
  4. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/api-reference/client.mdx +2 -2
  5. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/concepts/environment.mdx +1 -1
  6. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/concepts/gym.mdx +1 -1
  7. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/examples/basic.mdx +2 -2
  8. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/examples/custom-agent.mdx +1 -1
  9. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/introduction.mdx +1 -1
  10. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/quickstart.mdx +1 -1
  11. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/examples/claude_osworld.ipynb +85 -14
  12. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/__init__.py +1 -1
  13. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/adapters/claude/__init__.py +0 -1
  14. hud_python-0.1.0b3/hud/adapters/common/types.py +293 -0
  15. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/client.py +16 -15
  16. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/environment.py +30 -25
  17. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/gym.py +2 -2
  18. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/run.py +12 -14
  19. hud_python-0.1.0b3/hud/server/__init__.py +5 -0
  20. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/server/requests.py +79 -52
  21. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/settings.py +6 -8
  22. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/pyproject.toml +2 -2
  23. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/tests/test_import.py +1 -1
  24. hud_python-0.1.0b2/hud/adapters/common/types.py +0 -92
  25. hud_python-0.1.0b2/hud/server/__init__.py +0 -5
  26. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/.env.example +0 -0
  27. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/.github/workflows/ci.yml +0 -0
  28. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/.github/workflows/release.yml +0 -0
  29. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/.gitignore +0 -0
  30. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/LICENSE +0 -0
  31. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/MANIFEST.in +0 -0
  32. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/agent/base.py +0 -0
  33. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/agent/claude.py +0 -0
  34. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/api-reference/adapters.mdx +0 -0
  35. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/api-reference/env.mdx +0 -0
  36. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/concepts/adapter.mdx +0 -0
  37. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/concepts/client.mdx +0 -0
  38. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/examples/claude-agent.mdx +0 -0
  39. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/installation.mdx +0 -0
  40. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/logo/HUD.svg +0 -0
  41. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/docs/mint.json +0 -0
  42. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/examples/README.md +0 -0
  43. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/adapters/__init__.py +0 -0
  44. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/adapters/claude/adapter.py +0 -0
  45. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/adapters/common/__init__.py +0 -0
  46. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/adapters/common/adapter.py +0 -0
  47. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/py.typed +0 -0
  48. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/utils/__init__.py +0 -0
  49. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/hud/utils/config.py +0 -0
  50. {hud_python-0.1.0b2 → hud_python-0.1.0b3}/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hud-python
3
- Version: 0.1.0b2
3
+ Version: 0.1.0b3
4
4
  Summary: SDK for the HUD evaluation platform.
5
5
  Project-URL: Homepage, https://github.com/Human-Data/hud-sdk
6
6
  Project-URL: Bug Tracker, https://github.com/Human-Data/hud-sdk/issues
@@ -95,7 +95,7 @@ async def main():
95
95
  evalset = await client.load_evalset(id="OSWorld-Ubuntu")
96
96
 
97
97
  # Create a run and environment
98
- run = client.create_run(name="example-run", gym=gym, evalset=evalset)
98
+ run = await client.create_run(name="example-run", gym=gym, evalset=evalset)
99
99
  env = await run.make(metadata={"agent_id": "OSWORLD-1"})
100
100
  await env.wait_for_ready()
101
101
 
@@ -38,7 +38,7 @@ async def main():
38
38
  evalset = await client.load_evalset(id="OSWorld-Ubuntu")
39
39
 
40
40
  # Create a run and environment
41
- run = client.create_run(name="example-run", gym=gym, evalset=evalset)
41
+ run = await client.create_run(name="example-run", gym=gym, evalset=evalset)
42
42
  env = await run.make(metadata={"agent_id": "OSWORLD-1"})
43
43
  await env.wait_for_ready()
44
44
 
@@ -1,4 +1,3 @@
1
- import json
2
1
  import os
3
2
  import openai
4
3
  from typing import Literal, Optional
@@ -11,7 +10,7 @@ class ResponseAgent:
11
10
  if not self.api_key:
12
11
  raise ValueError("OpenAI API key must be provided or set as OPENAI_API_KEY environment variable")
13
12
 
14
- self.client = openai.Client(api_key=self.api_key)
13
+ self.async_client = openai.AsyncClient(api_key=self.api_key)
15
14
 
16
15
  self.system_prompt = """
17
16
  You are an assistant that helps determine the appropriate response to an agent's message.
@@ -28,9 +27,9 @@ class ResponseAgent:
28
27
  Respond ONLY with one of these two options.
29
28
  """
30
29
 
31
- def determine_response(self, agent_message: str) -> ResponseType:
30
+ async def determine_response(self, agent_message: str) -> ResponseType:
32
31
  try:
33
- response = self.client.chat.completions.create(
32
+ response = await self.async_client.chat.completions.create(
34
33
  model="gpt-4o",
35
34
  messages=[
36
35
  {"role": "system", "content": self.system_prompt},
@@ -125,7 +125,7 @@ if run:
125
125
  ### create_run
126
126
 
127
127
  ```python
128
- create_run(
128
+ async create_run(
129
129
  name: str,
130
130
  gym: Gym,
131
131
  evalset: EvalSet,
@@ -150,7 +150,7 @@ Creates a new run.
150
150
 
151
151
  **Example:**
152
152
  ```python
153
- run = client.create_run(
153
+ run = await client.create_run(
154
154
  name="example-run",
155
155
  gym=gym,
156
156
  evalset=evalset,
@@ -17,7 +17,7 @@ from hud import HUDClient
17
17
  client = HUDClient(api_key="your-api-key")
18
18
  gym = await client.load_gym(id="OSWorld-Ubuntu")
19
19
  evalset = await client.load_evalset(id="OSWorld-Ubuntu")
20
- run = client.create_run(name="example-run", gym=gym, evalset=evalset)
20
+ run = await client.create_run(name="example-run", gym=gym, evalset=evalset)
21
21
 
22
22
  # Create environment
23
23
  env = await run.make(metadata={"agent_id": "example"})
@@ -43,7 +43,7 @@ Each gym has the following properties:
43
43
  Gyms are used when creating a run:
44
44
 
45
45
  ```python
46
- run = client.create_run(name="my-run", gym=gym, evalset=evalset)
46
+ run = await client.create_run(name="my-run", gym=gym, evalset=evalset)
47
47
  ```
48
48
 
49
49
  This associates the run with the specific environment defined by the gym.
@@ -59,7 +59,7 @@ Create a run to execute tasks:
59
59
 
60
60
  ```python
61
61
  # Create a run
62
- run = client.create_run(
62
+ run = await client.create_run(
63
63
  name="example-run",
64
64
  gym=gym,
65
65
  evalset=evalset,
@@ -133,7 +133,7 @@ async def main():
133
133
  evalset = await client.load_evalset(id="OSWorld-Ubuntu")
134
134
 
135
135
  # Create a run and get tasks
136
- run = client.create_run(name="example-run", gym=gym, evalset=evalset)
136
+ run = await client.create_run(name="example-run", gym=gym, evalset=evalset)
137
137
  tasks = await run.fetch_task_ids()
138
138
 
139
139
  # Create environment and wait for it to be ready
@@ -96,7 +96,7 @@ async def main():
96
96
  evalset = await client.load_evalset(id="OSWorld-Ubuntu")
97
97
 
98
98
  # Create the run
99
- run = client.create_run(name="simple-agent-run", gym=gym, evalset=evalset)
99
+ run = await client.create_run(name="simple-agent-run", gym=gym, evalset=evalset)
100
100
  tasks = await run.fetch_task_ids()
101
101
 
102
102
  # Initialize the agent and adapter
@@ -45,7 +45,7 @@ async def main():
45
45
  evalset = await client.load_evalset(id="OSWorld-Ubuntu")
46
46
 
47
47
  # Create a run
48
- run = client.create_run(name="example-run", gym=gym, evalset=evalset)
48
+ run = await client.create_run(name="example-run", gym=gym, evalset=evalset)
49
49
 
50
50
  # And more...
51
51
 
@@ -31,7 +31,7 @@ async def main():
31
31
  evalset = await client.load_evalset(id="OSWorld-Ubuntu")
32
32
 
33
33
  # Create a run and get tasks
34
- run = client.create_run(name="example-run", gym=gym, evalset=evalset)
34
+ run = await client.create_run(name="example-run", gym=gym, evalset=evalset)
35
35
  tasks = await run.fetch_task_ids()
36
36
 
37
37
  # Create environment and wait for it to be ready
@@ -19,7 +19,7 @@
19
19
  },
20
20
  {
21
21
  "cell_type": "code",
22
- "execution_count": 2,
22
+ "execution_count": 3,
23
23
  "metadata": {},
24
24
  "outputs": [],
25
25
  "source": [
@@ -28,7 +28,6 @@
28
28
  "\n",
29
29
  "# initalize Claude Computer Use agent\n",
30
30
  "anthropic = Anthropic(api_key=os.getenv(\"ANTHROPIC_API_KEY\"))\n",
31
- "agent = ClaudeAgent(anthropic)\n",
32
31
  "\n",
33
32
  "# initialize adapter to interact with the environment\n",
34
33
  "cua_adapter = ClaudeAdapter()"
@@ -36,9 +35,17 @@
36
35
  },
37
36
  {
38
37
  "cell_type": "code",
39
- "execution_count": null,
38
+ "execution_count": 4,
40
39
  "metadata": {},
41
- "outputs": [],
40
+ "outputs": [
41
+ {
42
+ "name": "stdout",
43
+ "output_type": "stream",
44
+ "text": [
45
+ "Total tasks in OSWorld: 368\n"
46
+ ]
47
+ }
48
+ ],
42
49
  "source": [
43
50
  "# load OSWorld environment\n",
44
51
  "gym = await client.load_gym(id=\"OSWorld-Ubuntu\")\n",
@@ -47,7 +54,7 @@
47
54
  "evalset = await client.load_evalset(id=\"OSWorld-Ubuntu\")\n",
48
55
  "\n",
49
56
  "# create a run that will host all evaluations\n",
50
- "run = client.create_run(name=\"Claude-test-OSWorld\", gym=gym, evalset=evalset)\n",
57
+ "run = await client.create_run(name=\"Claude-test-OSWorld\", gym=gym, evalset=evalset)\n",
51
58
  "\n",
52
59
  "# fetch all task ids from the run\n",
53
60
  "tasks = await run.fetch_task_ids()\n",
@@ -56,11 +63,38 @@
56
63
  },
57
64
  {
58
65
  "cell_type": "code",
59
- "execution_count": null,
66
+ "execution_count": 5,
60
67
  "metadata": {},
61
- "outputs": [],
68
+ "outputs": [
69
+ {
70
+ "name": "stdout",
71
+ "output_type": "stream",
72
+ "text": [
73
+ "Task description: Can you make my computer bring back the last tab I shut down?\n"
74
+ ]
75
+ },
76
+ {
77
+ "data": {
78
+ "text/html": [
79
+ "\n",
80
+ " <div style=\"width: 960px; height: 540px; overflow: hidden;\">\n",
81
+ " <div style=\"transform: scale(0.5); transform-origin: top left;\">\n",
82
+ " <iframe src=\"http://18.212.230.156:5910/vnc.html\" width=\"1920\" height=\"1080\" style=\"border: 1px solid #ddd;\">\n",
83
+ " </iframe>\n",
84
+ " </div>\n",
85
+ " </div>\n",
86
+ " "
87
+ ],
88
+ "text/plain": [
89
+ "<IPython.core.display.HTML object>"
90
+ ]
91
+ },
92
+ "metadata": {},
93
+ "output_type": "display_data"
94
+ }
95
+ ],
62
96
  "source": [
63
- "# it may take around 3 minutes to initialize the OSWorld platform and reset to a task\n",
97
+ "# it may take around 1-2 minutes to initialize the OSWorld platform and reset to a task\n",
64
98
  "\n",
65
99
  "# make a HUD environment\n",
66
100
  "env = await run.make()\n",
@@ -77,11 +111,22 @@
77
111
  },
78
112
  {
79
113
  "cell_type": "code",
80
- "execution_count": null,
114
+ "execution_count": 6,
81
115
  "metadata": {},
82
- "outputs": [],
116
+ "outputs": [
117
+ {
118
+ "name": "stdout",
119
+ "output_type": "stream",
120
+ "text": [
121
+ "Agent's action: {'action': 'key', 'text': 'ctrl+shift+t'}\n",
122
+ "Step 1 completed\n"
123
+ ]
124
+ }
125
+ ],
83
126
  "source": [
84
127
  "# agent loop\n",
128
+ "agent = ClaudeAgent(anthropic)\n",
129
+ "\n",
85
130
  "for i in range(8):\n",
86
131
  " # rescale screenshot to Claude's resolution\n",
87
132
  " screenshot = cua_adapter.rescale(obs.screenshot)\n",
@@ -107,9 +152,17 @@
107
152
  },
108
153
  {
109
154
  "cell_type": "code",
110
- "execution_count": null,
155
+ "execution_count": 7,
111
156
  "metadata": {},
112
- "outputs": [],
157
+ "outputs": [
158
+ {
159
+ "name": "stdout",
160
+ "output_type": "stream",
161
+ "text": [
162
+ "Evaluation result: 1.0\n"
163
+ ]
164
+ }
165
+ ],
113
166
  "source": [
114
167
  "# evaluate environment state\n",
115
168
  "result = await env.evaluate()\n",
@@ -121,9 +174,27 @@
121
174
  },
122
175
  {
123
176
  "cell_type": "code",
124
- "execution_count": null,
177
+ "execution_count": 8,
125
178
  "metadata": {},
126
- "outputs": [],
179
+ "outputs": [
180
+ {
181
+ "name": "stdout",
182
+ "output_type": "stream",
183
+ "text": [
184
+ "Run: Claude-test-OSWorld (ID: 7c0df152-e799-4ec6-ac2e-8a4e0aaa5b99)\n",
185
+ "Created: 2025-03-10 02:45:28\n",
186
+ "------------------------------------------------------------\n",
187
+ "Progress: 1/1 tasks completed (\n",
188
+ " 100.0% completion rate)\n",
189
+ "\n",
190
+ "Status Distribution:\n",
191
+ "completed : ██████████████████████████████████████████████████ 1 (100.0%)\n",
192
+ "\n",
193
+ "Average Score: 1.00\n",
194
+ "Score: 1.00/1.00\n"
195
+ ]
196
+ }
197
+ ],
127
198
  "source": [
128
199
  "analytics = await run.get_analytics()\n",
129
200
  "print(analytics)"
@@ -9,7 +9,7 @@ from hud.environment import Environment, EvalSet, Observation, TaskResult
9
9
  from hud.gym import Gym
10
10
  from hud.run import Run
11
11
 
12
- __version__ = "0.1.0b2"
12
+ __version__ = "0.1.0b3"
13
13
 
14
14
  __all__ = [
15
15
  "Environment",
@@ -3,4 +3,3 @@ from __future__ import annotations
3
3
  from .adapter import ClaudeAdapter
4
4
 
5
5
  __all__ = ["ClaudeAdapter"]
6
-
@@ -0,0 +1,293 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Annotated, Literal, Union
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+
8
+ # Base class for all actions
9
+ class CLAAction(BaseModel):
10
+ type: str
11
+
12
+
13
+ # Basic Point model for coordinates
14
+ class Point(BaseModel):
15
+ x: int
16
+ y: int
17
+
18
+
19
+ # CLICK ACTION (supports extra options)
20
+ class ClickAction(CLAAction):
21
+ type: Literal["click"] = "click"
22
+ point: Point | None = None
23
+ selector: str | None = None
24
+ button: Literal["left", "right", "wheel", "back", "forward"] = "left"
25
+ pattern: list[int] | None = None # [delay_1, delay_2, ...]
26
+ hold_keys: list[CLAKey] | None = None
27
+
28
+
29
+ # PRESS ACTION for key presses/hotkeys
30
+ class PressAction(CLAAction):
31
+ type: Literal["press"] = "press"
32
+ keys: list[CLAKey]
33
+
34
+
35
+ # TYPE ACTION for text typing
36
+ class TypeAction(CLAAction):
37
+ type: Literal["type"] = "type"
38
+ text: str
39
+ enter_after: bool | None = False
40
+
41
+
42
+ # SCROLL ACTION
43
+ class ScrollAction(CLAAction):
44
+ type: Literal["scroll"] = "scroll"
45
+ point: Point | None = None
46
+ scroll: Point | None = None
47
+ hold_keys: list[CLAKey] | None = None
48
+
49
+
50
+ # MOVE ACTION for mouse movement
51
+ class MoveAction(CLAAction):
52
+ type: Literal["move"] = "move"
53
+ point: Point | None = None
54
+ selector: str | None = None
55
+ offset: Point | None = None
56
+
57
+
58
+ # WAIT ACTION
59
+ class WaitAction(CLAAction):
60
+ type: Literal["wait"] = "wait"
61
+ time: int # in milliseconds
62
+
63
+
64
+ # DRAG ACTION
65
+ class DragAction(CLAAction):
66
+ type: Literal["drag"] = "drag"
67
+ path: list[Point]
68
+ pattern: list[int] | None = None # [delay_1, delay_2, ...]
69
+ hold_keys: list[CLAKey] | None = None
70
+
71
+
72
+ # SCREENSHOT ACTION
73
+ class ScreenshotFetch(CLAAction):
74
+ type: Literal["screenshot"] = "screenshot"
75
+
76
+
77
+ class PositionFetch(CLAAction):
78
+ type: Literal["position"] = "position"
79
+
80
+
81
+ # Union of all possible actions
82
+ CLA = Annotated[
83
+ Union[
84
+ ClickAction,
85
+ PressAction,
86
+ TypeAction,
87
+ ScrollAction,
88
+ MoveAction,
89
+ WaitAction,
90
+ DragAction,
91
+ ScreenshotFetch,
92
+ PositionFetch,
93
+ ],
94
+ Field(discriminator="type"),
95
+ ]
96
+
97
+
98
+ CLAKey = Literal[
99
+ # Control keys
100
+ "backspace",
101
+ "tab",
102
+ "enter",
103
+ "shift",
104
+ "shiftleft",
105
+ "shiftright",
106
+ "ctrl",
107
+ "ctrlleft",
108
+ "ctrlright",
109
+ "alt",
110
+ "altleft",
111
+ "altright",
112
+ "pause",
113
+ "capslock",
114
+ "esc",
115
+ "escape",
116
+ "space",
117
+ "pageup",
118
+ "pagedown",
119
+ "end",
120
+ "home",
121
+ "left",
122
+ "up",
123
+ "right",
124
+ "down",
125
+ "select",
126
+ "print",
127
+ "execute",
128
+ "printscreen",
129
+ "prtsc",
130
+ "insert",
131
+ "delete",
132
+ "help",
133
+ "sleep",
134
+ # Special keys
135
+ "numlock",
136
+ "scrolllock",
137
+ "clear",
138
+ "separator",
139
+ "modechange",
140
+ "apps",
141
+ "browserback",
142
+ "browserfavorites",
143
+ "browserforward",
144
+ "browserhome",
145
+ "browserrefresh",
146
+ "browsersearch",
147
+ "browserstop",
148
+ "launchapp1",
149
+ "launchapp2",
150
+ "launchmail",
151
+ "launchmediaselect",
152
+ "playpause",
153
+ "stop",
154
+ "prevtrack",
155
+ "nexttrack",
156
+ "volumemute",
157
+ "volumeup",
158
+ "volumedown",
159
+ "zoom",
160
+ # Modifier keys
161
+ "win",
162
+ "winleft",
163
+ "winright",
164
+ "command",
165
+ "option",
166
+ "optionleft",
167
+ "optionright",
168
+ "fn",
169
+ # Numpad keys
170
+ "num0",
171
+ "num1",
172
+ "num2",
173
+ "num3",
174
+ "num4",
175
+ "num5",
176
+ "num6",
177
+ "num7",
178
+ "num8",
179
+ "num9",
180
+ "multiply",
181
+ "add",
182
+ "subtract",
183
+ "decimal",
184
+ "divide",
185
+ # Function keys
186
+ "f1",
187
+ "f2",
188
+ "f3",
189
+ "f4",
190
+ "f5",
191
+ "f6",
192
+ "f7",
193
+ "f8",
194
+ "f9",
195
+ "f10",
196
+ "f11",
197
+ "f12",
198
+ "f13",
199
+ "f14",
200
+ "f15",
201
+ "f16",
202
+ "f17",
203
+ "f18",
204
+ "f19",
205
+ "f20",
206
+ "f21",
207
+ "f22",
208
+ "f23",
209
+ "f24",
210
+ # Language-specific keys
211
+ "hanguel",
212
+ "hangul",
213
+ "hanja",
214
+ "kana",
215
+ "kanji",
216
+ "junja",
217
+ "convert",
218
+ "nonconvert",
219
+ "yen",
220
+ # Characters
221
+ "\t",
222
+ "\n",
223
+ "\r",
224
+ " ",
225
+ "!",
226
+ '"',
227
+ "#",
228
+ "$",
229
+ "%",
230
+ "&",
231
+ "'",
232
+ "(",
233
+ ")",
234
+ "*",
235
+ "+",
236
+ ",",
237
+ "-",
238
+ ".",
239
+ "/",
240
+ "0",
241
+ "1",
242
+ "2",
243
+ "3",
244
+ "4",
245
+ "5",
246
+ "6",
247
+ "7",
248
+ "8",
249
+ "9",
250
+ ":",
251
+ ";",
252
+ "<",
253
+ "=",
254
+ ">",
255
+ "?",
256
+ "@",
257
+ "[",
258
+ "\\",
259
+ "]",
260
+ "^",
261
+ "_",
262
+ "`",
263
+ "a",
264
+ "b",
265
+ "c",
266
+ "d",
267
+ "e",
268
+ "f",
269
+ "g",
270
+ "h",
271
+ "i",
272
+ "j",
273
+ "k",
274
+ "l",
275
+ "m",
276
+ "n",
277
+ "o",
278
+ "p",
279
+ "q",
280
+ "r",
281
+ "s",
282
+ "t",
283
+ "u",
284
+ "v",
285
+ "w",
286
+ "x",
287
+ "y",
288
+ "z",
289
+ "{",
290
+ "|",
291
+ "}",
292
+ "~",
293
+ ]