reykit 1.0.1__py3-none-any.whl → 1.1.1__py3-none-any.whl

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.
Files changed (60) hide show
  1. reydb/__init__.py +1 -1
  2. reydb/rbuild.py +44 -44
  3. reydb/rconnection.py +107 -107
  4. reydb/rexecute.py +9 -13
  5. reydb/rfile.py +8 -8
  6. reydb/rinformation.py +13 -25
  7. reydb/rparameter.py +10 -10
  8. reykit/__init__.py +1 -1
  9. reykit/rcomm.py +12 -12
  10. reykit/rdata.py +4 -4
  11. reykit/remail.py +12 -14
  12. reykit/rexception.py +4 -4
  13. reykit/rimage.py +9 -9
  14. reykit/rlog.py +30 -30
  15. reykit/rmonkey.py +4 -5
  16. reykit/rmultitask.py +14 -15
  17. reykit/rnumber.py +2 -2
  18. reykit/ros.py +21 -21
  19. reykit/rrandom.py +11 -11
  20. reykit/rregex.py +10 -13
  21. reykit/rschedule.py +10 -10
  22. reykit/rstdout.py +13 -13
  23. reykit/rsystem.py +224 -30
  24. reykit/rtable.py +31 -31
  25. reykit/rtext.py +3 -3
  26. reykit/rtime.py +11 -31
  27. reykit/rtype.py +2 -2
  28. reykit/rwrap.py +16 -16
  29. reykit/rzip.py +4 -5
  30. {reykit-1.0.1.dist-info → reykit-1.1.1.dist-info}/METADATA +1 -1
  31. reykit-1.1.1.dist-info/RECORD +38 -0
  32. reykit-1.0.1.dist-info/RECORD +0 -64
  33. reyweb/__init__.py +0 -19
  34. reyweb/rall.py +0 -12
  35. reyweb/rbaidu/__init__.py +0 -21
  36. reyweb/rbaidu/rbaidu_base.py +0 -186
  37. reyweb/rbaidu/rbaidu_chat.py +0 -299
  38. reyweb/rbaidu/rbaidu_image.py +0 -183
  39. reyweb/rbaidu/rbaidu_voice.py +0 -256
  40. reywechat/__init__.py +0 -32
  41. reywechat/data/client_api.dll +0 -0
  42. reywechat/rall.py +0 -20
  43. reywechat/rclient.py +0 -912
  44. reywechat/rdatabase.py +0 -1189
  45. reywechat/rexception.py +0 -65
  46. reywechat/rexecute.py +0 -201
  47. reywechat/rlog.py +0 -198
  48. reywechat/rreceive.py +0 -1232
  49. reywechat/rschedule.py +0 -136
  50. reywechat/rsend.py +0 -630
  51. reywechat/rwechat.py +0 -201
  52. reyworm/__init__.py +0 -24
  53. reyworm/rall.py +0 -16
  54. reyworm/rbrowser.py +0 -134
  55. reyworm/rcalendar.py +0 -159
  56. reyworm/rnews.py +0 -126
  57. reyworm/rsecurity.py +0 -239
  58. reyworm/rtranslate.py +0 -75
  59. {reykit-1.0.1.dist-info → reykit-1.1.1.dist-info}/WHEEL +0 -0
  60. {reykit-1.0.1.dist-info → reykit-1.1.1.dist-info}/top_level.txt +0 -0
reykit/rmultitask.py CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
  from __future__ import annotations
13
- from typing import Any, Optional, Literal, Union
13
+ from typing import Any, Literal
14
14
  from collections.abc import Callable, Iterable, Generator, Coroutine
15
15
  from threading import RLock as TRLock, get_ident as threading_get_ident
16
16
  from concurrent.futures import ThreadPoolExecutor, Future as CFuture, as_completed as concurrent_as_completed
@@ -78,15 +78,15 @@ def async_run(*coroutines: Coroutine) -> list:
78
78
 
79
79
  async def async_request(
80
80
  url: str,
81
- params: Optional[dict] = None,
82
- data: Optional[Union[dict, str, bytes]] = None,
83
- json: Optional[dict] = None,
81
+ params: dict | None = None,
82
+ data: dict | str | bytes | None = None,
83
+ json: dict | None = None,
84
84
  headers: dict[str, str] = {},
85
- timeout: Optional[float] = None,
86
- proxy: Optional[str] = None,
87
- method: Optional[Literal['get', 'post', 'put', 'patch', 'delete', 'options', 'head']] = None,
88
- check: Union[bool, int, Iterable[int]] = False,
89
- handler: Optional[Union[str, tuple[str], Callable[[ClientResponse], Union[Coroutine, Any]]]] = None
85
+ timeout: float | None = None,
86
+ proxy: str | None = None,
87
+ method: Literal['get', 'post', 'put', 'patch', 'delete', 'options', 'head'] | None = None,
88
+ check: bool | int | Iterable[int] = False,
89
+ handler: str | tuple[str] | Callable[[ClientResponse], Coroutine | Any] | None = None
90
90
  ) -> Any:
91
91
  """
92
92
  Get asynchronous `Coroutine` instance of send request.
@@ -119,7 +119,6 @@ async def async_request(
119
119
  - `Literal[True]`: Check if is between 200 and 299.
120
120
  - `int`: Check if is this value.
121
121
  - `Iterable`: Check if is in sequence.
122
-
123
122
  handler : Response handler.
124
123
  - `None`: Automatic handle.
125
124
  `Response 'Content-Type' is 'application/json'`: Use `ClientResponse.json` method.
@@ -247,7 +246,7 @@ class RThreadLock():
247
246
 
248
247
  # Set attribute.
249
248
  self.lock = TRLock()
250
- self.acquire_thread_id: Optional[int] = None
249
+ self.acquire_thread_id: int | None = None
251
250
 
252
251
 
253
252
  def acquire(
@@ -372,7 +371,7 @@ class RThreadPool(object):
372
371
  self,
373
372
  task: Callable,
374
373
  *args: Any,
375
- _max_workers: Optional[int] = None,
374
+ _max_workers: int | None = None,
376
375
  **kwargs: Any
377
376
  ) -> None:
378
377
  """
@@ -498,7 +497,7 @@ class RThreadPool(object):
498
497
 
499
498
  def generate(
500
499
  self,
501
- timeout: Optional[float] = None
500
+ timeout: float | None = None
502
501
  ) -> Generator[CFuture]:
503
502
  """
504
503
  Return the generator of added task instance.
@@ -601,7 +600,7 @@ class RAsyncPool(object):
601
600
  async_func: Callable[..., Coroutine],
602
601
  *args: Any,
603
602
  _max_async: int = 10,
604
- _exc_handler: Optional[Callable] = None,
603
+ _exc_handler: Callable | None = None,
605
604
  **kwargs: Any
606
605
  ) -> None:
607
606
  """
@@ -783,7 +782,7 @@ class RAsyncPool(object):
783
782
 
784
783
  def get(
785
784
  self,
786
- timeout: Optional[float] = None
785
+ timeout: float | None = None
787
786
  ) -> Any:
788
787
  """
789
788
  Get one execution result of asynchronous `Coroutine`, will block.
reykit/rnumber.py CHANGED
@@ -9,7 +9,7 @@
9
9
  """
10
10
 
11
11
 
12
- from typing import Any, Union
12
+ from typing import Any
13
13
 
14
14
  from .rexception import throw
15
15
 
@@ -21,7 +21,7 @@ __all__ = (
21
21
  )
22
22
 
23
23
 
24
- def digits(number: Union[int, float]) -> tuple[int, int]:
24
+ def digits(number: int | float) -> tuple[int, int]:
25
25
  """
26
26
  Judge the number of integer digits and decimal digits.
27
27
 
reykit/ros.py CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
  from __future__ import annotations
13
- from typing import Any, Union, Literal, Optional, NoReturn, overload
13
+ from typing import Any, Literal, NoReturn, overload
14
14
  from io import TextIOBase, BufferedIOBase
15
15
  from os import (
16
16
  walk as os_walk,
@@ -76,12 +76,12 @@ __all__ = (
76
76
  type FilePath = str
77
77
  type FileText = str
78
78
  type FileData = bytes
79
- type FileStr = Union[FilePath, FileText, TextIOBase]
80
- type FileBytes = Union[FilePath, FileData, BufferedIOBase]
81
- type File = Union[FileStr, FileBytes]
79
+ type FileStr = FilePath | FileText | TextIOBase
80
+ type FileBytes = FilePath | FileData | BufferedIOBase
81
+ type File = FileStr | FileBytes
82
82
 
83
83
 
84
- def get_md5(file: Union[str, bytes]) -> str:
84
+ def get_md5(file: str | bytes) -> str:
85
85
  """
86
86
  Get file MD5.
87
87
 
@@ -265,7 +265,7 @@ def get_file_bytes(file: FileBytes) -> bytes:
265
265
  return file_bytes
266
266
 
267
267
 
268
- def read_toml(path: Union[str, RFile]) -> dict[str, Any]:
268
+ def read_toml(path: str | RFile) -> dict[str, Any]:
269
269
  """
270
270
  Read and parse TOML file.
271
271
  Treat nan as a None or null value.
@@ -338,7 +338,7 @@ class RFile(object):
338
338
  def read(
339
339
  self,
340
340
  type_: Literal['str', 'bytes'] = 'bytes'
341
- ) -> Union[bytes, str]:
341
+ ) -> bytes | str:
342
342
  """
343
343
  Read file data.
344
344
 
@@ -371,7 +371,7 @@ class RFile(object):
371
371
 
372
372
  def write(
373
373
  self,
374
- data: Optional[Any] = '',
374
+ data: Any | None = '',
375
375
  append: bool = False
376
376
  ) -> None:
377
377
  """
@@ -735,7 +735,7 @@ class RFile(object):
735
735
 
736
736
  def __contains__(
737
737
  self,
738
- value: Union[str, bytes]
738
+ value: str | bytes
739
739
  ) -> bool:
740
740
  """
741
741
  Judge if file text contain value.
@@ -775,7 +775,7 @@ class RFolder(object):
775
775
 
776
776
  def __init__(
777
777
  self,
778
- path: Optional[str] = None
778
+ path: str | None = None
779
779
  ) -> None:
780
780
  """
781
781
  Build `folder` attributes.
@@ -873,7 +873,7 @@ class RFolder(object):
873
873
  pattern: str,
874
874
  recursion: bool = False,
875
875
  all_ : Literal[False] = False
876
- ) -> Optional[str]: ...
876
+ ) -> str | None: ...
877
877
 
878
878
  @overload
879
879
  def search(
@@ -888,7 +888,7 @@ class RFolder(object):
888
888
  pattern: str,
889
889
  recursion: bool = False,
890
890
  all_ : bool = False
891
- ) -> Optional[str]:
891
+ ) -> str | None:
892
892
  """
893
893
  Search file by name.
894
894
 
@@ -1149,8 +1149,8 @@ class RTempFile(object):
1149
1149
 
1150
1150
  def __init__(
1151
1151
  self,
1152
- dir_: Optional[str] = None,
1153
- suffix: Optional[str] = None,
1152
+ dir_: str | None = None,
1153
+ suffix: str | None = None,
1154
1154
  type_: Literal['str', 'bytes'] = 'bytes'
1155
1155
  ) -> None:
1156
1156
  """
@@ -1181,7 +1181,7 @@ class RTempFile(object):
1181
1181
  self.path = self.file.name
1182
1182
 
1183
1183
 
1184
- def read(self) -> Union[bytes, str]:
1184
+ def read(self) -> bytes | str:
1185
1185
  """
1186
1186
  Read file data.
1187
1187
 
@@ -1199,7 +1199,7 @@ class RTempFile(object):
1199
1199
 
1200
1200
  def write(
1201
1201
  self,
1202
- data: Union[str, bytes]
1202
+ data: str | bytes
1203
1203
  ) -> None:
1204
1204
  """
1205
1205
  Write file data.
@@ -1391,7 +1391,7 @@ class RTempFile(object):
1391
1391
 
1392
1392
  def __contains__(
1393
1393
  self,
1394
- value: Union[str, bytes]
1394
+ value: str | bytes
1395
1395
  ) -> bool:
1396
1396
  """
1397
1397
  Judge if file text contain value.
@@ -1434,7 +1434,7 @@ class RTempFolder(object):
1434
1434
 
1435
1435
  def __init__(
1436
1436
  self,
1437
- dir_: Optional[str] = None
1437
+ dir_: str | None = None
1438
1438
  ) -> None:
1439
1439
  """
1440
1440
  Build `temporary folder` attributes.
@@ -1529,7 +1529,7 @@ class RTempFolder(object):
1529
1529
  pattern: str,
1530
1530
  recursion: bool = False,
1531
1531
  all_ : Literal[False] = False
1532
- ) -> Optional[str]: ...
1532
+ ) -> str | None: ...
1533
1533
 
1534
1534
  @overload
1535
1535
  def search(
@@ -1544,7 +1544,7 @@ class RTempFolder(object):
1544
1544
  pattern: str,
1545
1545
  recursion: bool = False,
1546
1546
  all_ : bool = False
1547
- ) -> Optional[str]:
1547
+ ) -> str | None:
1548
1548
  """
1549
1549
  Search file by name.
1550
1550
 
@@ -1762,7 +1762,7 @@ class RTempFolder(object):
1762
1762
 
1763
1763
  def doc_to_docx(
1764
1764
  path: str,
1765
- save_path: Optional[str] = None
1765
+ save_path: str | None = None
1766
1766
  ) -> str:
1767
1767
  """
1768
1768
  Convert `DOC` file to `DOCX` file.
reykit/rrandom.py CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
  from __future__ import annotations
13
- from typing import Dict, Union, Optional, Literal, Self, overload
13
+ from typing import Literal, Self, overload
14
14
  from types import TracebackType
15
15
  from collections.abc import Sequence
16
16
  from string import digits as string_digits, ascii_letters as string_ascii_letters, punctuation as string_punctuation
@@ -42,7 +42,7 @@ class RConfigRandom(object, metaclass=RConfigMeta):
42
42
  """
43
43
 
44
44
  # RRandom.
45
- _rrandom_dict: Dict[int, RRandomSeed] = {}
45
+ _rrandom_dict: dict[int, RRandomSeed] = {}
46
46
 
47
47
 
48
48
  class RRandomSeed(object):
@@ -64,7 +64,7 @@ class RRandomSeed(object):
64
64
  """
65
65
 
66
66
 
67
- def __init__(self, seed: Optional[Union[int, float, str, bytes, bytearray]] = None) -> None:
67
+ def __init__(self, seed: int | float | str | bytes | bytearray | None = None) -> None:
68
68
  """
69
69
  Build `random` attributes.
70
70
 
@@ -72,7 +72,7 @@ class RRandomSeed(object):
72
72
  ----------
73
73
  seed : Random seed.
74
74
  - `None`: Clear seed.
75
- - `Union[int, float, str, bytes, bytearray]` : Set seed.
75
+ - `int | float | str | bytes | bytearray` : Set seed.
76
76
  """
77
77
 
78
78
  # Delete.
@@ -114,9 +114,9 @@ class RRandomSeed(object):
114
114
 
115
115
  def __exit__(
116
116
  self,
117
- exc_type: Optional[type[BaseException]],
118
- exc_instance: Optional[BaseException],
119
- exc_traceback: Optional[TracebackType]
117
+ exc_type: type[BaseException] | None,
118
+ exc_instance: BaseException | None,
119
+ exc_traceback: TracebackType | None
120
120
  ) -> None:
121
121
  """
122
122
  Exit syntax `with`.
@@ -158,8 +158,8 @@ def randn(
158
158
 
159
159
  def randn(
160
160
  *thresholds: float,
161
- precision: Optional[int] = None
162
- ) -> Union[int, float]:
161
+ precision: int | None = None
162
+ ) -> int | float:
163
163
  """
164
164
  Random number.
165
165
 
@@ -273,9 +273,9 @@ def randi(
273
273
 
274
274
  def randi(
275
275
  data: Sequence,
276
- multi: Optional[int] = None,
276
+ multi: int | None = None,
277
277
  unique: bool = True
278
- ) -> Union[Element, list[Element]]:
278
+ ) -> Element | list[Element]:
279
279
  """
280
280
  Random index data element.
281
281
 
reykit/rregex.py CHANGED
@@ -9,7 +9,7 @@
9
9
  """
10
10
 
11
11
 
12
- from typing import Optional, Union, Literal, overload
12
+ from typing import Literal, overload
13
13
  from collections.abc import Callable
14
14
  from re import (
15
15
  search as re_search,
@@ -38,7 +38,7 @@ __all__ = (
38
38
  def search(
39
39
  pattern: str,
40
40
  text: str
41
- ) -> Optional[Union[str, tuple[Optional[str], ...]]]:
41
+ ) -> str | tuple[str | None, ...] | None:
42
42
  """
43
43
  Regular search text.
44
44
 
@@ -73,7 +73,7 @@ def search(
73
73
  def findall(
74
74
  pattern: str,
75
75
  text: str,
76
- ) -> Union[list[str], list[tuple[str, ...]]]:
76
+ ) -> list[str] | list[tuple[str, ...]]:
77
77
  """
78
78
  Regular find all text.
79
79
 
@@ -96,8 +96,8 @@ def findall(
96
96
  def sub(
97
97
  pattern: str,
98
98
  text: str,
99
- replace: Optional[Union[str, Callable[[RMatch], str]]] = None,
100
- count: Optional[int] = None
99
+ replace: str | Callable[[RMatch], str] | None = None,
100
+ count: int | None = None
101
101
  ) -> str:
102
102
  """
103
103
  Regular replace text.
@@ -130,7 +130,7 @@ def sub(
130
130
  def split(
131
131
  pattern: str,
132
132
  text: str,
133
- count: Optional[int] = None
133
+ count: int | None = None
134
134
  ) -> list[str]:
135
135
  """
136
136
  Regular split text.
@@ -161,23 +161,20 @@ def search_batch(
161
161
  text: str,
162
162
  *patterns: str,
163
163
  first: Literal[True] = True
164
- ) -> Optional[Union[str, tuple[Optional[str], ...]]]: ...
164
+ ) -> str | tuple[str | None, ...] | None: ...
165
165
 
166
166
  @overload
167
167
  def search_batch(
168
168
  text: str,
169
169
  *patterns: str,
170
170
  first: Literal[False] = True
171
- ) -> list[Optional[Union[str, tuple[Optional[str], ...]]]]: ...
171
+ ) -> list[str | tuple[str | None, ...] | None]: ...
172
172
 
173
173
  def search_batch(
174
174
  text: str,
175
175
  *patterns: str,
176
176
  first: bool = True
177
- ) -> Union[
178
- Optional[Union[str, tuple[Optional[str], ...]]],
179
- list[Optional[Union[str, tuple[Optional[str], ...]]]]
180
- ]:
177
+ ) -> str | tuple[str | None, ...] | list[str | tuple[str | None, ...] | None] | None:
181
178
  """
182
179
  Batch regular search text.
183
180
 
@@ -237,7 +234,7 @@ def findall_batch(text: str, *patterns: str) -> str:
237
234
  return texts
238
235
 
239
236
 
240
- def sub_batch(text: str, *patterns: Union[str, tuple[str, Union[str, Callable[[RMatch], str]]]]) -> str:
237
+ def sub_batch(text: str, *patterns: str | tuple[str, str | Callable[[RMatch], str]]) -> str:
241
238
  """
242
239
  Batch regular replace text.
243
240
 
reykit/rschedule.py CHANGED
@@ -9,7 +9,7 @@
9
9
  """
10
10
 
11
11
 
12
- from typing import Any, Literal, Union, Optional
12
+ from typing import Any, Literal
13
13
  from collections.abc import Callable
14
14
  from apscheduler.executors.pool import ThreadPoolExecutor
15
15
  from apscheduler.schedulers.background import BackgroundScheduler
@@ -123,8 +123,8 @@ class RSchedule(object):
123
123
  self,
124
124
  func: Callable,
125
125
  trigger: Literal['date', 'interval', 'cron'] = 'date',
126
- args: Optional[tuple] = None,
127
- kwargs: Optional[dict] = None,
126
+ args: tuple | None = None,
127
+ kwargs: dict | None = None,
128
128
  **trigger_kwargs: Any
129
129
  ) -> Job:
130
130
  """
@@ -157,10 +157,10 @@ class RSchedule(object):
157
157
 
158
158
  def modify_task(
159
159
  self,
160
- task: Union[Job, str],
161
- trigger: Optional[Literal['date', 'interval', 'cron']] = None,
162
- args: Optional[tuple] = None,
163
- kwargs: Optional[dict] = None,
160
+ task: Job | str,
161
+ trigger: Literal['date', 'interval', 'cron'] | None = None,
162
+ args: tuple | None = None,
163
+ kwargs: dict | None = None,
164
164
  **trigger_kwargs: Any
165
165
  ) -> None:
166
166
  """
@@ -205,7 +205,7 @@ class RSchedule(object):
205
205
 
206
206
  def remove_task(
207
207
  self,
208
- task: Union[Job, str]
208
+ task: Job | str
209
209
  ) -> None:
210
210
  """
211
211
  Remove task.
@@ -227,7 +227,7 @@ class RSchedule(object):
227
227
 
228
228
  def pause_task(
229
229
  self,
230
- task: Union[Job, str]
230
+ task: Job | str
231
231
  ) -> None:
232
232
  """
233
233
  Pause task.
@@ -249,7 +249,7 @@ class RSchedule(object):
249
249
 
250
250
  def resume_task(
251
251
  self,
252
- task: Union[Job, str]
252
+ task: Job | str
253
253
  ) -> None:
254
254
  """
255
255
  Resume task.
reykit/rstdout.py CHANGED
@@ -9,7 +9,7 @@
9
9
  """
10
10
 
11
11
 
12
- from typing import Any, Literal, Optional, Union, Final, Self
12
+ from typing import Any, Literal, Final, Self
13
13
  from collections.abc import Callable
14
14
  import sys
15
15
  from io import TextIOWrapper
@@ -60,9 +60,9 @@ class RConfigStdout(object, metaclass=RConfigMeta):
60
60
 
61
61
  def beautify_text(
62
62
  data: tuple[Any],
63
- title: Union[bool, str] = True,
64
- width: Optional[int] = None,
65
- frame: Optional[Literal['full', 'half', 'top', 'half_plain', 'top_plain']] = 'full'
63
+ title: bool | str = True,
64
+ width: int | None = None,
65
+ frame: Literal['full', 'half', 'top', 'half_plain', 'top_plain'] | None = 'full'
66
66
  ) -> str:
67
67
  """
68
68
  Beautify data to text.
@@ -132,9 +132,9 @@ def beautify_text(
132
132
 
133
133
  def echo(
134
134
  *data: Any,
135
- title: Union[bool, str] = True,
136
- width: Optional[int] = None,
137
- frame: Optional[Literal['full', 'half', 'top', 'half_plain', 'top_plain']] = 'full'
135
+ title: bool | str = True,
136
+ width: int | None = None,
137
+ frame: Literal['full', 'half', 'top', 'half_plain', 'top_plain'] | None = 'full'
138
138
  ) -> str:
139
139
  """
140
140
  Beautify data to text, and print.
@@ -176,10 +176,10 @@ def echo(
176
176
 
177
177
  def rinput(
178
178
  *data: Any,
179
- title: Union[bool, str] = True,
180
- width: Optional[int] = None,
181
- frame: Optional[Literal['full', 'half', 'top', 'half_plain', 'top_plain']] = 'full',
182
- extra: Optional[str] = None
179
+ title: bool | str = True,
180
+ width: int | None = None,
181
+ frame: Literal['full', 'half', 'top', 'half_plain', 'top_plain'] | None = 'full',
182
+ extra: str | None = None
183
183
  ) -> str:
184
184
  """
185
185
  Beautify data to text, and print data, and read string from standard input.
@@ -251,7 +251,7 @@ def start_print() -> None:
251
251
  RConfigStdout._stoped = False
252
252
 
253
253
 
254
- def modify_print(preprocess: Callable[[str], Optional[str]]) -> None:
254
+ def modify_print(preprocess: Callable[[str], str] | None) -> None:
255
255
  """
256
256
  Modify standard output print write method.
257
257
 
@@ -264,7 +264,7 @@ def modify_print(preprocess: Callable[[str], Optional[str]]) -> None:
264
264
 
265
265
 
266
266
  # Define.
267
- def write(__s: str) -> Optional[int]:
267
+ def write(__s: str) -> int | None:
268
268
  """
269
269
  Modified standard output write method.
270
270