solara-enterprise 1.30.0__py2.py3-none-any.whl → 1.31.0__py2.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.
- solara_enterprise/__init__.py +2 -1
- solara_enterprise/search/index.py +1 -1
- solara_enterprise/ssg.py +45 -16
- {solara_enterprise-1.30.0.dist-info → solara_enterprise-1.31.0.dist-info}/METADATA +3 -2
- {solara_enterprise-1.30.0.dist-info → solara_enterprise-1.31.0.dist-info}/RECORD +7 -7
- {solara_enterprise-1.30.0.dist-info → solara_enterprise-1.31.0.dist-info}/WHEEL +1 -1
- {solara_enterprise-1.30.0.dist-info → solara_enterprise-1.31.0.dist-info}/licenses/LICENSE +0 -0
solara_enterprise/__init__.py
CHANGED
|
@@ -56,7 +56,7 @@ def add_document(base_url: str, route: solara.Route, build_path: Path, documents
|
|
|
56
56
|
else:
|
|
57
57
|
# split by h1 and h2
|
|
58
58
|
parts: List[List[Any]] = [[]]
|
|
59
|
-
ids = [
|
|
59
|
+
ids = []
|
|
60
60
|
titles = [soup.title.string if soup.title else ""]
|
|
61
61
|
current = parts[-1]
|
|
62
62
|
# remove invisible title elements
|
solara_enterprise/ssg.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import concurrent.futures.thread
|
|
1
2
|
import logging
|
|
2
|
-
import multiprocessing.pool
|
|
3
3
|
import threading
|
|
4
4
|
import time
|
|
5
5
|
import typing
|
|
6
6
|
import urllib
|
|
7
|
+
import weakref
|
|
7
8
|
from pathlib import Path
|
|
8
|
-
from typing import List, Optional
|
|
9
|
+
from typing import List, Optional, Tuple
|
|
9
10
|
|
|
10
11
|
import solara
|
|
11
12
|
from rich import print as rprint
|
|
@@ -29,7 +30,7 @@ class Playwright(threading.local):
|
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
pw = Playwright()
|
|
32
|
-
|
|
33
|
+
_used: List[Tuple["playwright.sync_api.Browser", "playwright.sync_api._context_manager.PlaywrightContextManager"]] = []
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
class SSGData(TypedDict):
|
|
@@ -44,15 +45,48 @@ def _get_playwright():
|
|
|
44
45
|
return pw
|
|
45
46
|
from playwright.sync_api import sync_playwright
|
|
46
47
|
|
|
48
|
+
pw.number = 42
|
|
47
49
|
pw.context_manager = sync_playwright()
|
|
48
50
|
pw.sync_playwright = pw.context_manager.start()
|
|
49
51
|
|
|
50
52
|
pw.browser = pw.sync_playwright.chromium.launch(headless=not settings.ssg.headed)
|
|
51
53
|
pw.page = pw.browser.new_page()
|
|
52
|
-
|
|
54
|
+
_used.append((pw.browser, pw.context_manager))
|
|
53
55
|
return pw
|
|
54
56
|
|
|
55
57
|
|
|
58
|
+
def _worker_with_cleanup(*args, **kwargs):
|
|
59
|
+
try:
|
|
60
|
+
concurrent.futures.thread._worker(*args, **kwargs)
|
|
61
|
+
finally:
|
|
62
|
+
pw = _get_playwright()
|
|
63
|
+
pw.browser.close()
|
|
64
|
+
pw.context_manager.__exit__(None, None, None)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class CleanupThreadPoolExecutor(concurrent.futures.ThreadPoolExecutor):
|
|
68
|
+
def _adjust_thread_count(self):
|
|
69
|
+
# copy of the original code with _worker replaced
|
|
70
|
+
# if idle threads are available, don't spin new threads
|
|
71
|
+
if self._idle_semaphore.acquire(timeout=0):
|
|
72
|
+
return
|
|
73
|
+
|
|
74
|
+
# When the executor gets lost, the weakref callback will wake up
|
|
75
|
+
# the worker threads.
|
|
76
|
+
def weakref_cb(_, q=self._work_queue):
|
|
77
|
+
q.put(None)
|
|
78
|
+
|
|
79
|
+
num_threads = len(self._threads)
|
|
80
|
+
if num_threads < self._max_workers:
|
|
81
|
+
thread_name = "%s_%d" % (self._thread_name_prefix or self, num_threads)
|
|
82
|
+
t = threading.Thread(
|
|
83
|
+
name=thread_name, target=_worker_with_cleanup, args=(weakref.ref(self, weakref_cb), self._work_queue, self._initializer, self._initargs)
|
|
84
|
+
)
|
|
85
|
+
t.start()
|
|
86
|
+
self._threads.add(t) # type: ignore
|
|
87
|
+
concurrent.futures.thread._threads_queues[t] = self._work_queue # type: ignore
|
|
88
|
+
|
|
89
|
+
|
|
56
90
|
def ssg_crawl(base_url: str):
|
|
57
91
|
license.check("SSG")
|
|
58
92
|
import solara.server.app
|
|
@@ -69,31 +103,26 @@ def ssg_crawl(base_url: str):
|
|
|
69
103
|
# although in theory we should be able to run this with multiple threads
|
|
70
104
|
# there are issues with uvloop:
|
|
71
105
|
# e.g.: "Racing with another loop to spawn a process."
|
|
72
|
-
thread_pool =
|
|
106
|
+
thread_pool = CleanupThreadPoolExecutor(max_workers=1)
|
|
73
107
|
|
|
74
108
|
results = []
|
|
75
109
|
for route in routes:
|
|
76
|
-
results.append(thread_pool.
|
|
110
|
+
results.append(thread_pool.submit(ssg_crawl_route, f"{base_url}/", route, build_path, thread_pool))
|
|
77
111
|
|
|
78
112
|
def wait(async_result):
|
|
79
|
-
results = async_result.
|
|
113
|
+
results = async_result.result()
|
|
80
114
|
for result in results:
|
|
81
115
|
wait(result)
|
|
82
116
|
|
|
83
117
|
for result in results:
|
|
84
118
|
wait(result)
|
|
85
|
-
|
|
86
|
-
thread_pool.
|
|
87
|
-
for pw in playwrights:
|
|
88
|
-
assert pw.browser is not None
|
|
89
|
-
assert pw.context_manager is not None
|
|
90
|
-
pw.browser.close()
|
|
91
|
-
pw.context_manager.__exit__(None, None, None)
|
|
119
|
+
|
|
120
|
+
thread_pool.shutdown()
|
|
92
121
|
|
|
93
122
|
rprint("Done building SSG")
|
|
94
123
|
|
|
95
124
|
|
|
96
|
-
def ssg_crawl_route(base_url: str, route: solara.Route, build_path: Path, thread_pool:
|
|
125
|
+
def ssg_crawl_route(base_url: str, route: solara.Route, build_path: Path, thread_pool: CleanupThreadPoolExecutor):
|
|
97
126
|
# if route
|
|
98
127
|
url = base_url + (route.path if route.path != "/" else "")
|
|
99
128
|
if not route.children:
|
|
@@ -146,7 +175,7 @@ def ssg_crawl_route(base_url: str, route: solara.Route, build_path: Path, thread
|
|
|
146
175
|
rprint(f"Skipping existing render: {path}")
|
|
147
176
|
results = []
|
|
148
177
|
for child in route.children:
|
|
149
|
-
result = thread_pool.
|
|
178
|
+
result = thread_pool.submit(ssg_crawl_route, url + "/", child, build_path / Path(route.path), thread_pool)
|
|
150
179
|
results.append(result)
|
|
151
180
|
return results
|
|
152
181
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: solara-enterprise
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.31.0
|
|
4
4
|
Dynamic: Summary
|
|
5
5
|
Project-URL: Home, https://www.github.com/widgetti/solara
|
|
6
6
|
Author-email: "Maarten A. Breddels" <maartenbreddels@gmail.com>, Mario Buikhuizen <mariobuikhuizen@gmail.com>
|
|
7
7
|
License: Not open source, contact contact@solara.dev for licencing.
|
|
8
8
|
License-File: LICENSE
|
|
9
9
|
Classifier: License :: Free for non-commercial use
|
|
10
|
-
Requires-Dist: solara==1.
|
|
10
|
+
Requires-Dist: solara-server==1.31.0
|
|
11
|
+
Requires-Dist: solara-ui==1.31.0
|
|
11
12
|
Provides-Extra: all
|
|
12
13
|
Requires-Dist: solara-enterprise[auth]; extra == 'all'
|
|
13
14
|
Requires-Dist: solara-enterprise[cache]; extra == 'all'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
solara_enterprise/__init__.py,sha256=
|
|
1
|
+
solara_enterprise/__init__.py,sha256=vG6BIPBmxJi9QnG-XEOBuf7G4XvVPTohOVlUVacScJg,57
|
|
2
2
|
solara_enterprise/license.py,sha256=GCGEs3x9rtKf0dYUcHkx-yteIQuRlgnS8hPbl9BDAXs,412
|
|
3
|
-
solara_enterprise/ssg.py,sha256=
|
|
3
|
+
solara_enterprise/ssg.py,sha256=uw3397RX0Qmg-OqOsgwaePDymhUvZTTFcBKkSWy1uCk,8935
|
|
4
4
|
solara_enterprise/auth/__init__.py,sha256=83RGLIkVJrb6R1iZxg5YS0R3kaCmqMHu4qs8S74LJXo,513
|
|
5
5
|
solara_enterprise/auth/components.py,sha256=mTazvLWJrduS6CrcsY60BJgkvQztH5X67CkOCRFXYV4,4038
|
|
6
6
|
solara_enterprise/auth/flask.py,sha256=Y__abnQPnP1cdQAkU8BBg9FuWMZ1rNnUmTLE_x19MlE,3539
|
|
@@ -14,10 +14,10 @@ solara_enterprise/cache/memory_size.py,sha256=5PAUaxVvHMIFINA3Z4z48zDvAATTFkEd0e
|
|
|
14
14
|
solara_enterprise/cache/multi_level.py,sha256=hMjruI1cwNwDajaRXAJ7TxQqfw5XWRvtYuAU7M4f_W8,710
|
|
15
15
|
solara_enterprise/cache/redis.py,sha256=_GlACNJ5hfpRJ2Hw_2k3ma6gwEVLoVNTplS0Q5cGcRk,779
|
|
16
16
|
solara_enterprise/search/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
-
solara_enterprise/search/index.py,sha256=
|
|
17
|
+
solara_enterprise/search/index.py,sha256=W98DC_6SmQDCfX5YcmS6OfZbO0LheleBmo0FUI7NOqU,3303
|
|
18
18
|
solara_enterprise/search/search.py,sha256=rnVHP81AwL0GR8s5vnNU6rpEIqCVnZSgwfFfCuoibCQ,467
|
|
19
19
|
solara_enterprise/search/search.vue,sha256=Aoyp9XPK9dDlKCymJqAtT6eoTsEoAOIe6zXiJYup5f4,6127
|
|
20
|
-
solara_enterprise-1.
|
|
21
|
-
solara_enterprise-1.
|
|
22
|
-
solara_enterprise-1.
|
|
23
|
-
solara_enterprise-1.
|
|
20
|
+
solara_enterprise-1.31.0.dist-info/METADATA,sha256=5X2Nqy5Cgu_JiSbFzwtLlrwzfGQrLrSWoQ5MpIhrgtM,989
|
|
21
|
+
solara_enterprise-1.31.0.dist-info/WHEEL,sha256=L5_n4Kc1NmrSdVgbp6hdnwwVwBnoYOCnbHBRMD-qNJ4,105
|
|
22
|
+
solara_enterprise-1.31.0.dist-info/licenses/LICENSE,sha256=04_xbTWtvdcQomu6IXsIkniKk8EcD9P1GyJM2dYPoSU,59
|
|
23
|
+
solara_enterprise-1.31.0.dist-info/RECORD,,
|
|
File without changes
|