intuned-runtime 1.1.0__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.
@@ -3,7 +3,7 @@ import os
3
3
 
4
4
  import arguably
5
5
 
6
- from runtime.browser import launch_chromium
6
+ from runtime.browser import launch_browser
7
7
  from runtime.browser.storage_state import get_storage_state
8
8
 
9
9
 
@@ -21,7 +21,7 @@ async def browser__save_state(
21
21
  output_path (str): Path to save browser state to.
22
22
  """
23
23
 
24
- async with launch_chromium(
24
+ async with launch_browser(
25
25
  cdp_address=cdp_address,
26
26
  ) as (context, _):
27
27
  storage_state = await get_storage_state(context)
@@ -3,7 +3,7 @@ import os
3
3
 
4
4
  import arguably
5
5
 
6
- from runtime.browser import launch_chromium
6
+ from runtime.browser import launch_browser
7
7
  from runtime.browser.storage_state import set_storage_state
8
8
  from runtime.run.intuned_settings import load_intuned_settings
9
9
  from runtime.types.run_types import StorageState
@@ -26,7 +26,7 @@ async def project__auth_session__load(
26
26
  if not intuned_settings.auth_sessions.enabled:
27
27
  raise Exception("Auth sessions are not enabled")
28
28
 
29
- async with launch_chromium(
29
+ async with launch_browser(
30
30
  cdp_address=cdp_address,
31
31
  ) as (context, _):
32
32
  auth_session_path = os.path.join(os.getcwd(), auth_session_path)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: intuned-runtime
3
- Version: 1.1.0
3
+ Version: 1.1.1
4
4
  Summary: Runtime commands for Intuned platform Python scrapers
5
5
  License: Elastic-2.0
6
6
  Keywords: runtime,intuned
@@ -17,6 +17,8 @@ Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Programming Language :: Python :: 3.13
18
18
  Requires-Dist: aiofiles (>=24.1.0,<25.0.0)
19
19
  Requires-Dist: arguably (>=1.3.0,<2.0.0)
20
+ Requires-Dist: browserforge[all]
21
+ Requires-Dist: camoufox[geoip] (>=0.4.11,<0.5.0)
20
22
  Requires-Dist: gitpython (>=3.1.43,<4.0.0)
21
23
  Requires-Dist: httpx (>=0.23.0,<1)
22
24
  Requires-Dist: more-termcolor (>=1.1.3,<2.0.0)
@@ -40,13 +40,13 @@ intuned_internal_cli/commands/ai_source/__init__.py,sha256=lg7owgcK8owNn2a4VBUP9
40
40
  intuned_internal_cli/commands/ai_source/ai_source.py,sha256=2woQtCmhxKvLfEz832eUoCT9gMsuSvEE6rMnHSYXC7w,138
41
41
  intuned_internal_cli/commands/ai_source/deploy.py,sha256=NpomuP_2mo5SLKe7BZoY5H0Pp36aDtkYU_CyihqOvdI,2457
42
42
  intuned_internal_cli/commands/browser/__init__.py,sha256=AuVbvh7aSBTFKYvewXZyPoIvfBTe2uHiPcnaAkzapas,95
43
- intuned_internal_cli/commands/browser/save_state.py,sha256=eHKfvBfeFR_U9VQbsjOnIZjWepyDjNn9NL3naDYWP2s,841
43
+ intuned_internal_cli/commands/browser/save_state.py,sha256=_gfspwLkk6j1zBzqY1Qr7KnEMjGP6x10Q2IvKdfjyuI,839
44
44
  intuned_internal_cli/commands/init.py,sha256=8rWBenWZfwNtLxOBqhEMbOATyQNEnmDUmrFJ1xBGyxI,4384
45
45
  intuned_internal_cli/commands/project/__init__.py,sha256=t97wvhSenerYRdbSeCKXqHASA6EWA3lc1hnRhF9baOE,734
46
46
  intuned_internal_cli/commands/project/auth_session/__init__.py,sha256=gt7mlaW6xmqAc_4-pfF_FiecsR51C6fqCaq_NFbcbwA,300
47
47
  intuned_internal_cli/commands/project/auth_session/check.py,sha256=AFILp7m34nAO_RD3IfRpuJm5Zh0wnCRtBXqIrerdbwo,4565
48
48
  intuned_internal_cli/commands/project/auth_session/create.py,sha256=r-eYu3uLUo2mzF836CbVgu4oBzcIIDekzzFwwekxmg0,3374
49
- intuned_internal_cli/commands/project/auth_session/load.py,sha256=UUvg9Vyj15xiR44XlJzojLoFm5esv-o4E3qA3JqnBsE,1201
49
+ intuned_internal_cli/commands/project/auth_session/load.py,sha256=Y0V6bFZQeHq_lTtR-rQvM9SSbExWhVVMFu-Uykl-9k4,1199
50
50
  intuned_internal_cli/commands/project/project.py,sha256=_MSh6Xor2Cbh-ItifwgOPq_BP8UDuKB7S6w796FULKQ,137
51
51
  intuned_internal_cli/commands/project/run.py,sha256=FDYYkU24aURYbljyYLFo8wLF-nvb86EVr9gMEjAfeE0,12274
52
52
  intuned_internal_cli/commands/project/run_interface.py,sha256=4RyR8WZriIF7Va4z1wt-q6zZDQOI31n62Ho2dyimzUY,8717
@@ -63,12 +63,15 @@ runtime/__init__.py,sha256=87gDXuxUv_kGzQfuB1mh6DF-dDysJN8r684c7jGnHxc,144
63
63
  runtime/backend_functions/__init__.py,sha256=j2EaK4FK8bmdFtqc5FxtFwx1KhIn_7qKPChrrAhJI3s,119
64
64
  runtime/backend_functions/_call_backend_function.py,sha256=zuaf4mwYHSm5RTedhMdU66jAMAzdPYPMmXJE_V1xoyk,2869
65
65
  runtime/backend_functions/get_auth_session_parameters.py,sha256=pOvB7XiWpphEuBpazdKALw9EWgBU1PeY3gkzBfVLpkc,869
66
- runtime/browser/__init__.py,sha256=CRBpMS319LBz2FLxDjjCvQdOUCgHLIrQFscr_Zi5Hm0,160
67
- runtime/browser/launch_chromium.py,sha256=OVaE8ezjxCYA1NUSDdd3FczrfNCpG_528Vmsv4S6QGU,7916
66
+ runtime/browser/__init__.py,sha256=EPWfa4ZmdR8GJqh2qcsx1ZvHmCYiUYrQ-zeHYVapH9s,285
67
+ runtime/browser/helpers.py,sha256=b1Xp005adbl7ZeJrSEYgH2OPzrZEHxTPgGTsnS3OqS0,554
68
+ runtime/browser/launch_browser.py,sha256=f71hLUDbIBEv5hhQVOQFTXleUm_X1kmEpp0kTx0SqZo,966
69
+ runtime/browser/launch_camoufox.py,sha256=8dg14UfN9nBA7T075UQFhpyhvJD_aVqLdDJTNiwU0FY,1752
70
+ runtime/browser/launch_chromium.py,sha256=0i0IWQO5rByPw56F_OsUp8Z55Qn2-ETQ6q5B2aXvNv4,7456
68
71
  runtime/browser/storage_state.py,sha256=fwLg8sP-H-vgt_6AJKNl03CpgyMVCQWWcN2cqswTQMs,3603
69
72
  runtime/context/__init__.py,sha256=hg8ejm4bJy4tNkwmZ9lKgYJx6bU7OgOdBS684Uv5XGg,73
70
73
  runtime/context/context.py,sha256=pl_0x77_d5CiAznz1qGSk6o9cW-msNvlCt-2eFoMKlA,1739
71
- runtime/env.py,sha256=h4BJI-XVSZKgtTxjkzj2HsyN3DlY5Ml9GZqeH4CKDE8,238
74
+ runtime/env.py,sha256=OXxzLpM56AJVlX0gmG7Ph82xAfqZboW3kv2232lzXb4,306
72
75
  runtime/errors/__init__.py,sha256=oqiBSvT_yFLQ3hG0AbCUA3WYFaxkTDVkDMSy59xvBCo,688
73
76
  runtime/errors/auth_session_errors.py,sha256=6b4XTI8UCDHDPX4jEA8_HyrNUp4VZ1TrEA8DRh6Z3rM,228
74
77
  runtime/errors/run_api_errors.py,sha256=LdmOEHoUk7wjWSk0HQYqslfJNNmxVgga_0bankzvX-s,3341
@@ -80,7 +83,7 @@ runtime/helpers/get_auth_session_parameters.py,sha256=7bopGhJ7vjKAn_UxnHSAah-k2r
80
83
  runtime/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
84
  runtime/run/__init__.py,sha256=zxMYVb7hn147YTrhMLsrcX6-KTd71HLrYHstJOWeWXQ,52
82
85
  runtime/run/intuned_settings.py,sha256=vy2-ktEzUfUp5Z90dp3l7jPKHNjgB-8GSMDgAY-rYaU,1074
83
- runtime/run/playwright_constructs.py,sha256=UZvP502fk4Hk8xtI9jMlyJ7jHLJsWt2SZyZjhet7L1A,576
86
+ runtime/run/playwright_constructs.py,sha256=EIfnRlAi1k1wRiTT2OpPFVmrWwEeeiryuORibaLD1Xw,573
84
87
  runtime/run/pydantic_encoder.py,sha256=wJCljwwINSICvCJ0i2izp2RLkQ15nYglUQCyyjM40Jk,332
85
88
  runtime/run/run_api.py,sha256=iYekBi-mkBuBNvLIBXQ6RWvEDN7JhjSlX3i7a2td2P8,8952
86
89
  runtime/run/traces.py,sha256=fKzh11LqV47ujgq_9I2tdp-dgld566wffWaHwU_4gis,1123
@@ -89,8 +92,8 @@ runtime/types/payload.py,sha256=sty8HgDEn3nJbZrwEOMCXyuG7_ICGDwlBIIWSON5ABY,124
89
92
  runtime/types/run_types.py,sha256=-j-XKXfRkzlyoW-Doe0og2jbqMMQWjOTIUqRFEc8lHA,4582
90
93
  runtime_helpers/__init__.py,sha256=XBrEiE9yNC8Lgn8NgIkqNXbI6e4ap237E83Zj_nlhCQ,249
91
94
  runtime_helpers/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
- intuned_runtime-1.1.0.dist-info/LICENSE,sha256=9LIjQdgyU_ptzNIfItNCR7VmEHqYnrY1f1XwOreKFI0,3714
93
- intuned_runtime-1.1.0.dist-info/METADATA,sha256=SO-KZ2dpNlLDzqEQBZcOMC8_oie3r2wyw2D9ZSigXWQ,5217
94
- intuned_runtime-1.1.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
95
- intuned_runtime-1.1.0.dist-info/entry_points.txt,sha256=ToMS2cqDeRmF1FGkflwoeD-Xz6jJV5p1zIbw9G7IxMg,85
96
- intuned_runtime-1.1.0.dist-info/RECORD,,
95
+ intuned_runtime-1.1.1.dist-info/LICENSE,sha256=9LIjQdgyU_ptzNIfItNCR7VmEHqYnrY1f1XwOreKFI0,3714
96
+ intuned_runtime-1.1.1.dist-info/METADATA,sha256=X7RhKRebpDcNZzUCoO4YvgAvToqPrh6UL8ad8ysB0l0,5299
97
+ intuned_runtime-1.1.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
98
+ intuned_runtime-1.1.1.dist-info/entry_points.txt,sha256=ToMS2cqDeRmF1FGkflwoeD-Xz6jJV5p1zIbw9G7IxMg,85
99
+ intuned_runtime-1.1.1.dist-info/RECORD,,
@@ -1,4 +1,6 @@
1
+ from .launch_browser import launch_browser
2
+ from .launch_camoufox import launch_camoufox
1
3
  from .launch_chromium import dangerous_launch_chromium
2
4
  from .launch_chromium import launch_chromium
3
5
 
4
- __all__ = ["launch_chromium", "dangerous_launch_chromium"]
6
+ __all__ = ["launch_chromium", "dangerous_launch_chromium", "launch_camoufox", "launch_browser"]
@@ -0,0 +1,21 @@
1
+ import os
2
+ from typing import Optional
3
+ from typing import TYPE_CHECKING
4
+
5
+ from playwright.async_api import ProxySettings
6
+
7
+ if TYPE_CHECKING:
8
+ from playwright.async_api import ProxySettings
9
+
10
+
11
+ def get_proxy_env() -> Optional["ProxySettings"]:
12
+ server = os.getenv("PROXY_SERVER")
13
+ username = os.getenv("PROXY_USERNAME")
14
+ password = os.getenv("PROXY_PASSWORD")
15
+ if server is None or username is None or password is None:
16
+ return None
17
+ return {
18
+ "server": server,
19
+ "username": username,
20
+ "password": password,
21
+ }
@@ -0,0 +1,31 @@
1
+ from contextlib import asynccontextmanager
2
+
3
+ from playwright.async_api import ProxySettings
4
+
5
+ from runtime.env import get_browser_type
6
+
7
+ from .launch_camoufox import launch_camoufox
8
+ from .launch_chromium import launch_chromium
9
+
10
+
11
+ @asynccontextmanager
12
+ async def launch_browser(
13
+ proxy: ProxySettings | None = None,
14
+ headless: bool = False,
15
+ *,
16
+ cdp_address: str | None = None,
17
+ ):
18
+ browser_type = get_browser_type()
19
+ match browser_type:
20
+ case "camoufox":
21
+ async with launch_camoufox(headless=headless, proxy=proxy) as (context, page):
22
+ try:
23
+ yield context, page
24
+ finally:
25
+ await context.close()
26
+ case "chromium" | _:
27
+ async with launch_chromium(headless=headless, cdp_address=cdp_address, proxy=proxy) as (context, page):
28
+ try:
29
+ yield context, page
30
+ finally:
31
+ await context.close()
@@ -0,0 +1,61 @@
1
+ import logging
2
+ import os
3
+ from contextlib import asynccontextmanager
4
+ from typing import Any
5
+ from typing import AsyncGenerator
6
+ from typing import Tuple
7
+
8
+ import anyio
9
+ from camoufox.async_api import AsyncCamoufox
10
+ from playwright.async_api import Browser
11
+ from playwright.async_api import BrowserContext
12
+ from playwright.async_api import Page
13
+
14
+ from .helpers import get_proxy_env
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ async def create_user_dir():
20
+ # Create a temporary directory
21
+ playwright_temp_dir = anyio.Path(await anyio.mkdtemp(prefix="pw-"))
22
+ user_dir = playwright_temp_dir / "userdir"
23
+
24
+ return await user_dir.absolute()
25
+
26
+
27
+ @asynccontextmanager
28
+ async def launch_camoufox(
29
+ headless: bool = True,
30
+ timeout: int = 10,
31
+ **kwargs: Any,
32
+ ) -> AsyncGenerator[Tuple[BrowserContext, Page], None]:
33
+ dir = await create_user_dir()
34
+ if kwargs.get("proxy") is None:
35
+ proxy_env = get_proxy_env()
36
+ else:
37
+ proxy_env = kwargs.get("proxy")
38
+ kwargs.pop("proxy", None)
39
+ async with AsyncCamoufox(
40
+ headless=headless,
41
+ config={"forceScopeAccess": True}, # required
42
+ disable_coop=True,
43
+ geoip=True,
44
+ proxy=proxy_env,
45
+ persistent_context=True,
46
+ user_data_dir=dir,
47
+ i_know_what_im_doing=True,
48
+ ) as camoufox:
49
+ if isinstance(camoufox, Browser):
50
+ context = await camoufox.new_context()
51
+ else:
52
+ context = camoufox
53
+ context.set_default_timeout(timeout * 1000)
54
+
55
+ async def remove_dir_after_close(*_: Any, **__: Any) -> None:
56
+ if not dir:
57
+ return
58
+ os.system(f"rm -rf {os.path.realpath(dir)}")
59
+
60
+ context.once("close", remove_dir_after_close)
61
+ yield context, context.pages[0]
@@ -4,30 +4,14 @@ import logging
4
4
  import os
5
5
  from contextlib import asynccontextmanager
6
6
  from typing import Any
7
- from typing import Optional
8
- from typing import TYPE_CHECKING
9
7
 
10
8
  import anyio
11
9
 
12
- if TYPE_CHECKING:
13
- from playwright.async_api import ProxySettings
10
+ from .helpers import get_proxy_env
14
11
 
15
12
  logger = logging.getLogger(__name__)
16
13
 
17
14
 
18
- def get_proxy_env() -> Optional["ProxySettings"]:
19
- server = os.getenv("PROXY_SERVER")
20
- username = os.getenv("PROXY_USERNAME")
21
- password = os.getenv("PROXY_PASSWORD")
22
- if server is None or username is None or password is None:
23
- return None
24
- return {
25
- "server": server,
26
- "username": username,
27
- "password": password,
28
- }
29
-
30
-
31
15
  chromium_launch_args_to_ignore = [
32
16
  "--disable-field-trial-config",
33
17
  "--disable-background-networking",
runtime/env.py CHANGED
@@ -11,3 +11,7 @@ def get_project_id():
11
11
 
12
12
  def get_functions_domain():
13
13
  return os.environ.get("FUNCTIONS_DOMAIN")
14
+
15
+
16
+ def get_browser_type():
17
+ return os.environ.get("BROWSER_TYPE")
@@ -3,8 +3,7 @@ from typing import TYPE_CHECKING
3
3
 
4
4
  if TYPE_CHECKING:
5
5
  from playwright.async_api import ProxySettings
6
-
7
- from ..browser import launch_chromium
6
+ from ..browser import launch_browser
8
7
 
9
8
 
10
9
  @asynccontextmanager
@@ -14,7 +13,7 @@ async def get_production_playwright_constructs(
14
13
  *,
15
14
  cdp_address: str | None = None,
16
15
  ):
17
- async with launch_chromium(headless=headless, cdp_address=cdp_address, proxy=proxy) as (context, page):
16
+ async with launch_browser(headless=headless, cdp_address=cdp_address, proxy=proxy) as (context, page):
18
17
  try:
19
18
  yield context, page
20
19
  finally: