From ad42bd0c036c21f636116336b1d9b40f96d76ded Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Sun, 19 Oct 2025 07:56:12 -0400 Subject: [PATCH 01/24] Updating deps --- .../example/flask_example/app/app.zip.hash | 2 +- .../example/flask_example/pubspec.lock | 182 +++++++++--------- .../example/flask_example/pubspec.yaml | 4 +- .../windows/flutter/CMakeLists.txt | 7 +- .../example/flet_example/app/app.zip.hash | 2 +- .../example/flet_example/pubspec.lock | 112 ++++++----- .../example/flet_example/pubspec.yaml | 6 +- .../example/run_example/pubspec.lock | 168 ++++++++-------- .../example/run_example/pubspec.yaml | 8 +- src/serious_python/pubspec.yaml | 18 +- src/serious_python_android/pubspec.yaml | 10 +- src/serious_python_darwin/pubspec.yaml | 6 +- src/serious_python_linux/pubspec.yaml | 4 +- .../lib/src/utils.dart | 4 +- .../pubspec.yaml | 10 +- src/serious_python_windows/pubspec.yaml | 4 +- .../windows/CMakeLists.txt | 10 +- 17 files changed, 295 insertions(+), 262 deletions(-) diff --git a/src/serious_python/example/flask_example/app/app.zip.hash b/src/serious_python/example/flask_example/app/app.zip.hash index 7099c3a9..293ce40f 100644 --- a/src/serious_python/example/flask_example/app/app.zip.hash +++ b/src/serious_python/example/flask_example/app/app.zip.hash @@ -1 +1 @@ -9abed4a7d914300e2cf342c04e7dfcf58a5dbda44fc93a99a86b0e8831207840 \ No newline at end of file +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 \ No newline at end of file diff --git a/src/serious_python/example/flask_example/pubspec.lock b/src/serious_python/example/flask_example/pubspec.lock index 2986e328..2883064f 100644 --- a/src/serious_python/example/flask_example/pubspec.lock +++ b/src/serious_python/example/flask_example/pubspec.lock @@ -5,66 +5,66 @@ packages: dependency: transitive description: name: archive - sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" url: "https://pub.dev" source: hosted - version: "3.6.1" + version: "4.0.7" args: dependency: transitive description: name: args - sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.7.0" async: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.13.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" characters: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.1" crypto: dependency: transitive description: name: crypto - sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" cupertino_icons: dependency: "direct main" description: @@ -77,18 +77,18 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" ffi: dependency: transitive description: name: ffi - sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" file: dependency: transitive description: @@ -106,10 +106,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "6.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -127,106 +127,106 @@ packages: dependency: "direct main" description: name: http - sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007 url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.5.0" http_parser: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.2" leak_tracker: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: name: lints - sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "6.0.0" matcher: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.16.0" path: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" path_provider: dependency: transitive description: name: path_provider - sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7" + sha256: "993381400e94d18469750e5b9dcb8206f15bc09f9da86b9e44a9b0092a0066db" url: "https://pub.dev" source: hosted - version: "2.2.10" + version: "2.2.18" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.2" path_provider_linux: dependency: transitive description: @@ -255,18 +255,18 @@ packages: dependency: transitive description: name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" url: "https://pub.dev" source: hosted - version: "6.0.2" + version: "6.1.0" platform: dependency: transitive description: name: platform - sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" url: "https://pub.dev" source: hosted - version: "3.1.5" + version: "3.1.6" plugin_platform_interface: dependency: transitive description: @@ -275,157 +275,165 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + posix: + dependency: transitive + description: + name: posix + sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" + url: "https://pub.dev" + source: hosted + version: "6.0.3" serious_python: dependency: "direct main" description: path: "../.." relative: true source: path - version: "0.9.0" + version: "0.9.2" serious_python_android: dependency: transitive description: path: "../../../serious_python_android" relative: true source: path - version: "0.9.0" + version: "0.9.2" serious_python_darwin: dependency: transitive description: path: "../../../serious_python_darwin" relative: true source: path - version: "0.9.0" + version: "0.9.2" serious_python_linux: dependency: transitive description: path: "../../../serious_python_linux" relative: true source: path - version: "0.9.0" + version: "0.9.2" serious_python_platform_interface: dependency: transitive description: path: "../../../serious_python_platform_interface" relative: true source: path - version: "0.9.0" + version: "0.9.2" serious_python_windows: dependency: transitive description: path: "../../../serious_python_windows" relative: true source: path - version: "0.9.0" + version: "0.9.2" shelf: dependency: transitive description: name: shelf - sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.2" sky_engine: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.4.1" term_glyph: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test_api: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.6" toml: dependency: transitive description: name: toml - sha256: "9968de24e45b632bf1a654fe1ac7b6fe5261c349243df83fd262397799c45a2d" + sha256: d968d149c8bd06dc14e09ea3a140f90a3f2ba71949e7a91df4a46f3107400e71 url: "https://pub.dev" source: hosted - version: "0.15.0" + version: "0.16.0" typed_data: dependency: transitive description: name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.4.0" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "15.0.2" web: dependency: transitive description: name: web - sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.1.0" sdks: - dart: ">=3.4.0 <4.0.0" - flutter: ">=3.22.0" + dart: ">=3.8.0 <4.0.0" + flutter: ">=3.29.0" diff --git a/src/serious_python/example/flask_example/pubspec.yaml b/src/serious_python/example/flask_example/pubspec.yaml index f82685f5..905a6750 100644 --- a/src/serious_python/example/flask_example/pubspec.yaml +++ b/src/serious_python/example/flask_example/pubspec.yaml @@ -38,7 +38,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.2 + cupertino_icons: ^1.0.8 http: ^1.1.2 dev_dependencies: @@ -50,7 +50,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^2.0.0 + flutter_lints: ^6.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/src/serious_python/example/flask_example/windows/flutter/CMakeLists.txt b/src/serious_python/example/flask_example/windows/flutter/CMakeLists.txt index 930d2071..903f4899 100644 --- a/src/serious_python/example/flask_example/windows/flutter/CMakeLists.txt +++ b/src/serious_python/example/flask_example/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/src/serious_python/example/flet_example/app/app.zip.hash b/src/serious_python/example/flet_example/app/app.zip.hash index a846e48f..293ce40f 100644 --- a/src/serious_python/example/flet_example/app/app.zip.hash +++ b/src/serious_python/example/flet_example/app/app.zip.hash @@ -1 +1 @@ -43f8a7b00e44a09647dda36299259976950ba7259c5060de20677c449690fc73 \ No newline at end of file +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 \ No newline at end of file diff --git a/src/serious_python/example/flet_example/pubspec.lock b/src/serious_python/example/flet_example/pubspec.lock index c3f79d69..81287015 100644 --- a/src/serious_python/example/flet_example/pubspec.lock +++ b/src/serious_python/example/flet_example/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: archive - sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" url: "https://pub.dev" source: hosted - version: "3.6.1" + version: "4.0.7" args: dependency: transitive description: name: args - sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.7.0" async: dependency: transitive description: @@ -37,26 +37,26 @@ packages: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.1" cross_file: dependency: transitive description: @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: crypto - sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" cupertino_icons: dependency: "direct main" description: @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" ffi: dependency: transitive description: @@ -251,10 +251,10 @@ packages: dependency: transitive description: name: http - sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007 url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.5.0" http_parser: dependency: transitive description: @@ -272,10 +272,10 @@ packages: dependency: transitive description: name: intl - sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" url: "https://pub.dev" source: hosted - version: "0.19.0" + version: "0.20.2" js: dependency: transitive description: @@ -296,26 +296,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -344,26 +344,26 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.16.0" package_info_plus: dependency: "direct main" description: @@ -384,10 +384,10 @@ packages: dependency: "direct main" description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" path_parsing: dependency: transitive description: @@ -400,10 +400,10 @@ packages: dependency: "direct main" description: name: path_provider - sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" path_provider_android: dependency: transitive description: @@ -468,6 +468,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + posix: + dependency: transitive + description: + name: posix + sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" + url: "https://pub.dev" + source: hosted + version: "6.0.3" process: dependency: transitive description: @@ -546,42 +554,42 @@ packages: path: "../.." relative: true source: path - version: "0.9.0" + version: "0.9.2" serious_python_android: dependency: transitive description: path: "../../../serious_python_android" relative: true source: path - version: "0.9.0" + version: "0.9.2" serious_python_darwin: dependency: transitive description: path: "../../../serious_python_darwin" relative: true source: path - version: "0.9.0" + version: "0.9.2" serious_python_linux: dependency: transitive description: path: "../../../serious_python_linux" relative: true source: path - version: "0.9.0" + version: "0.9.2" serious_python_platform_interface: dependency: transitive description: path: "../../../serious_python_platform_interface" relative: true source: path - version: "0.9.0" + version: "0.9.2" serious_python_windows: dependency: transitive description: path: "../../../serious_python_windows" relative: true source: path - version: "0.9.0" + version: "0.9.2" shared_preferences: dependency: transitive description: @@ -650,7 +658,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: @@ -663,18 +671,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: @@ -703,18 +711,18 @@ packages: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.6" toml: dependency: transitive description: name: toml - sha256: "9968de24e45b632bf1a654fe1ac7b6fe5261c349243df83fd262397799c45a2d" + sha256: d968d149c8bd06dc14e09ea3a140f90a3f2ba71949e7a91df4a46f3107400e71 url: "https://pub.dev" source: hosted - version: "0.15.0" + version: "0.16.0" typed_data: dependency: transitive description: @@ -823,10 +831,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -908,5 +916,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.4.0 <4.0.0" + dart: ">=3.8.0-0 <4.0.0" flutter: ">=3.22.0" diff --git a/src/serious_python/example/flet_example/pubspec.yaml b/src/serious_python/example/flet_example/pubspec.yaml index f8e5e4ee..8cc02e1f 100644 --- a/src/serious_python/example/flet_example/pubspec.yaml +++ b/src/serious_python/example/flet_example/pubspec.yaml @@ -37,14 +37,14 @@ dependencies: flet: ^0.26.0 - path: ^1.8.3 + path: ^1.9.1 url_strategy: ^0.2.0 - path_provider: ^2.1.4 + path_provider: ^2.1.5 package_info_plus: ^8.0.2 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.2 + cupertino_icons: ^1.0.8 dev_dependencies: flutter_test: diff --git a/src/serious_python/example/run_example/pubspec.lock b/src/serious_python/example/run_example/pubspec.lock index 94e4ede3..a8b02d07 100644 --- a/src/serious_python/example/run_example/pubspec.lock +++ b/src/serious_python/example/run_example/pubspec.lock @@ -5,66 +5,66 @@ packages: dependency: transitive description: name: archive - sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" url: "https://pub.dev" source: hosted - version: "3.6.1" + version: "4.0.7" args: dependency: transitive description: name: args - sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.7.0" async: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.13.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" characters: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.19.1" crypto: dependency: transitive description: name: crypto - sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" cupertino_icons: dependency: "direct main" description: @@ -77,26 +77,26 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" ffi: dependency: transitive description: name: ffi - sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" file: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" flutter: dependency: "direct main" description: flutter @@ -137,18 +137,18 @@ packages: dependency: transitive description: name: http - sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007 url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.5.0" http_parser: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.2" integration_test: dependency: "direct dev" description: flutter @@ -158,26 +158,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.7" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -190,10 +190,10 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: @@ -206,42 +206,42 @@ packages: dependency: transitive description: name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.16.0" path: dependency: "direct main" description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" path_provider: dependency: "direct main" description: name: path_provider - sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7" + sha256: "993381400e94d18469750e5b9dcb8206f15bc09f9da86b9e44a9b0092a0066db" url: "https://pub.dev" source: hosted - version: "2.2.10" + version: "2.2.18" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.2" path_provider_linux: dependency: transitive description: @@ -270,18 +270,18 @@ packages: dependency: transitive description: name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" url: "https://pub.dev" source: hosted - version: "6.0.2" + version: "6.1.0" platform: dependency: transitive description: name: platform - sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" url: "https://pub.dev" source: hosted - version: "3.1.5" + version: "3.1.6" plugin_platform_interface: dependency: transitive description: @@ -290,14 +290,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + posix: + dependency: transitive + description: + name: posix + sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" + url: "https://pub.dev" + source: hosted + version: "6.0.3" process: dependency: transitive description: name: process - sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" + sha256: c6248e4526673988586e8c00bb22a49210c258dc91df5227d5da9748ecf79744 url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.0.5" serious_python: dependency: "direct main" description: @@ -344,10 +352,10 @@ packages: dependency: transitive description: name: shelf - sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.2" sky_engine: dependency: transitive description: flutter @@ -357,34 +365,34 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.1" sync_http: dependency: transitive description: @@ -397,74 +405,74 @@ packages: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test_api: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.6" toml: dependency: transitive description: name: toml - sha256: "9968de24e45b632bf1a654fe1ac7b6fe5261c349243df83fd262397799c45a2d" + sha256: d968d149c8bd06dc14e09ea3a140f90a3f2ba71949e7a91df4a46f3107400e71 url: "https://pub.dev" source: hosted - version: "0.15.0" + version: "0.16.0" typed_data: dependency: transitive description: name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.4.0" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: name: vm_service - sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" url: "https://pub.dev" source: hosted - version: "14.3.0" + version: "15.0.2" web: dependency: transitive description: name: web - sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" webdriver: dependency: transitive description: name: webdriver - sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8" + sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "3.1.0" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.1.0" sdks: - dart: ">=3.4.0 <4.0.0" - flutter: ">=3.22.0" + dart: ">=3.8.0-0 <4.0.0" + flutter: ">=3.29.0" diff --git a/src/serious_python/example/run_example/pubspec.yaml b/src/serious_python/example/run_example/pubspec.yaml index 6e186c10..edfc2819 100644 --- a/src/serious_python/example/run_example/pubspec.yaml +++ b/src/serious_python/example/run_example/pubspec.yaml @@ -34,12 +34,12 @@ dependencies: serious_python: path: ../../ - path_provider: ^2.0.15 - path: ^1.8.3 + path_provider: ^2.1.5 + path: ^1.9.1 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.2 + cupertino_icons: ^1.0.8 dev_dependencies: flutter_test: @@ -50,7 +50,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^2.0.0 + flutter_lints: ^6.0.0 integration_test: sdk: flutter diff --git a/src/serious_python/pubspec.yaml b/src/serious_python/pubspec.yaml index ce367121..ba015384 100644 --- a/src/serious_python/pubspec.yaml +++ b/src/serious_python/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python description: A cross-platform plugin for adding embedded Python runtime to your Flutter apps. homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 0.9.2 +version: 0.9.2+1 platforms: ios: @@ -43,18 +43,18 @@ dependencies: serious_python_linux: path: ../serious_python_linux - path_provider: ^2.1.3 - archive: ^3.6.1 - path: ^1.9.0 - args: ^2.5.0 - toml: ^0.15.0 - http: ^1.2.1 + path_provider: ^2.1.5 + archive: ^4.0.7 + path: ^1.9.1 + args: ^2.7.0 + toml: ^0.16.0 + http: ^1.5.0 shelf: ^1.4.1 - crypto: ^3.0.5 + crypto: ^3.0.6 glob: ^2.1.3 dev_dependencies: flutter_test: sdk: flutter plugin_platform_interface: ^2.1.6 - flutter_lints: ^2.0.0 \ No newline at end of file + flutter_lints: ^6.0.0 \ No newline at end of file diff --git a/src/serious_python_android/pubspec.yaml b/src/serious_python_android/pubspec.yaml index 9aa63a37..726b4dd3 100644 --- a/src/serious_python_android/pubspec.yaml +++ b/src/serious_python_android/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_android description: Android implementation of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 0.9.2 +version: 0.9.2+1 environment: sdk: ">=3.0.0 <4.0.0" @@ -14,14 +14,14 @@ dependencies: plugin_platform_interface: ^2.1.8 serious_python_platform_interface: path: ../serious_python_platform_interface - path: ^1.9.0 - ffi: ^2.1.2 + path: ^1.9.1 + ffi: ^2.1.3 dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 - ffigen: ^9.0.0 + flutter_lints: ^6.0.0 + ffigen: ^19.1.0 flutter: plugin: diff --git a/src/serious_python_darwin/pubspec.yaml b/src/serious_python_darwin/pubspec.yaml index 659499c5..16717374 100644 --- a/src/serious_python_darwin/pubspec.yaml +++ b/src/serious_python_darwin/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_darwin description: iOS and macOS implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 0.9.2 +version: 0.9.2+1 environment: sdk: ">=3.0.0 <4.0.0" @@ -14,12 +14,12 @@ dependencies: plugin_platform_interface: ^2.1.8 serious_python_platform_interface: path: ../serious_python_platform_interface - path: ^1.9.0 + path: ^1.9.1 dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter_lints: ^6.0.0 flutter: plugin: diff --git a/src/serious_python_linux/pubspec.yaml b/src/serious_python_linux/pubspec.yaml index 651300f8..97e10cd8 100644 --- a/src/serious_python_linux/pubspec.yaml +++ b/src/serious_python_linux/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_linux description: Linux implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 0.9.2 +version: 0.9.2+1 environment: sdk: '>=3.1.3 <4.0.0' @@ -18,7 +18,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter_lints: ^6.0.0 flutter: plugin: diff --git a/src/serious_python_platform_interface/lib/src/utils.dart b/src/serious_python_platform_interface/lib/src/utils.dart index e364c4e3..a45e7f34 100644 --- a/src/serious_python_platform_interface/lib/src/utils.dart +++ b/src/serious_python_platform_interface/lib/src/utils.dart @@ -60,9 +60,9 @@ Future extractAssetOrFile(String path, archive = ZipDecoder().decodeBytes(data); } else { final inputStream = InputFileStream(path); - archive = ZipDecoder().decodeBuffer(inputStream); + archive = ZipDecoder().decodeStream(inputStream); } - await extractArchiveToDiskAsync(archive, destDir.path, asyncWrite: true); + await extractArchiveToDisk(archive, destDir.path); } catch (e) { debugPrint("Error unpacking archive: $e"); await destDir.delete(recursive: true); diff --git a/src/serious_python_platform_interface/pubspec.yaml b/src/serious_python_platform_interface/pubspec.yaml index 1823cc09..c23dd326 100644 --- a/src/serious_python_platform_interface/pubspec.yaml +++ b/src/serious_python_platform_interface/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_platform_interface description: A common platform interface for the serious_python plugin. homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 0.9.2 +version: 0.9.2+1 environment: sdk: ">=3.0.0 <4.0.0" @@ -12,11 +12,11 @@ dependencies: flutter: sdk: flutter plugin_platform_interface: ^2.1.8 - path_provider: ^2.1.3 - archive: ^3.6.1 - path: ^1.9.0 + path_provider: ^2.1.5 + archive: ^4.0.7 + path: ^1.9.1 dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter_lints: ^6.0.0 diff --git a/src/serious_python_windows/pubspec.yaml b/src/serious_python_windows/pubspec.yaml index 439a50e0..7a91d271 100644 --- a/src/serious_python_windows/pubspec.yaml +++ b/src/serious_python_windows/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_windows description: Windows implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 0.9.2 +version: 0.9.2+1 environment: sdk: '>=3.1.3 <4.0.0' @@ -18,7 +18,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter_lints: ^6.0.0 flutter: plugin: diff --git a/src/serious_python_windows/windows/CMakeLists.txt b/src/serious_python_windows/windows/CMakeLists.txt index d13a5c11..ba8659b6 100644 --- a/src/serious_python_windows/windows/CMakeLists.txt +++ b/src/serious_python_windows/windows/CMakeLists.txt @@ -30,6 +30,10 @@ list(APPEND PLUGIN_SOURCES "serious_python_windows_plugin.h" ) +if(MSVC) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") +endif() + # Define the plugin library target. Its name must not be changed (see comment # on PLUGIN_NAME above). add_library(${PLUGIN_NAME} SHARED @@ -71,9 +75,9 @@ target_link_libraries(${PLUGIN_NAME} PRIVATE set(serious_python_windows_bundled_libraries "${PYTHON_PACKAGE}/python312$<$:_d>.dll" "${PYTHON_PACKAGE}/python3$<$:_d>.dll" - "$ENV{WINDIR}/system32/msvcp140.dll" - "$ENV{WINDIR}/system32/vcruntime140.dll" - "$ENV{WINDIR}/system32/vcruntime140_1.dll" +# "$ENV{WINDIR}/system32/msvcp140.dll" +# "$ENV{WINDIR}/system32/vcruntime140.dll" +# "$ENV{WINDIR}/system32/vcruntime140_1.dll" PARENT_SCOPE ) From 895b3826068e94719c5a657f9c8d78907dc4c407 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Sun, 19 Oct 2025 08:13:40 -0400 Subject: [PATCH 02/24] Updated deps --- .../example/flask_example/pubspec.lock | 24 +-- .../example/flet_example/pubspec.lock | 172 +++++++++--------- .../example/run_example/pubspec.lock | 32 ++-- 3 files changed, 114 insertions(+), 114 deletions(-) diff --git a/src/serious_python/example/flask_example/pubspec.lock b/src/serious_python/example/flask_example/pubspec.lock index 2883064f..450738d9 100644 --- a/src/serious_python/example/flask_example/pubspec.lock +++ b/src/serious_python/example/flask_example/pubspec.lock @@ -215,18 +215,18 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "993381400e94d18469750e5b9dcb8206f15bc09f9da86b9e44a9b0092a0066db" + sha256: e122c5ea805bb6773bb12ce667611265980940145be920cd09a4b0ec0285cb16 url: "https://pub.dev" source: hosted - version: "2.2.18" + version: "2.2.20" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" + sha256: efaec349ddfc181528345c56f8eda9d6cccd71c177511b132c6a0ddaefaa2738 url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.3" path_provider_linux: dependency: transitive description: @@ -289,42 +289,42 @@ packages: path: "../.." relative: true source: path - version: "0.9.2" + version: "0.9.3+1" serious_python_android: dependency: transitive description: path: "../../../serious_python_android" relative: true source: path - version: "0.9.2" + version: "0.9.3+1" serious_python_darwin: dependency: transitive description: path: "../../../serious_python_darwin" relative: true source: path - version: "0.9.2" + version: "0.9.3+1" serious_python_linux: dependency: transitive description: path: "../../../serious_python_linux" relative: true source: path - version: "0.9.2" + version: "0.9.3+1" serious_python_platform_interface: dependency: transitive description: path: "../../../serious_python_platform_interface" relative: true source: path - version: "0.9.2" + version: "0.9.3+1" serious_python_windows: dependency: transitive description: path: "../../../serious_python_windows" relative: true source: path - version: "0.9.2" + version: "0.9.3+1" shelf: dependency: transitive description: @@ -435,5 +435,5 @@ packages: source: hosted version: "1.1.0" sdks: - dart: ">=3.8.0 <4.0.0" - flutter: ">=3.29.0" + dart: ">=3.9.0 <4.0.0" + flutter: ">=3.35.0" diff --git a/src/serious_python/example/flet_example/pubspec.lock b/src/serious_python/example/flet_example/pubspec.lock index a9b25b04..2500a16d 100644 --- a/src/serious_python/example/flet_example/pubspec.lock +++ b/src/serious_python/example/flet_example/pubspec.lock @@ -93,26 +93,26 @@ packages: dependency: transitive description: name: device_info_plus - sha256: "72d146c6d7098689ff5c5f66bcf593ac11efc530095385356e131070333e64da" + sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a" url: "https://pub.dev" source: hosted - version: "11.3.0" + version: "11.5.0" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - sha256: "0b04e02b30791224b31969eb1b50d723498f402971bff3630bca2ba839bd1ed2" + sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f url: "https://pub.dev" source: hosted - version: "7.0.2" + version: "7.0.3" equatable: dependency: transitive description: name: equatable - sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.0.7" fake_async: dependency: transitive description: @@ -125,10 +125,10 @@ packages: dependency: transitive description: name: ffi - sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" file: dependency: transitive description: @@ -141,10 +141,10 @@ packages: dependency: transitive description: name: file_picker - sha256: e7e16c9d15c36330b94ca0e2ad8cb61f93cd5282d0158c09805aed13b5452f22 + sha256: f2d9f173c2c14635cc0e9b14c143c49ef30b4934e8d1d274d6206fcb0086a06f url: "https://pub.dev" source: hosted - version: "10.3.2" + version: "10.3.3" fl_chart: dependency: transitive description: @@ -196,18 +196,18 @@ packages: dependency: transitive description: name: flutter_markdown - sha256: f0e599ba89c9946c8e051780f0ec99aba4ba15895e0380a7ab68f420046fc44e + sha256: "08fb8315236099ff8e90cb87bb2b935e0a724a3af1623000a9cec930468e0f27" url: "https://pub.dev" source: hosted - version: "0.7.4+1" + version: "0.7.7+1" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda" + sha256: "306f0596590e077338312f38837f595c04f28d6cdeeac392d3d74df2f0003687" url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.0.32" flutter_redux: dependency: transitive description: @@ -220,10 +220,10 @@ packages: dependency: transitive description: name: flutter_svg - sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b + sha256: b9c2ad5872518a27507ab432d1fb97e8813b05f0fc693f9d40fad06d073e0678 url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.2.1" flutter_test: dependency: "direct dev" description: flutter @@ -267,10 +267,10 @@ packages: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.2" integration_test: dependency: "direct dev" description: flutter @@ -336,18 +336,18 @@ packages: dependency: transitive description: name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" markdown: dependency: transitive description: name: markdown - sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051 + sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" url: "https://pub.dev" source: hosted - version: "7.2.2" + version: "7.3.0" matcher: dependency: transitive description: @@ -376,18 +376,18 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: a75164ade98cb7d24cfd0a13c6408927c6b217fa60dee5a7ff5c116a58f28918 + sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" url: "https://pub.dev" source: hosted - version: "8.0.2" + version: "8.3.1" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: ac1f4a4847f1ade8e6a87d1f39f5d7c67490738642e2542f559ec38c37489a66 + sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.2.1" path: dependency: "direct main" description: @@ -400,10 +400,10 @@ packages: dependency: transitive description: name: path_parsing - sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" path_provider: dependency: "direct main" description: @@ -416,18 +416,18 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7" + sha256: e122c5ea805bb6773bb12ce667611265980940145be920cd09a4b0ec0285cb16 url: "https://pub.dev" source: hosted - version: "2.2.10" + version: "2.2.20" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + sha256: efaec349ddfc181528345c56f8eda9d6cccd71c177511b132c6a0ddaefaa2738 url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.3" path_provider_linux: dependency: transitive description: @@ -456,10 +456,10 @@ packages: dependency: transitive description: name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" url: "https://pub.dev" source: hosted - version: "6.0.2" + version: "6.1.0" platform: dependency: transitive description: @@ -488,10 +488,10 @@ packages: dependency: transitive description: name: process - sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d" + sha256: c6248e4526673988586e8c00bb22a49210c258dc91df5227d5da9748ecf79744 url: "https://pub.dev" source: hosted - version: "5.0.3" + version: "5.0.5" redux: dependency: transitive description: @@ -562,66 +562,66 @@ packages: path: "../.." relative: true source: path - version: "0.9.2" + version: "0.9.3+1" serious_python_android: dependency: transitive description: path: "../../../serious_python_android" relative: true source: path - version: "0.9.2" + version: "0.9.3+1" serious_python_darwin: dependency: transitive description: path: "../../../serious_python_darwin" relative: true source: path - version: "0.9.2" + version: "0.9.3+1" serious_python_linux: dependency: transitive description: path: "../../../serious_python_linux" relative: true source: path - version: "0.9.2" + version: "0.9.3+1" serious_python_platform_interface: dependency: transitive description: path: "../../../serious_python_platform_interface" relative: true source: path - version: "0.9.2" + version: "0.9.3+1" serious_python_windows: dependency: transitive description: path: "../../../serious_python_windows" relative: true source: path - version: "0.9.2" + version: "0.9.3+1" shared_preferences: dependency: transitive description: name: shared_preferences - sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051" + sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.5.3" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e" + sha256: "34266009473bf71d748912da4bf62d439185226c03e01e2d9687bc65bbfcb713" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.15" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f + sha256: "1c33a907142607c40a7542768ec9badfd16293bac51da3a4482623d15845f88b" url: "https://pub.dev" source: hosted - version: "2.5.2" + version: "2.5.5" shared_preferences_linux: dependency: transitive description: @@ -642,10 +642,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.3" shared_preferences_windows: dependency: transitive description: @@ -658,10 +658,10 @@ packages: dependency: transitive description: name: shelf - sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.2" sky_engine: dependency: transitive description: flutter @@ -735,50 +735,50 @@ packages: dependency: transitive description: name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.4.0" url_launcher: dependency: transitive description: name: url_launcher - sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" + sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 url: "https://pub.dev" source: hosted - version: "6.3.1" + version: "6.3.2" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: f0c73347dfcfa5b3db8bc06e1502668265d39c08f310c29bff4e28eea9699f79 + sha256: "5c8b6c2d89a78f5a1cca70a73d9d5f86c701b36b42f9c9dac7bad592113c28e9" url: "https://pub.dev" source: hosted - version: "6.3.9" + version: "6.3.24" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e + sha256: "6b63f1441e4f653ae799166a72b50b1767321ecc263a57aadf825a7a2a5477d9" url: "https://pub.dev" source: hosted - version: "6.3.1" + version: "6.3.5" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af + sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672" + sha256: "8262208506252a3ed4ff5c0dc1e973d2c0e0ef337d0a074d35634da5d44397c9" url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.4" url_launcher_platform_interface: dependency: transitive description: @@ -791,18 +791,18 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" + sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.1" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" + sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.4" url_strategy: dependency: "direct main" description: @@ -815,26 +815,26 @@ packages: dependency: transitive description: name: vector_graphics - sha256: "44cc7104ff32563122a929e4620cf3efd584194eec6d1d913eb5ba593dbcf6de" + sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6 url: "https://pub.dev" source: hosted - version: "1.1.18" + version: "1.1.19" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" url: "https://pub.dev" source: hosted - version: "1.1.11+1" + version: "1.1.13" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad" + sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc url: "https://pub.dev" source: hosted - version: "1.1.16" + version: "1.1.19" vector_math: dependency: transitive description: @@ -847,18 +847,18 @@ packages: dependency: transitive description: name: vm_service - sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" url: "https://pub.dev" source: hosted - version: "15.0.0" + version: "15.0.2" web: dependency: transitive description: name: web - sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" web_socket_channel: dependency: transitive description: @@ -879,18 +879,18 @@ packages: dependency: transitive description: name: win32 - sha256: "329edf97fdd893e0f1e3b9e88d6a0e627128cc17cc316a8d67fda8f1451178ba" + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e url: "https://pub.dev" source: hosted - version: "5.13.0" + version: "5.15.0" win32_registry: dependency: transitive description: name: win32_registry - sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852" + sha256: "6f1b564492d0147b330dd794fee8f512cec4977957f310f9951b5f9d83618dae" url: "https://pub.dev" source: hosted - version: "1.1.5" + version: "2.1.0" window_manager: dependency: transitive description: @@ -911,10 +911,10 @@ packages: dependency: transitive description: name: xdg_directories - sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.1.0" xml: dependency: transitive description: @@ -924,5 +924,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.8.0-0 <4.0.0" - flutter: ">=3.22.0" + dart: ">=3.9.0 <4.0.0" + flutter: ">=3.35.0" diff --git a/src/serious_python/example/run_example/pubspec.lock b/src/serious_python/example/run_example/pubspec.lock index 0e447b55..8cc78ac7 100644 --- a/src/serious_python/example/run_example/pubspec.lock +++ b/src/serious_python/example/run_example/pubspec.lock @@ -111,10 +111,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "6.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -182,10 +182,10 @@ packages: dependency: transitive description: name: lints - sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "6.0.0" matcher: dependency: transitive description: @@ -230,18 +230,18 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "993381400e94d18469750e5b9dcb8206f15bc09f9da86b9e44a9b0092a0066db" + sha256: e122c5ea805bb6773bb12ce667611265980940145be920cd09a4b0ec0285cb16 url: "https://pub.dev" source: hosted - version: "2.2.18" + version: "2.2.20" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" + sha256: efaec349ddfc181528345c56f8eda9d6cccd71c177511b132c6a0ddaefaa2738 url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.3" path_provider_linux: dependency: transitive description: @@ -312,42 +312,42 @@ packages: path: "../.." relative: true source: path - version: "0.9.3" + version: "0.9.3+1" serious_python_android: dependency: transitive description: path: "../../../serious_python_android" relative: true source: path - version: "0.9.3" + version: "0.9.3+1" serious_python_darwin: dependency: transitive description: path: "../../../serious_python_darwin" relative: true source: path - version: "0.9.3" + version: "0.9.3+1" serious_python_linux: dependency: transitive description: path: "../../../serious_python_linux" relative: true source: path - version: "0.9.3" + version: "0.9.3+1" serious_python_platform_interface: dependency: transitive description: path: "../../../serious_python_platform_interface" relative: true source: path - version: "0.9.3" + version: "0.9.3+1" serious_python_windows: dependency: transitive description: path: "../../../serious_python_windows" relative: true source: path - version: "0.9.3" + version: "0.9.3+1" shelf: dependency: transitive description: @@ -474,5 +474,5 @@ packages: source: hosted version: "1.1.0" sdks: - dart: ">=3.8.0-0 <4.0.0" - flutter: ">=3.29.0" + dart: ">=3.9.0 <4.0.0" + flutter: ">=3.35.0" From ab35b265d69567740822b75bfbc02ccef49703bd Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Mon, 27 Oct 2025 09:39:44 -0400 Subject: [PATCH 03/24] Updating flutter version 3.7 --- src/serious_python/pubspec.yaml | 4 ++-- src/serious_python_android/pubspec.yaml | 2 +- src/serious_python_linux/pubspec.yaml | 4 ++-- src/serious_python_windows/pubspec.yaml | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/serious_python/pubspec.yaml b/src/serious_python/pubspec.yaml index 93b5942d..07cd7712 100644 --- a/src/serious_python/pubspec.yaml +++ b/src/serious_python/pubspec.yaml @@ -49,12 +49,12 @@ dependencies: args: ^2.7.0 toml: ^0.16.0 http: ^1.5.0 - shelf: ^1.4.1 + shelf: ^1.4.2 crypto: ^3.0.6 glob: ^2.1.3 dev_dependencies: flutter_test: sdk: flutter - plugin_platform_interface: ^2.1.6 + plugin_platform_interface: ^2.1.8 flutter_lints: ^6.0.0 \ No newline at end of file diff --git a/src/serious_python_android/pubspec.yaml b/src/serious_python_android/pubspec.yaml index e1e5d758..1da5e6e2 100644 --- a/src/serious_python_android/pubspec.yaml +++ b/src/serious_python_android/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: serious_python_platform_interface: path: ../serious_python_platform_interface path: ^1.9.1 - ffi: ^2.1.3 + ffi: ^2.1.4 dev_dependencies: flutter_test: diff --git a/src/serious_python_linux/pubspec.yaml b/src/serious_python_linux/pubspec.yaml index 78678e1d..63d87fc9 100644 --- a/src/serious_python_linux/pubspec.yaml +++ b/src/serious_python_linux/pubspec.yaml @@ -5,8 +5,8 @@ repository: https://github.com/flet-dev/serious-python version: 0.9.3+1 environment: - sdk: '>=3.1.3 <4.0.0' - flutter: '>=3.3.0' + sdk: ">=3.0.0 <4.0.0" + flutter: ">=3.7.0" dependencies: flutter: diff --git a/src/serious_python_windows/pubspec.yaml b/src/serious_python_windows/pubspec.yaml index 0d9f54fe..1c3097fa 100644 --- a/src/serious_python_windows/pubspec.yaml +++ b/src/serious_python_windows/pubspec.yaml @@ -5,8 +5,8 @@ repository: https://github.com/flet-dev/serious-python version: 0.9.3+1 environment: - sdk: '>=3.1.3 <4.0.0' - flutter: '>=3.3.0' + sdk: ">=3.0.0 <4.0.0" + flutter: ">=3.7.0" dependencies: flutter: From 3e94ae3a66b1d6af57964a724c96b294143d88de Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Mon, 27 Oct 2025 09:54:16 -0400 Subject: [PATCH 04/24] Using CMake InstallRequiredSystemLibraries module to bundle the correct MSVC runtime --- src/serious_python_windows/windows/CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/serious_python_windows/windows/CMakeLists.txt b/src/serious_python_windows/windows/CMakeLists.txt index ba8659b6..ac452353 100644 --- a/src/serious_python_windows/windows/CMakeLists.txt +++ b/src/serious_python_windows/windows/CMakeLists.txt @@ -31,9 +31,14 @@ list(APPEND PLUGIN_SOURCES ) if(MSVC) - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") + set(CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY $,ON,OFF>) + file(REAL_PATH ${CMAKE_BINARY_DIR}/runner/$ FLUTTER_APP_DIR) + set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION ${FLUTTER_APP_DIR}) endif() +include(InstallRequiredSystemLibraries) + # Define the plugin library target. Its name must not be changed (see comment # on PLUGIN_NAME above). add_library(${PLUGIN_NAME} SHARED @@ -75,9 +80,6 @@ target_link_libraries(${PLUGIN_NAME} PRIVATE set(serious_python_windows_bundled_libraries "${PYTHON_PACKAGE}/python312$<$:_d>.dll" "${PYTHON_PACKAGE}/python3$<$:_d>.dll" -# "$ENV{WINDIR}/system32/msvcp140.dll" -# "$ENV{WINDIR}/system32/vcruntime140.dll" -# "$ENV{WINDIR}/system32/vcruntime140_1.dll" PARENT_SCOPE ) From e25aed711349e0bc2b6ea6bd50fae5c0c1a0c9ef Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Mon, 27 Oct 2025 11:06:18 -0400 Subject: [PATCH 05/24] Debug libraries are NonRedist --- src/serious_python_windows/windows/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/serious_python_windows/windows/CMakeLists.txt b/src/serious_python_windows/windows/CMakeLists.txt index ac452353..b17aee4b 100644 --- a/src/serious_python_windows/windows/CMakeLists.txt +++ b/src/serious_python_windows/windows/CMakeLists.txt @@ -32,7 +32,6 @@ list(APPEND PLUGIN_SOURCES if(MSVC) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") - set(CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY $,ON,OFF>) file(REAL_PATH ${CMAKE_BINARY_DIR}/runner/$ FLUTTER_APP_DIR) set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION ${FLUTTER_APP_DIR}) endif() From cc37f6073f5a7f4f00abaf2ce57a507aac4dfae7 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Mon, 27 Oct 2025 11:07:03 -0400 Subject: [PATCH 06/24] Adding missing requirements.txt --- src/serious_python/example/flask_example/requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/serious_python/example/flask_example/requirements.txt diff --git a/src/serious_python/example/flask_example/requirements.txt b/src/serious_python/example/flask_example/requirements.txt new file mode 100644 index 00000000..8ab6294c --- /dev/null +++ b/src/serious_python/example/flask_example/requirements.txt @@ -0,0 +1 @@ +flask \ No newline at end of file From e3ff110cc56c6116c4e2c83764a73e343d30903b Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Mon, 27 Oct 2025 11:11:46 -0400 Subject: [PATCH 07/24] Updating plugin versions --- .../example/flask_example/pubspec.lock | 12 ++++++------ src/serious_python/example/flet_example/pubspec.lock | 12 ++++++------ src/serious_python/example/run_example/pubspec.lock | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/serious_python/example/flask_example/pubspec.lock b/src/serious_python/example/flask_example/pubspec.lock index 450738d9..c2fe1546 100644 --- a/src/serious_python/example/flask_example/pubspec.lock +++ b/src/serious_python/example/flask_example/pubspec.lock @@ -289,42 +289,42 @@ packages: path: "../.." relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_android: dependency: transitive description: path: "../../../serious_python_android" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_darwin: dependency: transitive description: path: "../../../serious_python_darwin" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_linux: dependency: transitive description: path: "../../../serious_python_linux" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_platform_interface: dependency: transitive description: path: "../../../serious_python_platform_interface" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_windows: dependency: transitive description: path: "../../../serious_python_windows" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" shelf: dependency: transitive description: diff --git a/src/serious_python/example/flet_example/pubspec.lock b/src/serious_python/example/flet_example/pubspec.lock index 2500a16d..13867579 100644 --- a/src/serious_python/example/flet_example/pubspec.lock +++ b/src/serious_python/example/flet_example/pubspec.lock @@ -562,42 +562,42 @@ packages: path: "../.." relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_android: dependency: transitive description: path: "../../../serious_python_android" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_darwin: dependency: transitive description: path: "../../../serious_python_darwin" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_linux: dependency: transitive description: path: "../../../serious_python_linux" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_platform_interface: dependency: transitive description: path: "../../../serious_python_platform_interface" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_windows: dependency: transitive description: path: "../../../serious_python_windows" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" shared_preferences: dependency: transitive description: diff --git a/src/serious_python/example/run_example/pubspec.lock b/src/serious_python/example/run_example/pubspec.lock index 8cc78ac7..18da7d47 100644 --- a/src/serious_python/example/run_example/pubspec.lock +++ b/src/serious_python/example/run_example/pubspec.lock @@ -312,42 +312,42 @@ packages: path: "../.." relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_android: dependency: transitive description: path: "../../../serious_python_android" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_darwin: dependency: transitive description: path: "../../../serious_python_darwin" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_linux: dependency: transitive description: path: "../../../serious_python_linux" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_platform_interface: dependency: transitive description: path: "../../../serious_python_platform_interface" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" serious_python_windows: dependency: transitive description: path: "../../../serious_python_windows" relative: true source: path - version: "0.9.3+1" + version: "0.9.4+1" shelf: dependency: transitive description: From 522dc425654ad1c1a9eb864fc2f3f22885012c92 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Mon, 27 Oct 2025 11:31:15 -0400 Subject: [PATCH 08/24] Migrating to github hosted flet package --- .../example/flet_example/pubspec.lock | 99 ++++++++++--------- .../example/flet_example/pubspec.yaml | 5 +- 2 files changed, 58 insertions(+), 46 deletions(-) diff --git a/src/serious_python/example/flet_example/pubspec.lock b/src/serious_python/example/flet_example/pubspec.lock index 13867579..c69ea38b 100644 --- a/src/serious_python/example/flet_example/pubspec.lock +++ b/src/serious_python/example/flet_example/pubspec.lock @@ -93,10 +93,10 @@ packages: dependency: transitive description: name: device_info_plus - sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a" + sha256: dd0e8e02186b2196c7848c9d394a5fd6e5b57a43a546082c5820b1ec72317e33 url: "https://pub.dev" source: hosted - version: "11.5.0" + version: "12.2.0" device_info_plus_platform_interface: dependency: transitive description: @@ -145,22 +145,15 @@ packages: url: "https://pub.dev" source: hosted version: "10.3.3" - fl_chart: - dependency: transitive - description: - name: fl_chart - sha256: "74959b99b92b9eebeed1a4049426fd67c4abc3c5a0f4d12e2877097d6a11ae08" - url: "https://pub.dev" - source: hosted - version: "0.69.2" flet: dependency: "direct main" description: - name: flet - sha256: "3be85b7d2e70e00d957966a7bcec2b290057d440b7aafd795a197a39ab3783cf" - url: "https://pub.dev" - source: hosted - version: "0.28.3" + path: "packages/flet" + ref: HEAD + resolved-ref: "42dcc718a9ddd6b2c53100fed8e9c6afbb78e223" + url: "https://github.com/flet-dev/flet.git" + source: git + version: "0.70.0" flutter: dependency: "direct main" description: flutter @@ -196,10 +189,10 @@ packages: dependency: transitive description: name: flutter_markdown - sha256: "08fb8315236099ff8e90cb87bb2b935e0a724a3af1623000a9cec930468e0f27" + sha256: e7bbc718adc9476aa14cfddc1ef048d2e21e4e8f18311aaac723266db9f9e7b5 url: "https://pub.dev" source: hosted - version: "0.7.7+1" + version: "0.7.6+2" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -208,14 +201,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.32" - flutter_redux: - dependency: transitive - description: - name: flutter_redux - sha256: "3b20be9e08d0038e1452fbfa1fdb1ea0a7c3738c997734530b3c6d0bb5fcdbdc" - url: "https://pub.dev" - source: hosted - version: "0.10.0" flutter_svg: dependency: transitive description: @@ -284,14 +269,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.20.2" - js: - dependency: transitive - description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" json_annotation: dependency: transitive description: @@ -372,6 +349,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.16.0" + msgpack_dart: + dependency: transitive + description: + name: msgpack_dart + sha256: c2d235ed01f364719b5296aecf43ac330f0d7bc865fa134d0d7910a40454dffb + url: "https://pub.dev" + source: hosted + version: "1.0.1" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" package_info_plus: dependency: "direct main" description: @@ -492,14 +485,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.5" - redux: + provider: dependency: transitive description: - name: redux - sha256: "1e86ed5b1a9a717922d0a0ca41f9bf49c1a587d50050e9426fc65b14e85ec4d7" + name: provider + sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "6.1.5+1" screen_retriever: dependency: transitive description: @@ -540,22 +533,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.0" + screenshot: + dependency: transitive + description: + name: screenshot + sha256: "63817697a7835e6ce82add4228e15d233b74d42975c143ad8cfe07009fab866b" + url: "https://pub.dev" + source: hosted + version: "3.0.0" sensors_plus: dependency: transitive description: name: sensors_plus - sha256: "8e7fa79b4940442bb595bfc0ee9da4af5a22a0fe6ebacc74998245ee9496a82d" + sha256: "89e2bfc3d883743539ce5774a2b93df61effde40ff958ecad78cd66b1a8b8d52" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "6.1.2" sensors_plus_platform_interface: dependency: transitive description: name: sensors_plus_platform_interface - sha256: bc472d6cfd622acb4f020e726433ee31788b038056691ba433fec80e448a094f + sha256: "58815d2f5e46c0c41c40fb39375d3f127306f7742efe3b891c0b1c87e2b5cd5d" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "2.0.1" serious_python: dependency: "direct main" description: @@ -859,14 +860,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "3.0.3" webdriver: dependency: transitive description: @@ -895,10 +904,10 @@ packages: dependency: transitive description: name: window_manager - sha256: "732896e1416297c63c9e3fb95aea72d0355f61390263982a47fd519169dc5059" + sha256: "7eb6d6c4164ec08e1bf978d6e733f3cebe792e2a23fb07cbca25c2872bfdbdcd" url: "https://pub.dev" source: hosted - version: "0.4.3" + version: "0.5.1" window_to_front: dependency: transitive description: diff --git a/src/serious_python/example/flet_example/pubspec.yaml b/src/serious_python/example/flet_example/pubspec.yaml index 4da6c1cb..fc0e369d 100644 --- a/src/serious_python/example/flet_example/pubspec.yaml +++ b/src/serious_python/example/flet_example/pubspec.yaml @@ -35,7 +35,10 @@ dependencies: serious_python: path: ../../ - flet: ^0.28.3 + flet: + git: + url: https://github.com/flet-dev/flet.git + path: packages/flet path: ^1.9.1 url_strategy: ^0.2.0 From b442ac587101d870c014c24568f523b3d72e9cef Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Mon, 10 Nov 2025 04:23:49 -0500 Subject: [PATCH 09/24] Using sync method for path --- src/serious_python/bin/package_command.dart | 26 ++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/serious_python/bin/package_command.dart b/src/serious_python/bin/package_command.dart index f7596bb9..6d1f9eab 100644 --- a/src/serious_python/bin/package_command.dart +++ b/src/serious_python/bin/package_command.dart @@ -183,13 +183,13 @@ class PackageCommand extends Command { exit(2); } - if (!await sourceDir.exists()) { + if (!sourceDir.existsSync()) { stderr.writeln('Source directory does not exist.'); exit(2); } final pubspecFile = File(path.join(currentPath, "pubspec.yaml")); - if (!await pubspecFile.exists()) { + if (!pubspecFile.existsSync()) { stderr.writeln("Current directory must contain pubspec.yaml."); exit(2); } @@ -211,7 +211,7 @@ class PackageCommand extends Command { // ensure standard Dart/Flutter "build" directory exists _buildDir = Directory(path.join(currentPath, "build")); - if (!await _buildDir!.exists()) { + if (!_buildDir!.existsSync()) { await _buildDir!.create(); } @@ -224,7 +224,7 @@ class PackageCommand extends Command { // create dest dir final dest = File(path.join(currentPath, assetPath)); - if (!await dest.parent.exists()) { + if (!dest.parent.existsSync()) { stdout.writeln("Creating asset directory: ${dest.parent.path}"); await dest.parent.create(recursive: true); } @@ -277,7 +277,7 @@ class PackageCommand extends Command { sitePackagesRoot = path.join(tempDir.path, defaultSitePackagesDir); } - if (await Directory(sitePackagesRoot).exists()) { + if (Directory(sitePackagesRoot).existsSync()) { await for (var f in Directory(sitePackagesRoot) .list() .where((f) => !path.basename(f.path).startsWith("."))) { @@ -373,7 +373,7 @@ class PackageCommand extends Command { if (!flutterPackagesCopied) { stdout.writeln( "Copying Flutter packages to $flutterPackagesRoot"); - if (!await flutterPackagesRootDir.exists()) { + if (!flutterPackagesRootDir.existsSync()) { await flutterPackagesRootDir.create(recursive: true); } await copyDirectory(sitePackagesFlutterDir, @@ -424,7 +424,7 @@ class PackageCommand extends Command { // synchronize pod var syncSh = File(path.join(sitePackagesRoot, ".pod", "sync_site_packages.sh")); - if (await syncSh.exists()) { + if (syncSh.existsSync()) { await runExec("/bin/sh", [syncSh.path]); } } @@ -442,9 +442,13 @@ class PackageCommand extends Command { } catch (e) { stdout.writeln("Error: $e"); } finally { - if (tempDir != null && await tempDir.exists()) { + if (tempDir != null && tempDir.existsSync()) { stdout.writeln("Deleting temp directory"); - await tempDir.delete(recursive: true); + try { + tempDir.deleteSync(recursive: true); + } on Exception catch(e, s){ + verbose('$e\n\n$s'); + } } if (pyodidePyPiServer != null) { stdout.writeln("Shutting down Pyodide PyPI server"); @@ -523,7 +527,7 @@ class PackageCommand extends Command { _pythonDir = Directory( path.join(_buildDir!.path, "build_python_$buildPythonVersion")); - if (!await _pythonDir!.exists()) { + if (!_pythonDir!.existsSync()) { await _pythonDir!.create(); var isArm64 = Platform.version.contains("arm64"); @@ -547,7 +551,7 @@ class PackageCommand extends Command { var pythonArchivePath = path.join(_buildDir!.path, pythonArchiveFilename); - if (!await File(pythonArchivePath).exists()) { + if (!File(pythonArchivePath).existsSync()) { // download Python distr from GitHub final url = "https://github.com/astral-sh/python-build-standalone/releases/download/$buildPythonReleaseDate/$pythonArchiveFilename"; From dc30b298e9b7ddc3ad0360cf20b2455c09ae9e93 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Mon, 10 Nov 2025 04:25:43 -0500 Subject: [PATCH 10/24] Update to flutter 3.35 --- .../example/flask_example/pubspec.yaml | 4 +- .../example/flet_example/pubspec.lock | 937 ------------------ .../example/flet_example/pubspec.yaml | 8 +- .../example/run_example/app/app.zip.hash | 2 +- .../example/run_example/pubspec.yaml | 3 +- src/serious_python/pubspec.yaml | 8 +- src/serious_python_android/pubspec.yaml | 6 +- src/serious_python_darwin/pubspec.yaml | 6 +- src/serious_python_linux/pubspec.yaml | 6 +- .../pubspec.yaml | 6 +- src/serious_python_windows/pubspec.yaml | 6 +- .../windows/CMakeLists.txt | 4 +- 12 files changed, 37 insertions(+), 959 deletions(-) delete mode 100644 src/serious_python/example/flet_example/pubspec.lock diff --git a/src/serious_python/example/flask_example/pubspec.yaml b/src/serious_python/example/flask_example/pubspec.yaml index 905a6750..9e2fb38d 100644 --- a/src/serious_python/example/flask_example/pubspec.yaml +++ b/src/serious_python/example/flask_example/pubspec.yaml @@ -19,8 +19,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=3.0.3 <4.0.0" - flutter: ">=3.7.0" + sdk: '>=3.7.0 < 4.0.0' + flutter: '>=3.27.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions diff --git a/src/serious_python/example/flet_example/pubspec.lock b/src/serious_python/example/flet_example/pubspec.lock deleted file mode 100644 index c69ea38b..00000000 --- a/src/serious_python/example/flet_example/pubspec.lock +++ /dev/null @@ -1,937 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - archive: - dependency: transitive - description: - name: archive - sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" - url: "https://pub.dev" - source: hosted - version: "4.0.7" - args: - dependency: transitive - description: - name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" - source: hosted - version: "2.7.0" - async: - dependency: transitive - description: - name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" - url: "https://pub.dev" - source: hosted - version: "2.13.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - characters: - dependency: transitive - description: - name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - clock: - dependency: transitive - description: - name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" - source: hosted - version: "1.1.2" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - cross_file: - dependency: transitive - description: - name: cross_file - sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" - url: "https://pub.dev" - source: hosted - version: "0.3.4+2" - crypto: - dependency: transitive - description: - name: crypto - sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" - url: "https://pub.dev" - source: hosted - version: "3.0.6" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" - source: hosted - version: "1.0.8" - dbus: - dependency: transitive - description: - name: dbus - sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" - url: "https://pub.dev" - source: hosted - version: "0.7.11" - device_info_plus: - dependency: transitive - description: - name: device_info_plus - sha256: dd0e8e02186b2196c7848c9d394a5fd6e5b57a43a546082c5820b1ec72317e33 - url: "https://pub.dev" - source: hosted - version: "12.2.0" - device_info_plus_platform_interface: - dependency: transitive - description: - name: device_info_plus_platform_interface - sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f - url: "https://pub.dev" - source: hosted - version: "7.0.3" - equatable: - dependency: transitive - description: - name: equatable - sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" - url: "https://pub.dev" - source: hosted - version: "2.0.7" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" - source: hosted - version: "1.3.3" - ffi: - dependency: transitive - description: - name: ffi - sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" - file_picker: - dependency: transitive - description: - name: file_picker - sha256: f2d9f173c2c14635cc0e9b14c143c49ef30b4934e8d1d274d6206fcb0086a06f - url: "https://pub.dev" - source: hosted - version: "10.3.3" - flet: - dependency: "direct main" - description: - path: "packages/flet" - ref: HEAD - resolved-ref: "42dcc718a9ddd6b2c53100fed8e9c6afbb78e223" - url: "https://github.com/flet-dev/flet.git" - source: git - version: "0.70.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_driver: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - flutter_highlight: - dependency: transitive - description: - name: flutter_highlight - sha256: "7b96333867aa07e122e245c033b8ad622e4e3a42a1a2372cbb098a2541d8782c" - url: "https://pub.dev" - source: hosted - version: "0.7.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 - url: "https://pub.dev" - source: hosted - version: "2.0.3" - flutter_localizations: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - flutter_markdown: - dependency: transitive - description: - name: flutter_markdown - sha256: e7bbc718adc9476aa14cfddc1ef048d2e21e4e8f18311aaac723266db9f9e7b5 - url: "https://pub.dev" - source: hosted - version: "0.7.6+2" - flutter_plugin_android_lifecycle: - dependency: transitive - description: - name: flutter_plugin_android_lifecycle - sha256: "306f0596590e077338312f38837f595c04f28d6cdeeac392d3d74df2f0003687" - url: "https://pub.dev" - source: hosted - version: "2.0.32" - flutter_svg: - dependency: transitive - description: - name: flutter_svg - sha256: b9c2ad5872518a27507ab432d1fb97e8813b05f0fc693f9d40fad06d073e0678 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - fuchsia_remote_debug_protocol: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - glob: - dependency: transitive - description: - name: glob - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" - source: hosted - version: "2.1.3" - highlight: - dependency: transitive - description: - name: highlight - sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21" - url: "https://pub.dev" - source: hosted - version: "0.7.0" - http: - dependency: transitive - description: - name: http - sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007 - url: "https://pub.dev" - source: hosted - version: "1.5.0" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" - source: hosted - version: "4.1.2" - integration_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - intl: - dependency: transitive - description: - name: intl - sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.dev" - source: hosted - version: "0.20.2" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.dev" - source: hosted - version: "4.9.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.dev" - source: hosted - version: "11.0.2" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.dev" - source: hosted - version: "3.0.10" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - lints: - dependency: transitive - description: - name: lints - sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - logging: - dependency: transitive - description: - name: logging - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" - source: hosted - version: "1.3.0" - markdown: - dependency: transitive - description: - name: markdown - sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" - url: "https://pub.dev" - source: hosted - version: "7.3.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.dev" - source: hosted - version: "0.12.17" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" - source: hosted - version: "0.11.1" - meta: - dependency: transitive - description: - name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.dev" - source: hosted - version: "1.16.0" - msgpack_dart: - dependency: transitive - description: - name: msgpack_dart - sha256: c2d235ed01f364719b5296aecf43ac330f0d7bc865fa134d0d7910a40454dffb - url: "https://pub.dev" - source: hosted - version: "1.0.1" - nested: - dependency: transitive - description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - package_info_plus: - dependency: "direct main" - description: - name: package_info_plus - sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" - url: "https://pub.dev" - source: hosted - version: "8.3.1" - package_info_plus_platform_interface: - dependency: transitive - description: - name: package_info_plus_platform_interface - sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - path: - dependency: "direct main" - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - path_parsing: - dependency: transitive - description: - name: path_parsing - sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - path_provider: - dependency: "direct main" - description: - name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: e122c5ea805bb6773bb12ce667611265980940145be920cd09a4b0ec0285cb16 - url: "https://pub.dev" - source: hosted - version: "2.2.20" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: efaec349ddfc181528345c56f8eda9d6cccd71c177511b132c6a0ddaefaa2738 - url: "https://pub.dev" - source: hosted - version: "2.4.3" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" - source: hosted - version: "2.3.0" - petitparser: - dependency: transitive - description: - name: petitparser - sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" - url: "https://pub.dev" - source: hosted - version: "6.1.0" - platform: - dependency: transitive - description: - name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" - source: hosted - version: "3.1.6" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - posix: - dependency: transitive - description: - name: posix - sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" - url: "https://pub.dev" - source: hosted - version: "6.0.3" - process: - dependency: transitive - description: - name: process - sha256: c6248e4526673988586e8c00bb22a49210c258dc91df5227d5da9748ecf79744 - url: "https://pub.dev" - source: hosted - version: "5.0.5" - provider: - dependency: transitive - description: - name: provider - sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" - url: "https://pub.dev" - source: hosted - version: "6.1.5+1" - screen_retriever: - dependency: transitive - description: - name: screen_retriever - sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - screen_retriever_linux: - dependency: transitive - description: - name: screen_retriever_linux - sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18 - url: "https://pub.dev" - source: hosted - version: "0.2.0" - screen_retriever_macos: - dependency: transitive - description: - name: screen_retriever_macos - sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - screen_retriever_platform_interface: - dependency: transitive - description: - name: screen_retriever_platform_interface - sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0 - url: "https://pub.dev" - source: hosted - version: "0.2.0" - screen_retriever_windows: - dependency: transitive - description: - name: screen_retriever_windows - sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - screenshot: - dependency: transitive - description: - name: screenshot - sha256: "63817697a7835e6ce82add4228e15d233b74d42975c143ad8cfe07009fab866b" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - sensors_plus: - dependency: transitive - description: - name: sensors_plus - sha256: "89e2bfc3d883743539ce5774a2b93df61effde40ff958ecad78cd66b1a8b8d52" - url: "https://pub.dev" - source: hosted - version: "6.1.2" - sensors_plus_platform_interface: - dependency: transitive - description: - name: sensors_plus_platform_interface - sha256: "58815d2f5e46c0c41c40fb39375d3f127306f7742efe3b891c0b1c87e2b5cd5d" - url: "https://pub.dev" - source: hosted - version: "2.0.1" - serious_python: - dependency: "direct main" - description: - path: "../.." - relative: true - source: path - version: "0.9.4+1" - serious_python_android: - dependency: transitive - description: - path: "../../../serious_python_android" - relative: true - source: path - version: "0.9.4+1" - serious_python_darwin: - dependency: transitive - description: - path: "../../../serious_python_darwin" - relative: true - source: path - version: "0.9.4+1" - serious_python_linux: - dependency: transitive - description: - path: "../../../serious_python_linux" - relative: true - source: path - version: "0.9.4+1" - serious_python_platform_interface: - dependency: transitive - description: - path: "../../../serious_python_platform_interface" - relative: true - source: path - version: "0.9.4+1" - serious_python_windows: - dependency: transitive - description: - path: "../../../serious_python_windows" - relative: true - source: path - version: "0.9.4+1" - shared_preferences: - dependency: transitive - description: - name: shared_preferences - sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" - url: "https://pub.dev" - source: hosted - version: "2.5.3" - shared_preferences_android: - dependency: transitive - description: - name: shared_preferences_android - sha256: "34266009473bf71d748912da4bf62d439185226c03e01e2d9687bc65bbfcb713" - url: "https://pub.dev" - source: hosted - version: "2.4.15" - shared_preferences_foundation: - dependency: transitive - description: - name: shared_preferences_foundation - sha256: "1c33a907142607c40a7542768ec9badfd16293bac51da3a4482623d15845f88b" - url: "https://pub.dev" - source: hosted - version: "2.5.5" - shared_preferences_linux: - dependency: transitive - description: - name: shared_preferences_linux - sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shared_preferences_platform_interface: - dependency: transitive - description: - name: shared_preferences_platform_interface - sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shared_preferences_web: - dependency: transitive - description: - name: shared_preferences_web - sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 - url: "https://pub.dev" - source: hosted - version: "2.4.3" - shared_preferences_windows: - dependency: transitive - description: - name: shared_preferences_windows - sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shelf: - dependency: transitive - description: - name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 - url: "https://pub.dev" - source: hosted - version: "1.4.2" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - source_span: - dependency: transitive - description: - name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.dev" - source: hosted - version: "1.10.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - sync_http: - dependency: transitive - description: - name: sync_http - sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" - url: "https://pub.dev" - source: hosted - version: "0.3.1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test_api: - dependency: transitive - description: - name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" - url: "https://pub.dev" - source: hosted - version: "0.7.6" - toml: - dependency: transitive - description: - name: toml - sha256: d968d149c8bd06dc14e09ea3a140f90a3f2ba71949e7a91df4a46f3107400e71 - url: "https://pub.dev" - source: hosted - version: "0.16.0" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - url_launcher: - dependency: transitive - description: - name: url_launcher - sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 - url: "https://pub.dev" - source: hosted - version: "6.3.2" - url_launcher_android: - dependency: transitive - description: - name: url_launcher_android - sha256: "5c8b6c2d89a78f5a1cca70a73d9d5f86c701b36b42f9c9dac7bad592113c28e9" - url: "https://pub.dev" - source: hosted - version: "6.3.24" - url_launcher_ios: - dependency: transitive - description: - name: url_launcher_ios - sha256: "6b63f1441e4f653ae799166a72b50b1767321ecc263a57aadf825a7a2a5477d9" - url: "https://pub.dev" - source: hosted - version: "6.3.5" - url_launcher_linux: - dependency: transitive - description: - name: url_launcher_linux - sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - url_launcher_macos: - dependency: transitive - description: - name: url_launcher_macos - sha256: "8262208506252a3ed4ff5c0dc1e973d2c0e0ef337d0a074d35634da5d44397c9" - url: "https://pub.dev" - source: hosted - version: "3.2.4" - url_launcher_platform_interface: - dependency: transitive - description: - name: url_launcher_platform_interface - sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - url_launcher_web: - dependency: transitive - description: - name: url_launcher_web - sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - url_launcher_windows: - dependency: transitive - description: - name: url_launcher_windows - sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" - url: "https://pub.dev" - source: hosted - version: "3.1.4" - url_strategy: - dependency: "direct main" - description: - name: url_strategy - sha256: "42b68b42a9864c4d710401add17ad06e28f1c1d5500c93b98c431f6b0ea4ab87" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - vector_graphics: - dependency: transitive - description: - name: vector_graphics - sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6 - url: "https://pub.dev" - source: hosted - version: "1.1.19" - vector_graphics_codec: - dependency: transitive - description: - name: vector_graphics_codec - sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" - url: "https://pub.dev" - source: hosted - version: "1.1.13" - vector_graphics_compiler: - dependency: transitive - description: - name: vector_graphics_compiler - sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc - url: "https://pub.dev" - source: hosted - version: "1.1.19" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.dev" - source: hosted - version: "2.2.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" - url: "https://pub.dev" - source: hosted - version: "15.0.2" - web: - dependency: transitive - description: - name: web - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - web_socket: - dependency: transitive - description: - name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 - url: "https://pub.dev" - source: hosted - version: "3.0.3" - webdriver: - dependency: transitive - description: - name: webdriver - sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - win32: - dependency: transitive - description: - name: win32 - sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e - url: "https://pub.dev" - source: hosted - version: "5.15.0" - win32_registry: - dependency: transitive - description: - name: win32_registry - sha256: "6f1b564492d0147b330dd794fee8f512cec4977957f310f9951b5f9d83618dae" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - window_manager: - dependency: transitive - description: - name: window_manager - sha256: "7eb6d6c4164ec08e1bf978d6e733f3cebe792e2a23fb07cbca25c2872bfdbdcd" - url: "https://pub.dev" - source: hosted - version: "0.5.1" - window_to_front: - dependency: transitive - description: - name: window_to_front - sha256: "7aef379752b7190c10479e12b5fd7c0b9d92adc96817d9e96c59937929512aee" - url: "https://pub.dev" - source: hosted - version: "0.0.3" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - xml: - dependency: transitive - description: - name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 - url: "https://pub.dev" - source: hosted - version: "6.5.0" -sdks: - dart: ">=3.9.0 <4.0.0" - flutter: ">=3.35.0" diff --git a/src/serious_python/example/flet_example/pubspec.yaml b/src/serious_python/example/flet_example/pubspec.yaml index fc0e369d..8ba3cf2a 100644 --- a/src/serious_python/example/flet_example/pubspec.yaml +++ b/src/serious_python/example/flet_example/pubspec.yaml @@ -19,8 +19,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=3.0.3 <4.0.0" - flutter: ">=3.7.0" + sdk: '>=3.7.0 < 4.0.0' + flutter: '>=3.27.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -43,7 +43,7 @@ dependencies: path: ^1.9.1 url_strategy: ^0.2.0 path_provider: ^2.1.5 - package_info_plus: ^8.0.2 + package_info_plus: ^9.0.0 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. @@ -58,7 +58,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^2.0.0 + flutter_lints: ^6.0.0 integration_test: sdk: flutter diff --git a/src/serious_python/example/run_example/app/app.zip.hash b/src/serious_python/example/run_example/app/app.zip.hash index 615dadf3..293ce40f 100644 --- a/src/serious_python/example/run_example/app/app.zip.hash +++ b/src/serious_python/example/run_example/app/app.zip.hash @@ -1 +1 @@ -2b009202b20832851c62f09fd3dc603131d9efa45da27efb94eb21b32da28ed0 \ No newline at end of file +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 \ No newline at end of file diff --git a/src/serious_python/example/run_example/pubspec.yaml b/src/serious_python/example/run_example/pubspec.yaml index edfc2819..3ca643a3 100644 --- a/src/serious_python/example/run_example/pubspec.yaml +++ b/src/serious_python/example/run_example/pubspec.yaml @@ -19,7 +19,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: '>=3.1.3 <4.0.0' + sdk: '>=3.7.0 < 4.0.0' + flutter: '>=3.27.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions diff --git a/src/serious_python/pubspec.yaml b/src/serious_python/pubspec.yaml index 29b31d0b..e880db5f 100644 --- a/src/serious_python/pubspec.yaml +++ b/src/serious_python/pubspec.yaml @@ -11,9 +11,11 @@ platforms: windows: linux: +resolution: workspace + environment: - sdk: ">=3.0.0 <4.0.0" - flutter: ">=3.7.0" + sdk: '>=3.7.0 < 4.0.0' + flutter: '>=3.27.0' flutter: plugin: @@ -47,7 +49,7 @@ dependencies: archive: ^4.0.7 path: ^1.9.1 args: ^2.7.0 - toml: ^0.16.0 + toml: ^0.17.0 http: ^1.5.0 shelf: ^1.4.2 crypto: ^3.0.6 diff --git a/src/serious_python_android/pubspec.yaml b/src/serious_python_android/pubspec.yaml index ebe92708..61884014 100644 --- a/src/serious_python_android/pubspec.yaml +++ b/src/serious_python_android/pubspec.yaml @@ -4,9 +4,11 @@ homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python version: 0.9.4+1 +resolution: workspace + environment: - sdk: ">=3.0.0 <4.0.0" - flutter: ">=3.7.0" + sdk: '>=3.7.0 < 4.0.0' + flutter: '>=3.27.0' dependencies: flutter: diff --git a/src/serious_python_darwin/pubspec.yaml b/src/serious_python_darwin/pubspec.yaml index dce6ea66..6799118a 100644 --- a/src/serious_python_darwin/pubspec.yaml +++ b/src/serious_python_darwin/pubspec.yaml @@ -4,9 +4,11 @@ homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python version: 0.9.4+1 +resolution: workspace + environment: - sdk: ">=3.0.0 <4.0.0" - flutter: ">=3.7.0" + sdk: '>=3.7.0 < 4.0.0' + flutter: '>=3.27.0' dependencies: flutter: diff --git a/src/serious_python_linux/pubspec.yaml b/src/serious_python_linux/pubspec.yaml index 6a11890d..86776c2e 100644 --- a/src/serious_python_linux/pubspec.yaml +++ b/src/serious_python_linux/pubspec.yaml @@ -4,9 +4,11 @@ homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python version: 0.9.4+1 +resolution: workspace + environment: - sdk: ">=3.0.0 <4.0.0" - flutter: ">=3.7.0" + sdk: '>=3.7.0 < 4.0.0' + flutter: '>=3.27.0' dependencies: flutter: diff --git a/src/serious_python_platform_interface/pubspec.yaml b/src/serious_python_platform_interface/pubspec.yaml index 3ddafc38..956a5730 100644 --- a/src/serious_python_platform_interface/pubspec.yaml +++ b/src/serious_python_platform_interface/pubspec.yaml @@ -4,9 +4,11 @@ homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python version: 0.9.4+1 +resolution: workspace + environment: - sdk: ">=3.0.0 <4.0.0" - flutter: ">=3.7.0" + sdk: '>=3.7.0 < 4.0.0' + flutter: '>=3.27.0' dependencies: flutter: diff --git a/src/serious_python_windows/pubspec.yaml b/src/serious_python_windows/pubspec.yaml index cb4c77c5..10fc1ac6 100644 --- a/src/serious_python_windows/pubspec.yaml +++ b/src/serious_python_windows/pubspec.yaml @@ -4,9 +4,11 @@ homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python version: 0.9.4+1 +resolution: workspace + environment: - sdk: ">=3.0.0 <4.0.0" - flutter: ">=3.7.0" + sdk: '>=3.7.0 < 4.0.0' + flutter: '>=3.27.0' dependencies: flutter: diff --git a/src/serious_python_windows/windows/CMakeLists.txt b/src/serious_python_windows/windows/CMakeLists.txt index b17aee4b..a9280026 100644 --- a/src/serious_python_windows/windows/CMakeLists.txt +++ b/src/serious_python_windows/windows/CMakeLists.txt @@ -101,7 +101,9 @@ add_custom_command(TARGET CopyPythonDLLs POST_BUILD ) if(DEFINED ENV{SERIOUS_PYTHON_SITE_PACKAGES}) - add_custom_command(TARGET CopyPythonDLLs POST_BUILD + add_custom_target(CopySitePackages ALL) + add_dependencies(CopySitePackages CopyPythonDLLs) + add_custom_command(TARGET CopySitePackages POST_BUILD COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/runner/$<$:Release>$<$:Debug>/site-packages" COMMAND ${CMAKE_COMMAND} -E make_directory From 780da34bf4b669b8f3947c40c799a7e688005ba3 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Wed, 26 Nov 2025 04:22:05 -0500 Subject: [PATCH 11/24] Change file method calls to sync --- src/serious_python/bin/package_command.dart | 492 +++++++++++++------- 1 file changed, 321 insertions(+), 171 deletions(-) diff --git a/src/serious_python/bin/package_command.dart b/src/serious_python/bin/package_command.dart index 6d1f9eab..c3d5aee0 100644 --- a/src/serious_python/bin/package_command.dart +++ b/src/serious_python/bin/package_command.dart @@ -32,32 +32,34 @@ const platforms = { "iphoneos.arm64": {"tag": "ios-13.0-arm64-iphoneos", "mac_ver": ""}, "iphonesimulator.arm64": { "tag": "ios-13.0-arm64-iphonesimulator", - "mac_ver": "" + "mac_ver": "", }, "iphonesimulator.x86_64": { "tag": "ios-13.0-x86_64-iphonesimulator", - "mac_ver": "" - } + "mac_ver": "", + }, }, "Android": { "arm64-v8a": {"tag": "android-24-arm64-v8a", "mac_ver": ""}, "armeabi-v7a": {"tag": "android-24-armeabi-v7a", "mac_ver": ""}, "x86_64": {"tag": "android-24-x86_64", "mac_ver": ""}, - "x86": {"tag": "android-24-x86", "mac_ver": ""} + "x86": {"tag": "android-24-x86", "mac_ver": ""}, }, "Pyodide": { - "": {"tag": "pyodide-2024.0-wasm32", "mac_ver": ""} + "": {"tag": "pyodide-2024.0-wasm32", "mac_ver": ""}, }, "Darwin": { "arm64": {"tag": "", "mac_ver": "arm64"}, - "x86_64": {"tag": "", "mac_ver": "x86_64"} + "x86_64": {"tag": "", "mac_ver": "x86_64"}, }, "Windows": { - "": {"tag": "", "mac_ver": ""} + "arm64": {"tag": "", "mac_ver": ""}, + "x86_64": {"tag": "", "mac_ver": ""}, }, "Linux": { - "": {"tag": "", "mac_ver": ""} - } + "arm64": {"tag": "", "mac_ver": ""}, + "x86_64": {"tag": "", "mac_ver": ""}, + }, }; const junkFilesDesktop = [ @@ -94,46 +96,80 @@ class PackageCommand extends Command { final description = "Packages Python app into Flutter asset."; PackageCommand() { - argParser.addOption('platform', - abbr: "p", - allowed: ["iOS", "Android", "Pyodide", "Windows", "Linux", "Darwin"], - mandatory: true, - help: "Install dependencies for specific platform, e.g. 'Android'."); - argParser.addMultiOption('arch', - help: - "Install dependencies for specific architectures only. Leave empty to install all supported architectures."); - argParser.addMultiOption('requirements', - abbr: "r", - help: "The list of dependencies to install. Allows any pip options.'", - splitCommas: false); - argParser.addOption('asset', - abbr: 'a', - help: - "Output asset path, relative to pubspec.yaml, to package Python program into."); - argParser.addMultiOption('exclude', - help: - "List of relative paths to exclude from app package, e.g. \"assets,build\"."); - argParser.addFlag("skip-site-packages", - help: "Skip installation of site packages.", negatable: false); - argParser.addFlag("compile-app", - help: "Compile Python application before packaging.", negatable: false); - argParser.addFlag("compile-packages", - help: "Compile application packages before packaging.", - negatable: false); - argParser.addFlag("cleanup", - help: - "Cleanup app and packages from unneccessary files and directories.", - negatable: false); - argParser.addFlag("cleanup-app", - help: "Cleanup app from unneccessary files and directories.", - negatable: false); - argParser.addMultiOption('cleanup-app-files', - help: "List of globs to delete extra app files and directories."); - argParser.addFlag("cleanup-packages", - help: "Cleanup packages from unneccessary files and directories.", - negatable: false); - argParser.addMultiOption('cleanup-package-files', - help: "List of globs to delete extra packages files and directories."); + argParser.addOption( + 'platform', + abbr: "p", + allowed: ["iOS", "Android", "Pyodide", "Windows", "Linux", "Darwin"], + mandatory: true, + help: "Install dependencies for specific platform, e.g. 'Android'.", + ); + argParser.addMultiOption( + 'arch', + help: + "Install dependencies for specific architectures only. Leave empty to install all supported architectures.", + ); + argParser.addMultiOption( + 'requirements', + abbr: "r", + help: "The list of dependencies to install. Allows any pip options.'", + splitCommas: false, + ); + argParser.addOption( + 'build-type', + abbr: 'b', + allowed: ['Debug', 'Profile', 'Release'], + defaultsTo: 'Release', + help: "Build type of application, one of debug, profile or release.", + ); + argParser.addOption( + 'asset', + abbr: 'a', + help: + "Output asset path, relative to pubspec.yaml, to package Python program into.", + ); + argParser.addMultiOption( + 'exclude', + help: + "List of relative paths to exclude from app package, e.g. \"assets,build\".", + ); + argParser.addFlag( + "skip-site-packages", + help: "Skip installation of site packages.", + negatable: false, + ); + argParser.addFlag( + "compile-app", + help: "Compile Python application before packaging.", + negatable: false, + ); + argParser.addFlag( + "compile-packages", + help: "Compile application packages before packaging.", + negatable: false, + ); + argParser.addFlag( + "cleanup", + help: "Cleanup app and packages from unneccessary files and directories.", + negatable: false, + ); + argParser.addFlag( + "cleanup-app", + help: "Cleanup app from unneccessary files and directories.", + negatable: false, + ); + argParser.addMultiOption( + 'cleanup-app-files', + help: "List of globs to delete extra app files and directories.", + ); + argParser.addFlag( + "cleanup-packages", + help: "Cleanup packages from unneccessary files and directories.", + negatable: false, + ); + argParser.addMultiOption( + 'cleanup-package-files', + help: "List of globs to delete extra packages files and directories.", + ); argParser.addFlag("verbose", help: "Verbose output.", negatable: false); } @@ -160,6 +196,7 @@ class PackageCommand extends Command { String platform = argResults?['platform']; List archArg = argResults?['arch']; List requirements = argResults?['requirements']; + String buildType = argResults?['build-type']; String? assetPath = argResults?['asset']; List exclude = argResults?['exclude']; bool skipSitePackages = argResults?["skip-site-packages"]; @@ -204,7 +241,8 @@ class PackageCommand extends Command { if (platform == "Pyodide") { pyodidePyPiServer = await startSimpleServer(); extraPyPiIndexes.add( - "http://${pyodidePyPiServer.address.host}:${pyodidePyPiServer.port}/simple"); + "http://${pyodidePyPiServer.address.host}:${pyodidePyPiServer.port}/simple", + ); } stdout.writeln("Extra PyPi indexes: $extraPyPiIndexes"); @@ -212,7 +250,7 @@ class PackageCommand extends Command { // ensure standard Dart/Flutter "build" directory exists _buildDir = Directory(path.join(currentPath, "build")); if (!_buildDir!.existsSync()) { - await _buildDir!.create(); + _buildDir!.createSync(); } // asset path @@ -226,18 +264,23 @@ class PackageCommand extends Command { final dest = File(path.join(currentPath, assetPath)); if (!dest.parent.existsSync()) { stdout.writeln("Creating asset directory: ${dest.parent.path}"); - await dest.parent.create(recursive: true); + dest.parent.createSync(recursive: true); } // create temp dir - tempDir = await Directory.systemTemp.createTemp('serious_python_temp'); + tempDir = Directory.systemTemp.createTempSync('serious_python_temp'); stdout.writeln("Created temp directory: ${tempDir.path}"); // copy app to a temp dir stdout.writeln( - "Copying Python app from ${sourceDir.path} to a temp directory"); - await copyDirectory(sourceDir, tempDir, sourceDir.path, - exclude.map((s) => s.trim()).toList()); + "Copying Python app from ${sourceDir.path} to a temp directory", + ); + await copyDirectory( + sourceDir, + tempDir, + sourceDir.path, + exclude.map((s) => s.trim()).toList(), + ); // compile all python code if (compileApp) { @@ -253,7 +296,8 @@ class PackageCommand extends Command { var allJunkFiles = [...junkFiles, ...cleanupAppFiles]; if (_verbose) { verbose( - "Delete unnecessary app files and directories: $allJunkFiles"); + "Delete unnecessary app files and directories: $allJunkFiles", + ); } else { stdout.writeln(("Cleanup app")); } @@ -263,25 +307,33 @@ class PackageCommand extends Command { // install requirements if (requirements.isNotEmpty && !skipSitePackages) { String? sitePackagesRoot; - - if (platform != "Pyodide") { - if (Platform.environment - .containsKey(sitePackagesEnvironmentVariable)) { + if (platform == 'Windows' || platform == 'Linux') { + sitePackagesRoot = path.join(tempDir.path, defaultSitePackagesDir); + } else if (platform != "Pyodide") { + if (Platform.environment.containsKey( + sitePackagesEnvironmentVariable, + )) { sitePackagesRoot = Platform.environment[sitePackagesEnvironmentVariable]; } if (sitePackagesRoot == null || sitePackagesRoot.isEmpty) { + verbose( + "Setting sitePackagesRoot(./build/site-packages): $sitePackagesRoot", + ); sitePackagesRoot = path.join(currentPath, "build", "site-packages"); } } else { + verbose( + "Setting sitePackagesRoot(tempDir,defaultSitePackagesDir): $sitePackagesRoot", + ); sitePackagesRoot = path.join(tempDir.path, defaultSitePackagesDir); } - if (Directory(sitePackagesRoot).existsSync()) { - await for (var f in Directory(sitePackagesRoot) - .list() - .where((f) => !path.basename(f.path).startsWith("."))) { - await f.delete(recursive: true); + verbose("Deleting packages from sitePackagesRoot: $sitePackagesRoot"); + await for (var f in Directory( + sitePackagesRoot, + ).list().where((f) => !path.basename(f.path).startsWith("."))) { + f.deleteSync(recursive: true); } } @@ -291,57 +343,94 @@ class PackageCommand extends Command { if (archArg.isNotEmpty && !archArg.contains(arch.key)) { continue; } - String? sitePackagesDir; + stdout.writeln( + "Invoking pip for platform/arch: $platform/${arch.key}", + ); + String sitePackagesDir = sitePackagesRoot; Map? pipEnv; Directory? sitecustomizeDir; try { // customized pip // create temp dir with sitecustomize.py for mobile and web - sitecustomizeDir = await Directory.systemTemp - .createTemp('serious_python_sitecustomize'); - var sitecustomizePath = - path.join(sitecustomizeDir.path, "sitecustomize.py"); + sitecustomizeDir = Directory.systemTemp.createTempSync( + 'serious_python_sitecustomize', + ); + var sitecustomizePath = path.join( + sitecustomizeDir.path, + "sitecustomize.py", + ); if (_verbose) { verbose( - "Configured $platform/${arch.key} platform with sitecustomize.py at $sitecustomizePath"); + "Configured $platform/${arch.key} platform with sitecustomize.py at $sitecustomizePath", + ); } else { stdout.writeln( - "Configured $platform/${arch.key} platform with sitecustomize.py"); + "Configured $platform/${arch.key} platform with sitecustomize.py", + ); } - await File(sitecustomizePath).writeAsString(sitecustomizePy - .replaceAll( - "{platform}", arch.value["tag"]!.isNotEmpty ? platform : "") - .replaceAll("{tag}", arch.value["tag"]!) - .replaceAll("{mac_ver}", arch.value["mac_ver"]!)); + File(sitecustomizePath).writeAsStringSync( + sitecustomizePy + .replaceAll( + "{platform}", + arch.value["tag"]!.isNotEmpty ? platform : "", + ) + .replaceAll("{tag}", arch.value["tag"]!) + .replaceAll("{mac_ver}", arch.value["mac_ver"]!), + ); // print(File(sitecustomizePath).readAsStringSync()); pipEnv = { - "PYTHONPATH": - [sitecustomizeDir.path].join(Platform.isWindows ? ";" : ":"), + "PYTHONPATH": [ + sitecustomizeDir.path, + ].join(Platform.isWindows ? ";" : ":"), }; - - sitePackagesDir = arch.key.isNotEmpty - ? path.join(sitePackagesRoot, arch.key) - : sitePackagesRoot; - if (!await Directory(sitePackagesDir).exists()) { - await Directory(sitePackagesDir).create(recursive: true); + String buildDir = path.join( + currentPath, + 'build', + Platform.operatingSystem, + arch.key == "x86_64" ? "x64" : arch.key, + "runner", + Platform.isWindows ? buildType : buildType.toLowerCase(), + ); + sitePackagesDir = + arch.key.isNotEmpty + ? Platform.isWindows + ? path.join(buildDir, "site-packages") + : path.join(buildDir, "python3.12", "site-packages") + : sitePackagesRoot; + if (!Directory(sitePackagesDir).existsSync()) { + verbose("Creating sitePackagesDir: $sitePackagesDir"); + Directory(sitePackagesDir).createSync(recursive: true); } - stdout.writeln( - "Installing $requirements with pip command to $sitePackagesDir"); + verbose( + "Installing $requirements with pip command to $sitePackagesDir", + ); List pipArgs = ["--disable-pip-version-check"]; + if (compilePackages) { + pipArgs.addAll(['--compile', '--only-binary=:all:']); + if (platform == 'Windows') { + if (arch.key == 'arm64') { + pipArgs.addAll(["--platform", "win_arm64"]); + } else { + pipArgs.addAll(["--platform", "win_amd64"]); + } + } + } + if (isMobile || isWeb) { pipArgs.addAll(["--only-binary", ":all:"]); - if (Platform.environment - .containsKey(allowSourceDistrosEnvironmentVariable)) { + if (Platform.environment.containsKey( + allowSourceDistrosEnvironmentVariable, + )) { pipArgs.addAll([ "--no-binary", - Platform.environment[allowSourceDistrosEnvironmentVariable]! + Platform.environment[allowSourceDistrosEnvironmentVariable]!, ]); } } @@ -358,29 +447,37 @@ class PackageCommand extends Command { ...pipArgs, '--target', sitePackagesDir, - ...requirements + ...requirements, ], environment: pipEnv); // move $sitePackagesDir/flutter if env var is defined - if (Platform.environment - .containsKey(flutterPackagesFlutterEnvironmentVariable)) { - var flutterPackagesRoot = Platform - .environment[flutterPackagesFlutterEnvironmentVariable]; + if (Platform.environment.containsKey( + flutterPackagesFlutterEnvironmentVariable, + )) { + var flutterPackagesRoot = + Platform + .environment[flutterPackagesFlutterEnvironmentVariable]; var flutterPackagesRootDir = Directory(flutterPackagesRoot!); - var sitePackagesFlutterDir = - Directory(path.join(sitePackagesDir, "flutter")); - if (await sitePackagesFlutterDir.exists()) { + var sitePackagesFlutterDir = Directory( + path.join(sitePackagesDir, "flutter"), + ); + if (sitePackagesFlutterDir.existsSync()) { if (!flutterPackagesCopied) { stdout.writeln( - "Copying Flutter packages to $flutterPackagesRoot"); + "Copying Flutter packages to $flutterPackagesRoot", + ); if (!flutterPackagesRootDir.existsSync()) { - await flutterPackagesRootDir.create(recursive: true); + flutterPackagesRootDir.createSync(recursive: true); } - await copyDirectory(sitePackagesFlutterDir, - flutterPackagesRootDir, sitePackagesFlutterDir.path, []); + await copyDirectory( + sitePackagesFlutterDir, + flutterPackagesRootDir, + sitePackagesFlutterDir.path, + [], + ); flutterPackagesCopied = true; } - await sitePackagesFlutterDir.delete(recursive: true); + sitePackagesFlutterDir.deleteSync(recursive: true); } } @@ -390,6 +487,7 @@ class PackageCommand extends Command { await runPython(['-m', 'compileall', '-b', sitePackagesDir]); verbose("Deleting original .py files"); + await cleanupDir(Directory(sitePackagesDir), ["**.py"]); } @@ -398,32 +496,36 @@ class PackageCommand extends Command { var allJunkFiles = [...junkFiles, ...cleanupPackageFiles]; if (_verbose) { verbose( - "Delete unnecessary package files and directories: $allJunkFiles"); + "Delete unnecessary package files and directories: $allJunkFiles", + ); } else { stdout.writeln(("Cleanup installed packages")); } await cleanupDir(Directory(sitePackagesDir), allJunkFiles); } } finally { - if (sitecustomizeDir != null && await sitecustomizeDir.exists()) { + if (sitecustomizeDir != null && sitecustomizeDir.existsSync()) { verbose( - "Deleting sitecustomize directory ${sitecustomizeDir.path}"); - await sitecustomizeDir.delete(recursive: true); + "Deleting sitecustomize directory ${sitecustomizeDir.path}", + ); + sitecustomizeDir.deleteSync(recursive: true); } } } // for each arch if (platform == "Darwin") { await macos_utils.mergeMacOsSitePackages( - path.join(sitePackagesRoot, "arm64"), - path.join(sitePackagesRoot, "x86_64"), - path.join(sitePackagesRoot), - _verbose); + path.join(sitePackagesRoot, "arm64"), + path.join(sitePackagesRoot, "x86_64"), + path.join(sitePackagesRoot), + _verbose, + ); } // synchronize pod - var syncSh = - File(path.join(sitePackagesRoot, ".pod", "sync_site_packages.sh")); + var syncSh = File( + path.join(sitePackagesRoot, ".pod", "sync_site_packages.sh"), + ); if (syncSh.existsSync()) { await runExec("/bin/sh", [syncSh.path]); } @@ -431,24 +533,26 @@ class PackageCommand extends Command { // create archive stdout.writeln( - "Creating app archive at ${dest.path} from a temp directory"); + "Creating app archive at ${dest.path} from a temp directory", + ); final encoder = ZipFileEncoder(); encoder.zipDirectory(tempDir, filename: dest.path); // create hash file stdout.writeln("Writing app archive hash to ${dest.path}.hash"); - await File("${dest.path}.hash") - .writeAsString(await calculateFileHash(dest.path)); + File( + "${dest.path}.hash", + ).writeAsStringSync(await calculateFileHash(dest.path)); } catch (e) { - stdout.writeln("Error: $e"); + verbose("Error: $e"); } finally { if (tempDir != null && tempDir.existsSync()) { stdout.writeln("Deleting temp directory"); try { tempDir.deleteSync(recursive: true); - } on Exception catch(e, s){ - verbose('$e\n\n$s'); - } + } on Exception catch (e, s) { + verbose('$e\n\n$s'); + } } if (pyodidePyPiServer != null) { stdout.writeln("Shutting down Pyodide PyPI server"); @@ -457,21 +561,31 @@ class PackageCommand extends Command { } } - Future copyDirectory(Directory source, Directory destination, - String rootDir, List excludeList) async { + Future copyDirectory( + Directory source, + Directory destination, + String rootDir, + List excludeList, + ) async { await for (var entity in source.list()) { if (excludeList.contains(path.relative(entity.path, from: rootDir))) { continue; } if (entity is Directory) { - final newDirectory = - Directory(path.join(destination.path, path.basename(entity.path))); - await newDirectory.create(); + final newDirectory = Directory( + path.join(destination.path, path.basename(entity.path)), + ); + newDirectory.createSync(); await copyDirectory( - entity.absolute, newDirectory, rootDir, excludeList); + entity.absolute, + newDirectory, + rootDir, + excludeList, + ); } else if (entity is File) { - await entity - .copy(path.join(destination.path, path.basename(entity.path))); + entity.copySync( + path.join(destination.path, path.basename(entity.path)), + ); } } } @@ -479,23 +593,30 @@ class PackageCommand extends Command { Future cleanupDir(Directory directory, List filesGlobs) async { verbose("Cleanup directory ${directory.path}: $filesGlobs"); await cleanupDirRecursive( - directory, - filesGlobs.map((g) => Glob(g.replaceAll("\\", "/"), - context: path.Context(current: directory.path)))); + directory, + filesGlobs.map( + (g) => Glob( + g.replaceAll("\\", "/"), + context: path.Context(current: directory.path), + ), + ), + ); } Future cleanupDirRecursive( - Directory directory, Iterable globs) async { + Directory directory, + Iterable globs, + ) async { var emptyDir = true; for (var entity in directory.listSync()) { if (globs.any((g) => g.matches(entity.path.replaceAll("\\", "/"))) && - await entity.exists()) { + entity.existsSync()) { verbose("Deleting ${entity.path}"); - await entity.delete(recursive: true); + entity.deleteSync(recursive: true); } else if (entity is Directory) { if (await cleanupDirRecursive(entity, globs)) { verbose("Deleting empty directory ${entity.path}"); - await entity.delete(recursive: true); + entity.deleteSync(recursive: true); } else { emptyDir = false; } @@ -506,8 +627,11 @@ class PackageCommand extends Command { return emptyDir; } - Future runExec(String execPath, List args, - {Map? environment}) async { + Future runExec( + String execPath, + List args, { + Map? environment, + }) async { final proc = await Process.start(execPath, args, environment: environment); await for (final line in proc.stdout.transform(utf8.decoder)) { @@ -521,14 +645,17 @@ class PackageCommand extends Command { return proc.exitCode; } - Future runPython(List args, - {Map? environment}) async { + Future runPython( + List args, { + Map? environment, + }) async { if (_pythonDir == null) { _pythonDir = Directory( - path.join(_buildDir!.path, "build_python_$buildPythonVersion")); + path.join(_buildDir!.path, "build_python_$buildPythonVersion"), + ); if (!_pythonDir!.existsSync()) { - await _pythonDir!.create(); + _pythonDir!.createSync(); var isArm64 = Platform.version.contains("arm64"); @@ -541,15 +668,19 @@ class PackageCommand extends Command { arch = 'x86_64-unknown-linux-gnu'; } else if (Platform.isLinux && isArm64) { arch = 'aarch64-unknown-linux-gnu'; - } else if (Platform.isWindows) { + } else if (Platform.isWindows && !isArm64) { arch = 'x86_64-pc-windows-msvc-shared'; + } else if (Platform.isWindows && isArm64) { + arch = 'aarch64-pc-windows-msvc-shared'; } var pythonArchiveFilename = "cpython-$buildPythonVersion+$buildPythonReleaseDate-$arch-install_only_stripped.tar.gz"; - var pythonArchivePath = - path.join(_buildDir!.path, pythonArchiveFilename); + var pythonArchivePath = path.join( + _buildDir!.path, + pythonArchiveFilename, + ); if (!File(pythonArchivePath).existsSync()) { // download Python distr from GitHub @@ -558,26 +689,33 @@ class PackageCommand extends Command { if (_verbose) { verbose( - "Downloading Python distributive from $url to $pythonArchivePath"); + "Downloading Python distributive from $url to $pythonArchivePath", + ); } else { stdout.writeln( - "Downloading Python distributive from $url to a build directory"); + "Downloading Python distributive from $url to a build directory", + ); } var response = await http.get(Uri.parse(url)); - await File(pythonArchivePath).writeAsBytes(response.bodyBytes); + File(pythonArchivePath).writeAsBytesSync(response.bodyBytes); } // extract Python from archive if (_verbose) { verbose( - "Extracting Python distributive from $pythonArchivePath to ${_pythonDir!.path}"); + "Extracting Python distributive from $pythonArchivePath to ${_pythonDir!.path}", + ); } else { stdout.writeln("Extracting Python distributive"); } - await Process.run( - 'tar', ['-xzf', pythonArchivePath, '-C', _pythonDir!.path]); + await Process.run('tar', [ + '-xzf', + pythonArchivePath, + '-C', + _pythonDir!.path, + ]); if (Platform.isMacOS) { duplicateSysconfigFile(_pythonDir!.path); @@ -585,9 +723,10 @@ class PackageCommand extends Command { } } - var pythonExePath = Platform.isWindows - ? path.join(_pythonDir!.path, 'python', 'python.exe') - : path.join(_pythonDir!.path, 'python', 'bin', 'python3'); + var pythonExePath = + Platform.isWindows + ? path.join(_pythonDir!.path, 'python', 'python.exe') + : path.join(_pythonDir!.path, 'python', 'bin', 'python3'); // Run the python executable verbose([pythonExePath, ...args].join(" ")); @@ -595,8 +734,10 @@ class PackageCommand extends Command { } void duplicateSysconfigFile(String pythonDir) { - final sysConfigGlob = Glob("python/lib/python3.*/_sysconfigdata__*.py", - context: path.Context(current: pythonDir)); + final sysConfigGlob = Glob( + "python/lib/python3.*/_sysconfigdata__*.py", + context: path.Context(current: pythonDir), + ); for (var sysConfig in sysConfigGlob.listSync(root: pythonDir)) { // copy the first found sys config and exit if (sysConfig is File) { @@ -620,8 +761,9 @@ class PackageCommand extends Command { const htmlHeader = "\n"; const htmlFooter = "\n"; - var pyodidePackages = - await fetchJsonFromUrl("$pyodideRootUrl/$pyodideLockFile"); + var pyodidePackages = await fetchJsonFromUrl( + "$pyodideRootUrl/$pyodideLockFile", + ); var wheels = Map.from(pyodidePackages["packages"]) ..removeWhere((k, p) => !p["file_name"].endsWith(".whl")); @@ -632,32 +774,40 @@ class PackageCommand extends Command { var parts = path.split("/"); if (parts.length == 1 && parts[0] == "simple") { return Response.ok( - htmlHeader + - wheels.keys - .map((k) => '$k
\n') - .join("") + - htmlFooter, - headers: {"Content-Type": "text/html"}); + htmlHeader + + wheels.keys + .map((k) => '$k
\n') + .join("") + + htmlFooter, + headers: {"Content-Type": "text/html"}, + ); } else if (parts.length == 2 && parts[0] == "simple") { List links = []; wheels.forEach((k, p) { if (k == parts[1].toLowerCase()) { links.add( - "${p['file_name']}
"); + "${p['file_name']}
", + ); } }); - return Response.ok(htmlHeader + links.join("\n") + htmlFooter, - headers: {"Content-Type": "text/html"}); + return Response.ok( + htmlHeader + links.join("\n") + htmlFooter, + headers: {"Content-Type": "text/html"}, + ); } else { return Response.ok('Request for "${request.url}"'); } } - var handler = - const Pipeline().addMiddleware(logRequests()).addHandler(serveRequest); + var handler = const Pipeline() + .addMiddleware(logRequests()) + .addHandler(serveRequest); - var server = - await shelf_io.serve(handler, '127.0.0.1', await getUnusedPort()); + var server = await shelf_io.serve( + handler, + '127.0.0.1', + await getUnusedPort(), + ); // Enable content compression server.autoCompress = true; From 13cb17959864c60e361df662f83c3babaecc2c69 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Wed, 26 Nov 2025 04:23:37 -0500 Subject: [PATCH 12/24] Format --- src/serious_python/example/flet_example/pubspec.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/serious_python/example/flet_example/pubspec.yaml b/src/serious_python/example/flet_example/pubspec.yaml index 8ba3cf2a..81f06b6f 100644 --- a/src/serious_python/example/flet_example/pubspec.yaml +++ b/src/serious_python/example/flet_example/pubspec.yaml @@ -31,15 +31,12 @@ environment: dependencies: flutter: sdk: flutter - serious_python: path: ../../ - flet: git: url: https://github.com/flet-dev/flet.git path: packages/flet - path: ^1.9.1 url_strategy: ^0.2.0 path_provider: ^2.1.5 From c240946c8e312d9869f907ada35b78c7457d1fdc Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Sun, 30 Nov 2025 07:47:51 -0500 Subject: [PATCH 13/24] Setting sitePackagesDir to build dir --- src/serious_python/bin/package_command.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/serious_python/bin/package_command.dart b/src/serious_python/bin/package_command.dart index c3d5aee0..204459bb 100644 --- a/src/serious_python/bin/package_command.dart +++ b/src/serious_python/bin/package_command.dart @@ -324,7 +324,7 @@ class PackageCommand extends Command { } } else { verbose( - "Setting sitePackagesRoot(tempDir,defaultSitePackagesDir): $sitePackagesRoot", + "Setting sitePackagesRoot(tempDir,defaultSitePackagesDir): ${path.join(tempDir.path, defaultSitePackagesDir)}", ); sitePackagesRoot = path.join(tempDir.path, defaultSitePackagesDir); } @@ -346,7 +346,7 @@ class PackageCommand extends Command { stdout.writeln( "Invoking pip for platform/arch: $platform/${arch.key}", ); - String sitePackagesDir = sitePackagesRoot; + // String sitePackagesDir = sitePackagesRoot; Map? pipEnv; Directory? sitecustomizeDir; @@ -395,7 +395,7 @@ class PackageCommand extends Command { "runner", Platform.isWindows ? buildType : buildType.toLowerCase(), ); - sitePackagesDir = + final sitePackagesDir = arch.key.isNotEmpty ? Platform.isWindows ? path.join(buildDir, "site-packages") From be83409ed184e7c0791d69a1810713fe271d43e5 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Sun, 30 Nov 2025 07:49:12 -0500 Subject: [PATCH 14/24] Using cmake-generator-expressions for comparisons --- src/serious_python_windows/windows/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/serious_python_windows/windows/CMakeLists.txt b/src/serious_python_windows/windows/CMakeLists.txt index a9280026..f0573065 100644 --- a/src/serious_python_windows/windows/CMakeLists.txt +++ b/src/serious_python_windows/windows/CMakeLists.txt @@ -93,11 +93,11 @@ add_custom_command(TARGET CopyPythonDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory "${PYTHON_PACKAGE}/DLLs" "${CMAKE_BINARY_DIR}/runner/$<$:Release>$<$:Debug>/DLLs" - COMMAND IF \"$<$:release>\" == \"release\" DEL \"${CMAKE_BINARY_DIR}/runner/Release/DLLs\\*_d.*\" /S /Q - COMMAND DEL \"${CMAKE_BINARY_DIR}/runner/$<$:Release>$<$:Debug>/DLLs\\*.ico\" /S /Q - COMMAND DEL \"${CMAKE_BINARY_DIR}/runner/$<$:Release>$<$:Debug>/DLLs\\*.cat\" /S /Q - COMMAND DEL \"${CMAKE_BINARY_DIR}/runner/$<$:Release>$<$:Debug>/DLLs\\tcl86t.dll\" /Q - COMMAND DEL \"${CMAKE_BINARY_DIR}/runner/$<$:Release>$<$:Debug>/DLLs\\tk86t.dll\" /Q + COMMAND IF \"$\" == \"1\" (DEL /S /Q \"${CMAKE_BINARY_DIR}/runner/Release/DLLs\\*_d.*\") + COMMAND DEL /S /Q \"${CMAKE_BINARY_DIR}/runner/$<$:Release>$<$:Debug>/DLLs\\*.ico\" + COMMAND DEL /S /Q \"${CMAKE_BINARY_DIR}/runner/$<$:Release>$<$:Debug>/DLLs\\*.cat\" + COMMAND DEL /Q \"${CMAKE_BINARY_DIR}/runner/$<$:Release>$<$:Debug>/DLLs\\tcl86t.dll\" + COMMAND DEL /Q \"${CMAKE_BINARY_DIR}/runner/$<$:Release>$<$:Debug>/DLLs\\tk86t.dll\" ) if(DEFINED ENV{SERIOUS_PYTHON_SITE_PACKAGES}) From c037e4b4a0e511065d8c43aa0987977474c9bda2 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Thu, 18 Dec 2025 10:58:32 -0500 Subject: [PATCH 15/24] Update python compile with no-cache --- src/serious_python/bin/package_command.dart | 27 ++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/serious_python/bin/package_command.dart b/src/serious_python/bin/package_command.dart index 204459bb..28da9697 100644 --- a/src/serious_python/bin/package_command.dart +++ b/src/serious_python/bin/package_command.dart @@ -398,7 +398,7 @@ class PackageCommand extends Command { final sitePackagesDir = arch.key.isNotEmpty ? Platform.isWindows - ? path.join(buildDir, "site-packages") + ? path.join(buildDir, "Lib", "site-packages") : path.join(buildDir, "python3.12", "site-packages") : sitePackagesRoot; if (!Directory(sitePackagesDir).existsSync()) { @@ -413,13 +413,33 @@ class PackageCommand extends Command { List pipArgs = ["--disable-pip-version-check"]; if (compilePackages) { - pipArgs.addAll(['--compile', '--only-binary=:all:']); + pipArgs.addAll(['--compile', '--implementation', 'cp', '--python-version', '3.12', '--only-binary=:all:']); if (platform == 'Windows') { if (arch.key == 'arm64') { pipArgs.addAll(["--platform", "win_arm64"]); } else { pipArgs.addAll(["--platform", "win_amd64"]); } + } else if (platform == 'Linux') { + if (arch.key == 'arm64') { + pipArgs.addAll(["--platform", "manylinux2014_aarch64"]); + } else { + pipArgs.addAll(["--platform", "manylinux2014_x86_64"]); + } + } else if (platform == 'Darwin') { + if (arch.key == 'arm64') { + pipArgs.addAll(["--platform", "macosx_11_0_arm64"]); + } else { + pipArgs.addAll(["--platform", "macosx_10_12_x86_64"]); + } + } else if (platform == 'Android') { + if (arch.key == 'arm64') { + pipArgs.addAll(["--platform", "android_24_arm64_v8a"]); + } else { + pipArgs.addAll(["--platform", "android_24_x86_64"]); + } + } else if (platform == 'IOS') { + pipArgs.addAll(["--platform", "ios_13_0_arm64_iphoneos"]); } } @@ -444,6 +464,7 @@ class PackageCommand extends Command { 'pip', 'install', '--upgrade', + '--no-cache-dir', ...pipArgs, '--target', sitePackagesDir, @@ -549,7 +570,7 @@ class PackageCommand extends Command { if (tempDir != null && tempDir.existsSync()) { stdout.writeln("Deleting temp directory"); try { - tempDir.deleteSync(recursive: true); + await tempDir.delete(recursive: true); } on Exception catch (e, s) { verbose('$e\n\n$s'); } From 4adead8c34be4234885d476f8a090bcc47b94eaa Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Thu, 26 Feb 2026 06:28:39 -0500 Subject: [PATCH 16/24] Update deps --- src/serious_python_android/pubspec.yaml | 9 ++++++++- src/serious_python_darwin/lib/serious_python_darwin.dart | 1 + src/serious_python_darwin/pubspec.yaml | 7 +++++++ src/serious_python_linux/lib/serious_python_linux.dart | 1 + src/serious_python_linux/pubspec.yaml | 7 +++++++ .../lib/src/method_channel_serious_python.dart | 3 ++- src/serious_python_platform_interface/pubspec.yaml | 7 +++++++ .../lib/serious_python_windows.dart | 1 + src/serious_python_windows/pubspec.yaml | 7 +++++++ 9 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/serious_python_android/pubspec.yaml b/src/serious_python_android/pubspec.yaml index ac669829..326b3214 100644 --- a/src/serious_python_android/pubspec.yaml +++ b/src/serious_python_android/pubspec.yaml @@ -2,7 +2,13 @@ name: serious_python_android description: Android implementation of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python +<<<<<<< HEAD +version: 0.9.5+1 + +resolution: workspace +======= version: 0.9.8+1 +>>>>>>> 93d636cc64931cefc89dbcf73cbd57f27fb4d309 environment: sdk: '>=3.7.0 < 4.0.0' @@ -12,6 +18,7 @@ dependencies: flutter: sdk: flutter plugin_platform_interface: ^2.1.8 + meta: ^1.17.0 serious_python_platform_interface: path: ../serious_python_platform_interface path: ^1.9.1 @@ -21,7 +28,7 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^6.0.0 - ffigen: ^19.1.0 + ffigen: ^20.0.0 flutter: plugin: diff --git a/src/serious_python_darwin/lib/serious_python_darwin.dart b/src/serious_python_darwin/lib/serious_python_darwin.dart index 3392ba34..0eb3a69b 100644 --- a/src/serious_python_darwin/lib/serious_python_darwin.dart +++ b/src/serious_python_darwin/lib/serious_python_darwin.dart @@ -1,5 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart'; import 'package:serious_python_platform_interface/serious_python_platform_interface.dart'; /// An implementation of [SeriousPythonPlatform] that uses method channels. diff --git a/src/serious_python_darwin/pubspec.yaml b/src/serious_python_darwin/pubspec.yaml index 0af8d2d1..73a9b58c 100644 --- a/src/serious_python_darwin/pubspec.yaml +++ b/src/serious_python_darwin/pubspec.yaml @@ -2,7 +2,13 @@ name: serious_python_darwin description: iOS and macOS implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python +<<<<<<< HEAD +version: 0.9.5+1 + +resolution: workspace +======= version: 0.9.8+1 +>>>>>>> 93d636cc64931cefc89dbcf73cbd57f27fb4d309 environment: sdk: '>=3.7.0 < 4.0.0' @@ -12,6 +18,7 @@ dependencies: flutter: sdk: flutter plugin_platform_interface: ^2.1.8 + meta: ^1.17.0 serious_python_platform_interface: path: ../serious_python_platform_interface path: ^1.9.1 diff --git a/src/serious_python_linux/lib/serious_python_linux.dart b/src/serious_python_linux/lib/serious_python_linux.dart index c76ab176..d709538d 100644 --- a/src/serious_python_linux/lib/serious_python_linux.dart +++ b/src/serious_python_linux/lib/serious_python_linux.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart'; import 'package:serious_python_platform_interface/serious_python_platform_interface.dart'; class SeriousPythonLinux extends SeriousPythonPlatform { diff --git a/src/serious_python_linux/pubspec.yaml b/src/serious_python_linux/pubspec.yaml index be6f7129..030eb8af 100644 --- a/src/serious_python_linux/pubspec.yaml +++ b/src/serious_python_linux/pubspec.yaml @@ -2,7 +2,13 @@ name: serious_python_linux description: Linux implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python +<<<<<<< HEAD +version: 0.9.5+1 + +resolution: workspace +======= version: 0.9.8+1 +>>>>>>> 93d636cc64931cefc89dbcf73cbd57f27fb4d309 environment: sdk: '>=3.7.0 < 4.0.0' @@ -12,6 +18,7 @@ dependencies: flutter: sdk: flutter plugin_platform_interface: ^2.1.8 + meta: ^1.17.0 serious_python_platform_interface: path: ../serious_python_platform_interface diff --git a/src/serious_python_platform_interface/lib/src/method_channel_serious_python.dart b/src/serious_python_platform_interface/lib/src/method_channel_serious_python.dart index 191cd349..7061cba4 100644 --- a/src/serious_python_platform_interface/lib/src/method_channel_serious_python.dart +++ b/src/serious_python_platform_interface/lib/src/method_channel_serious_python.dart @@ -1,5 +1,6 @@ -import 'package:flutter/foundation.dart' show visibleForTesting; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart'; import '../serious_python_platform_interface.dart'; diff --git a/src/serious_python_platform_interface/pubspec.yaml b/src/serious_python_platform_interface/pubspec.yaml index 849725e8..7dd616c9 100644 --- a/src/serious_python_platform_interface/pubspec.yaml +++ b/src/serious_python_platform_interface/pubspec.yaml @@ -2,7 +2,13 @@ name: serious_python_platform_interface description: A common platform interface for the serious_python plugin. homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python +<<<<<<< HEAD +version: 0.9.5+1 + +resolution: workspace +======= version: 0.9.8+1 +>>>>>>> 93d636cc64931cefc89dbcf73cbd57f27fb4d309 environment: sdk: '>=3.7.0 < 4.0.0' @@ -15,6 +21,7 @@ dependencies: path_provider: ^2.1.5 archive: ^4.0.7 path: ^1.9.1 + meta: ^1.17.0 dev_dependencies: flutter_test: diff --git a/src/serious_python_windows/lib/serious_python_windows.dart b/src/serious_python_windows/lib/serious_python_windows.dart index c0f48cf7..f807860d 100644 --- a/src/serious_python_windows/lib/serious_python_windows.dart +++ b/src/serious_python_windows/lib/serious_python_windows.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart'; import 'package:serious_python_platform_interface/serious_python_platform_interface.dart'; class SeriousPythonWindows extends SeriousPythonPlatform { diff --git a/src/serious_python_windows/pubspec.yaml b/src/serious_python_windows/pubspec.yaml index 5b297ee8..b938212a 100644 --- a/src/serious_python_windows/pubspec.yaml +++ b/src/serious_python_windows/pubspec.yaml @@ -2,7 +2,13 @@ name: serious_python_windows description: Windows implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python +<<<<<<< HEAD +version: 0.9.5+1 + +resolution: workspace +======= version: 0.9.8+1 +>>>>>>> 93d636cc64931cefc89dbcf73cbd57f27fb4d309 environment: sdk: '>=3.7.0 < 4.0.0' @@ -12,6 +18,7 @@ dependencies: flutter: sdk: flutter plugin_platform_interface: ^2.1.8 + meta: ^1.17.0 serious_python_platform_interface: path: ../serious_python_platform_interface From 5e3d78f8aa91fd7856f137b46da3f66865a76c1a Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Thu, 26 Feb 2026 06:50:10 -0500 Subject: [PATCH 17/24] Add searxng example --- .../example/searxng_example/.gitignore | 46 + .../example/searxng_example/README.md | 47 + .../searxng_example/analysis_options.yaml | 29 + .../searxng_example/android/.gitignore | 13 + .../searxng_example/android/app/build.gradle | 72 + .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 34 + .../com/example/flask_example/MainActivity.kt | 6 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 543 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 441 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 720 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1030 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1442 bytes .../app/src/main/res/values-night/styles.xml | 18 + .../app/src/main/res/values/styles.xml | 18 + .../app/src/profile/AndroidManifest.xml | 7 + .../searxng_example/android/build.gradle | 31 + .../searxng_example/android/gradle.properties | 4 + .../gradle/wrapper/gradle-wrapper.properties | 5 + .../searxng_example/android/settings.gradle | 11 + .../searxng_example/app/requirements.txt | 67 + .../app/src/common/__init__.py | 0 .../searxng_example/app/src/common/config.py | 73 + .../example/searxng_example/app/src/main.py | 11 + .../searxng_example/app/src/mcp/__init__.py | 0 .../searxng_example/app/src/mcp/py.typed | 0 .../searxng_example/app/src/mcp/server.py | 141 + .../app/src/runner/__init__.py | 1 + .../searxng_example/app/src/runner/py.typed | 0 .../src/runner/settings/settings_template.yml | 2695 +++++++++++++++++ .../app/src/runner/simplexng.py | 196 ++ .../app/src/shared/__init__.py | 0 .../searxng_example/app/src/shared/py.typed | 0 .../searxng_example/app/src/shared/types.py | 176 ++ .../app/src/tavily/__init__.py | 0 .../searxng_example/app/src/tavily/adapter.py | 215 ++ .../app/src/tavily/py.typed.py | 0 .../src/tavily/settings/tavily_defaults.yml | 3 + .../example/searxng_example/ios/.gitignore | 34 + .../ios/Flutter/AppFrameworkInfo.plist | 26 + .../ios/Flutter/Debug.xcconfig | 2 + .../ios/Flutter/Release.xcconfig | 2 + .../example/searxng_example/ios/Podfile | 44 + .../example/searxng_example/ios/Podfile.lock | 36 + .../ios/Runner.xcodeproj/project.pbxproj | 727 +++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 98 + .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 + .../Icon-App-1024x1024@1x.png | Bin 0 -> 10931 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 294 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 405 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 449 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 281 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 461 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 703 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 405 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 585 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 861 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 861 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 1673 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 761 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 1225 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 1417 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 67 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 67 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 67 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + .../searxng_example/ios/Runner/Info.plist | 51 + .../ios/Runner/Runner-Bridging-Header.h | 1 + .../ios/RunnerTests/RunnerTests.swift | 12 + .../example/searxng_example/lib/main.dart | 125 + .../example/searxng_example/linux/.gitignore | 1 + .../searxng_example/linux/CMakeLists.txt | 139 + .../linux/flutter/CMakeLists.txt | 88 + .../flutter/generated_plugin_registrant.cc | 15 + .../flutter/generated_plugin_registrant.h | 15 + .../linux/flutter/generated_plugins.cmake | 24 + .../example/searxng_example/linux/main.cc | 6 + .../searxng_example/linux/my_application.cc | 104 + .../searxng_example/linux/my_application.h | 18 + .../example/searxng_example/macos/.gitignore | 7 + .../macos/Flutter/Flutter-Debug.xcconfig | 2 + .../macos/Flutter/Flutter-Release.xcconfig | 2 + .../Flutter/GeneratedPluginRegistrant.swift | 14 + .../example/searxng_example/macos/Podfile | 43 + .../searxng_example/macos/Podfile.lock | 36 + .../macos/Runner.xcodeproj/project.pbxproj | 791 +++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 98 + .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../macos/Runner/AppDelegate.swift | 9 + .../AppIcon.appiconset/Contents.json | 68 + .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 102992 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 5679 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 519 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 14141 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 1065 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 36405 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 2217 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 343 +++ .../macos/Runner/Configs/AppInfo.xcconfig | 14 + .../macos/Runner/Configs/Debug.xcconfig | 2 + .../macos/Runner/Configs/Release.xcconfig | 2 + .../macos/Runner/Configs/Warnings.xcconfig | 13 + .../macos/Runner/DebugProfile.entitlements | 12 + .../searxng_example/macos/Runner/Info.plist | 32 + .../macos/Runner/MainFlutterWindow.swift | 15 + .../macos/Runner/Release.entitlements | 8 + .../macos/RunnerTests/RunnerTests.swift | 12 + .../example/searxng_example/pubspec.yaml | 65 + .../example/searxng_example/requirements.txt | 67 + .../searxng_example/test/widget_test.dart | 30 + .../searxng_example/windows/.gitignore | 17 + .../searxng_example/windows/CMakeLists.txt | 102 + .../windows/flutter/CMakeLists.txt | 109 + .../flutter/generated_plugin_registrant.cc | 14 + .../flutter/generated_plugin_registrant.h | 15 + .../windows/flutter/generated_plugins.cmake | 24 + .../windows/runner/CMakeLists.txt | 40 + .../searxng_example/windows/runner/Runner.rc | 121 + .../windows/runner/flutter_window.cpp | 71 + .../windows/runner/flutter_window.h | 33 + .../searxng_example/windows/runner/main.cpp | 43 + .../searxng_example/windows/runner/resource.h | 16 + .../windows/runner/resources/app_icon.ico | Bin 0 -> 33771 bytes .../windows/runner/runner.exe.manifest | 20 + .../searxng_example/windows/runner/utils.cpp | 65 + .../searxng_example/windows/runner/utils.h | 19 + .../windows/runner/win32_window.cpp | 288 ++ .../windows/runner/win32_window.h | 102 + 142 files changed, 8603 insertions(+) create mode 100644 src/serious_python/example/searxng_example/.gitignore create mode 100644 src/serious_python/example/searxng_example/README.md create mode 100644 src/serious_python/example/searxng_example/analysis_options.yaml create mode 100644 src/serious_python/example/searxng_example/android/.gitignore create mode 100644 src/serious_python/example/searxng_example/android/app/build.gradle create mode 100644 src/serious_python/example/searxng_example/android/app/src/debug/AndroidManifest.xml create mode 100644 src/serious_python/example/searxng_example/android/app/src/main/AndroidManifest.xml create mode 100644 src/serious_python/example/searxng_example/android/app/src/main/kotlin/com/example/flask_example/MainActivity.kt create mode 100644 src/serious_python/example/searxng_example/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 src/serious_python/example/searxng_example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 src/serious_python/example/searxng_example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 src/serious_python/example/searxng_example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 src/serious_python/example/searxng_example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 src/serious_python/example/searxng_example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 src/serious_python/example/searxng_example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 src/serious_python/example/searxng_example/android/app/src/main/res/values-night/styles.xml create mode 100644 src/serious_python/example/searxng_example/android/app/src/main/res/values/styles.xml create mode 100644 src/serious_python/example/searxng_example/android/app/src/profile/AndroidManifest.xml create mode 100644 src/serious_python/example/searxng_example/android/build.gradle create mode 100644 src/serious_python/example/searxng_example/android/gradle.properties create mode 100644 src/serious_python/example/searxng_example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 src/serious_python/example/searxng_example/android/settings.gradle create mode 100644 src/serious_python/example/searxng_example/app/requirements.txt create mode 100644 src/serious_python/example/searxng_example/app/src/common/__init__.py create mode 100644 src/serious_python/example/searxng_example/app/src/common/config.py create mode 100644 src/serious_python/example/searxng_example/app/src/main.py create mode 100644 src/serious_python/example/searxng_example/app/src/mcp/__init__.py create mode 100644 src/serious_python/example/searxng_example/app/src/mcp/py.typed create mode 100644 src/serious_python/example/searxng_example/app/src/mcp/server.py create mode 100644 src/serious_python/example/searxng_example/app/src/runner/__init__.py create mode 100644 src/serious_python/example/searxng_example/app/src/runner/py.typed create mode 100644 src/serious_python/example/searxng_example/app/src/runner/settings/settings_template.yml create mode 100644 src/serious_python/example/searxng_example/app/src/runner/simplexng.py create mode 100644 src/serious_python/example/searxng_example/app/src/shared/__init__.py create mode 100644 src/serious_python/example/searxng_example/app/src/shared/py.typed create mode 100644 src/serious_python/example/searxng_example/app/src/shared/types.py create mode 100644 src/serious_python/example/searxng_example/app/src/tavily/__init__.py create mode 100644 src/serious_python/example/searxng_example/app/src/tavily/adapter.py create mode 100644 src/serious_python/example/searxng_example/app/src/tavily/py.typed.py create mode 100644 src/serious_python/example/searxng_example/app/src/tavily/settings/tavily_defaults.yml create mode 100644 src/serious_python/example/searxng_example/ios/.gitignore create mode 100644 src/serious_python/example/searxng_example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 src/serious_python/example/searxng_example/ios/Flutter/Debug.xcconfig create mode 100644 src/serious_python/example/searxng_example/ios/Flutter/Release.xcconfig create mode 100644 src/serious_python/example/searxng_example/ios/Podfile create mode 100644 src/serious_python/example/searxng_example/ios/Podfile.lock create mode 100644 src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 src/serious_python/example/searxng_example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 src/serious_python/example/searxng_example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 src/serious_python/example/searxng_example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 src/serious_python/example/searxng_example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 src/serious_python/example/searxng_example/ios/Runner/AppDelegate.swift create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Info.plist create mode 100644 src/serious_python/example/searxng_example/ios/Runner/Runner-Bridging-Header.h create mode 100644 src/serious_python/example/searxng_example/ios/RunnerTests/RunnerTests.swift create mode 100644 src/serious_python/example/searxng_example/lib/main.dart create mode 100644 src/serious_python/example/searxng_example/linux/.gitignore create mode 100644 src/serious_python/example/searxng_example/linux/CMakeLists.txt create mode 100644 src/serious_python/example/searxng_example/linux/flutter/CMakeLists.txt create mode 100644 src/serious_python/example/searxng_example/linux/flutter/generated_plugin_registrant.cc create mode 100644 src/serious_python/example/searxng_example/linux/flutter/generated_plugin_registrant.h create mode 100644 src/serious_python/example/searxng_example/linux/flutter/generated_plugins.cmake create mode 100644 src/serious_python/example/searxng_example/linux/main.cc create mode 100644 src/serious_python/example/searxng_example/linux/my_application.cc create mode 100644 src/serious_python/example/searxng_example/linux/my_application.h create mode 100644 src/serious_python/example/searxng_example/macos/.gitignore create mode 100644 src/serious_python/example/searxng_example/macos/Flutter/Flutter-Debug.xcconfig create mode 100644 src/serious_python/example/searxng_example/macos/Flutter/Flutter-Release.xcconfig create mode 100644 src/serious_python/example/searxng_example/macos/Flutter/GeneratedPluginRegistrant.swift create mode 100644 src/serious_python/example/searxng_example/macos/Podfile create mode 100644 src/serious_python/example/searxng_example/macos/Podfile.lock create mode 100644 src/serious_python/example/searxng_example/macos/Runner.xcodeproj/project.pbxproj create mode 100644 src/serious_python/example/searxng_example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 src/serious_python/example/searxng_example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 src/serious_python/example/searxng_example/macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 src/serious_python/example/searxng_example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 src/serious_python/example/searxng_example/macos/Runner/AppDelegate.swift create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Base.lproj/MainMenu.xib create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Configs/AppInfo.xcconfig create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Configs/Debug.xcconfig create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Configs/Release.xcconfig create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Configs/Warnings.xcconfig create mode 100644 src/serious_python/example/searxng_example/macos/Runner/DebugProfile.entitlements create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Info.plist create mode 100644 src/serious_python/example/searxng_example/macos/Runner/MainFlutterWindow.swift create mode 100644 src/serious_python/example/searxng_example/macos/Runner/Release.entitlements create mode 100644 src/serious_python/example/searxng_example/macos/RunnerTests/RunnerTests.swift create mode 100644 src/serious_python/example/searxng_example/pubspec.yaml create mode 100644 src/serious_python/example/searxng_example/requirements.txt create mode 100644 src/serious_python/example/searxng_example/test/widget_test.dart create mode 100644 src/serious_python/example/searxng_example/windows/.gitignore create mode 100644 src/serious_python/example/searxng_example/windows/CMakeLists.txt create mode 100644 src/serious_python/example/searxng_example/windows/flutter/CMakeLists.txt create mode 100644 src/serious_python/example/searxng_example/windows/flutter/generated_plugin_registrant.cc create mode 100644 src/serious_python/example/searxng_example/windows/flutter/generated_plugin_registrant.h create mode 100644 src/serious_python/example/searxng_example/windows/flutter/generated_plugins.cmake create mode 100644 src/serious_python/example/searxng_example/windows/runner/CMakeLists.txt create mode 100644 src/serious_python/example/searxng_example/windows/runner/Runner.rc create mode 100644 src/serious_python/example/searxng_example/windows/runner/flutter_window.cpp create mode 100644 src/serious_python/example/searxng_example/windows/runner/flutter_window.h create mode 100644 src/serious_python/example/searxng_example/windows/runner/main.cpp create mode 100644 src/serious_python/example/searxng_example/windows/runner/resource.h create mode 100644 src/serious_python/example/searxng_example/windows/runner/resources/app_icon.ico create mode 100644 src/serious_python/example/searxng_example/windows/runner/runner.exe.manifest create mode 100644 src/serious_python/example/searxng_example/windows/runner/utils.cpp create mode 100644 src/serious_python/example/searxng_example/windows/runner/utils.h create mode 100644 src/serious_python/example/searxng_example/windows/runner/win32_window.cpp create mode 100644 src/serious_python/example/searxng_example/windows/runner/win32_window.h diff --git a/src/serious_python/example/searxng_example/.gitignore b/src/serious_python/example/searxng_example/.gitignore new file mode 100644 index 00000000..3efbe6a0 --- /dev/null +++ b/src/serious_python/example/searxng_example/.gitignore @@ -0,0 +1,46 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release + +/app/app.zip \ No newline at end of file diff --git a/src/serious_python/example/searxng_example/README.md b/src/serious_python/example/searxng_example/README.md new file mode 100644 index 00000000..1096120a --- /dev/null +++ b/src/serious_python/example/searxng_example/README.md @@ -0,0 +1,47 @@ +# searxng_example + +Before running the app run the following command to package Python app to an asset. + +For Android: + +``` +export SERIOUS_PYTHON_SITE_PACKAGES=$(pwd)/build/site-packages +dart run serious_python:main package app/src -p Android --requirements -r,app/src/requirements.txt +``` + +For iOS: + +``` +export SERIOUS_PYTHON_SITE_PACKAGES=$(pwd)/build/site-packages +dart run serious_python:main package app/src -p iOS --requirements -r,app/src/requirements.txt +``` + +For macOS: + +``` +dart run serious_python:main package app/src -p Darwin --requirements -r,app/src/requirements.txt +``` + +For Windows: + +``` +dart run serious_python:main package app/src -p Windows --requirements -r,app/src/requirements.txt +``` + +For Linux: + +``` +dart run serious_python:main package app/src -p Linux --requirements -r,app/src/requirements.txt +``` + +Important: to make `serious_python` work in your own Android app: + +If you build an App Bundle Edit `android/gradle.properties` and add the flag: + +``` +android.bundle.enableUncompressedNativeLibs=false +``` + +If you build an APK Make sure `android/app/src/AndroidManifest.xml` has `android:extractNativeLibs="true"` in the `` tag. + +For more information, see the [public issue](https://issuetracker.google.com/issues/147096055). \ No newline at end of file diff --git a/src/serious_python/example/searxng_example/analysis_options.yaml b/src/serious_python/example/searxng_example/analysis_options.yaml new file mode 100644 index 00000000..61b6c4de --- /dev/null +++ b/src/serious_python/example/searxng_example/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/src/serious_python/example/searxng_example/android/.gitignore b/src/serious_python/example/searxng_example/android/.gitignore new file mode 100644 index 00000000..6f568019 --- /dev/null +++ b/src/serious_python/example/searxng_example/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/src/serious_python/example/searxng_example/android/app/build.gradle b/src/serious_python/example/searxng_example/android/app/build.gradle new file mode 100644 index 00000000..7e39ac4f --- /dev/null +++ b/src/serious_python/example/searxng_example/android/app/build.gradle @@ -0,0 +1,72 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + namespace "com.example.searxng_example" + compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.searxng_example" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/src/serious_python/example/searxng_example/android/app/src/debug/AndroidManifest.xml b/src/serious_python/example/searxng_example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..399f6981 --- /dev/null +++ b/src/serious_python/example/searxng_example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/src/serious_python/example/searxng_example/android/app/src/main/AndroidManifest.xml b/src/serious_python/example/searxng_example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..3124b993 --- /dev/null +++ b/src/serious_python/example/searxng_example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + diff --git a/src/serious_python/example/searxng_example/android/app/src/main/kotlin/com/example/flask_example/MainActivity.kt b/src/serious_python/example/searxng_example/android/app/src/main/kotlin/com/example/flask_example/MainActivity.kt new file mode 100644 index 00000000..7d4bd743 --- /dev/null +++ b/src/serious_python/example/searxng_example/android/app/src/main/kotlin/com/example/flask_example/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.searxng_example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/src/serious_python/example/searxng_example/android/app/src/main/res/drawable-v21/launch_background.xml b/src/serious_python/example/searxng_example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 00000000..f74085f3 --- /dev/null +++ b/src/serious_python/example/searxng_example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/src/serious_python/example/searxng_example/android/app/src/main/res/drawable/launch_background.xml b/src/serious_python/example/searxng_example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 00000000..304732f8 --- /dev/null +++ b/src/serious_python/example/searxng_example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/src/serious_python/example/searxng_example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/src/serious_python/example/searxng_example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..a0e306dba073640b5f5408189588e46e7586f44c GIT binary patch literal 543 zcmeAS@N?&q;$mQ6;Pv!y2?Ej{Ak4uGB$JGtOM#SRiEBhjaDG}zd16s2gJVj5QmTSy zZen_BP-1fr3E97&a3q zB2l&!qQG|DV+Ny028$F%ZEr?{U`D$PjD9_gffE^nCNTz0 zW(=Of7&@IXbOvJ>5CIJbna^aM&g4+QMnD(8u-mi5Bt(&|xZ@%@sBNk%nt_5+E z&U1QAlyT>>sMB2Zd5T5*R3&Sld5=98o%0qdm+@@-JjKB8(xcUiGOB?O=e)LCdt!o~ zwXBiQlFwyn4J literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/src/serious_python/example/searxng_example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..9536e122de304225a47068eb7223d76d666ffff3 GIT binary patch literal 441 zcmeAS@N?&q;$mQ6;Pv!y2?EjvAk4uGBopp%ZUs`3C9V-A!TD(=<%vb942~)JNvR5+ zxryniL8*x;m4zo$ZGeip0(?STfiz?I?2w~BG`D>Nl0Y_u0T%%>AmZ%d{SXF=a}iKY z;1Q5GgH1N0Qz@fw7o%S{W5`s-kZFve(;35NGKS4!3Gp{-5j2|t=z$tr?2e1 zx|<{M`=1Yfvn$S7zyFh8TkauU@pWH(C1>qj#=iApHvX*F>$zT5Z{Kw7wA0T;2OjON z7k#nuLZxEVlhB3Vi%#w5R{pQ^jOYHGzyeuwiTP#h-KPy@XNo-6x!L4cXmw;Y?}zT1 x{SoUJZ@BL3ek9Tm?<0I*V^a>QWZRN z6Vp?JQWH}u3s0un02O@;@Ck7R(jiBGXm0z)=+VF!J{!mYa)AiQ29msy{SYot-2LEp zs8sM2psZNVG>BpbU4I6>AO`&q27?d=yF5lsH%2WlMzc6Z^CU)#6h`YzM*9LrhayJD z5=Pf*Mz>l<_c})RdPa|WM$cwOuNFq1c1E8LMqeQ6Wc2G|^zUN~=w}R?$QU%4F&K!Z zFosNJ44uvxHiI#2CS%wv#&95-&14+GWR=QfpU31}#^hej>{-X`)yVAKB$m-Ho;^jP zXr5%na;e&NQjMFXo3}}~?vQTVCEIlX=wO%qAYT-2Si1n|bFq>jzhDLd1p^=mNJuCs zXqZ2L{`vPHu$v`Skb!~G-_yl0B;(%Oo7epgI|#HsbkJD%J*z68(I=_t@zP|WtOtMN z*-pDmyMC`TC7X@Y;(68A`dP1aMK;{uwQr_>5%Y`1{dT{QiU0S1IUj!V%ko$9m)#%N z?Z5q=Wy2S14xiefgxA7M$@eujeB)&*wpY#g8`xIobm5osTK=|uYAU~Uy-r-|=Ui#0 znDWNGX<@#I(f8X;8}kKbP0l+XkKQY07&oz56KgE0((*E*<4;l zTz(bYfwkNrjoe`^+~Muqk)7O8UEEPUJkdQW3vQ|`ys5hAj_Q(os!JcJEq|!C;<4Jw zCu%F7s;zpawi<|@tAo%BU?^FFLuvNW38uhc`{#Stdr>a;n4M{0_YQ%j4>fdjtQ8yjqIWC;EEKi|V} zQcLmsyT&o!?D$^)-Iq2m(oWuq?OLJ7T4uS52aW7R5&w+O9~CRInfLn1Pt}SCmeu^S zN1iBl->`8JT->gb^i{y+j9j?j?&Gd14+=#(D`Z@pwP*FtX}kSN9UeTe}s2d&2ha~ z`LByZPJQC^d0ib(Hi}oi*6i$%vz~ZeE;p(_PUYpr&JyqSsa%;&m2^IBU|E~S7uo3B0TcuEV z@!9O(%!~cgl`j5x9lH9TqGF(8{pRwFlA5ftg)CmFq0UT;ocna?`et7v7+$uqOKaY3+r+0Li&wnaX`ZM#{f0~HpS$Xw zt{vW2{^h7Hp5nPEY*D-am1PP|97-KPV$o+6r{^n`=Y8Q#n7RMjb6~1s@O1TaS?83{ F1OV%ms*C^t literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/src/serious_python/example/searxng_example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..6c3f49b9f8d8f2bdd5f8f782295e99e78987f9d5 GIT binary patch literal 1442 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`Y^-l~``*vJ_m|JT=W~+Fb|;t; z5JCo?9}+4@ zL6#n9CmZeLAZsq7@DRlpQTd4Khin9B7ft}$9fbCTqP-$yCqlF+M2`gvXRvSqD^J)J z0Jgzk8v?cmVUG~@iopIb*oVQs2ylo5ha*6X0(vy;kA?kl;D{3sjtRiPNd#sRI3PM;iLoWdvMPHcR6@uf=3p3D!?-v4&da#ffL}B175g(dX9GFVSs z8=B}}%m0dJlq+^+HdGy=1~%JW6W`4=G~{L1gdrXsPAAKc(+&&q&?tQWblUDy?i0vY5l# z_^L@M|F`!v+J(j4#)ZW?8qt29v~Brxv2Ki#IJNycfvy{~N}L@xl8v@gmAZP8?63A6 z%ISJz*~=#s<=c9q?4QaY^N9dUT|c9P*-aH{ni;Lk2h?CqhrEXQlp3I1yDZCU5!RVg zmn2!aBPw%FMm@7fD^S|WuP~ozLzM1aeVaeB_2`Qo`Zwp2iMpv_QsVS5Q8yh)N}SH$Wmda#nBdDBkFpVNQ2ZT4Ndg+bROd2Ti-e#4lek~*~Tu;7Dn z;F448?VOnIqOl3pRE}YY{v8JG{Pf61JlG$ne=ngzfO-^7oS^K%yhjprS3xZbzE#WG zN>sOMX7ao08IJS~>IO|;ZC&Ax=I%#Gpl4?G$67^knK*2Xjn$k^Jvc-xygz#X+P)=X zvXxA}e0e#9qaA2K7JAyruVd|xZFxp|@P&w{dp8*>oGI@W*>CI=d(Ri78r|+_9rtkY zs%qU%7m=8EG_w;E3$IN%YaBZ7uHto~QN5-e6!kKP!xOde|kK?X4KPwMK4b{_VD; z!icQDg@TT&^Xld_c|gAryEafa(ses&;^N20)j5e|m7-04?}|a3i*rOj;rFFkpAB1R zL3$22SRE6}uVFH1h giTxLrW9w_L%V%nSH4N-R_)kK}(~a$V)mfzY7t$Yc&;S4c literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/android/app/src/main/res/values-night/styles.xml b/src/serious_python/example/searxng_example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 00000000..06952be7 --- /dev/null +++ b/src/serious_python/example/searxng_example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/src/serious_python/example/searxng_example/android/app/src/main/res/values/styles.xml b/src/serious_python/example/searxng_example/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..cb1ef880 --- /dev/null +++ b/src/serious_python/example/searxng_example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/src/serious_python/example/searxng_example/android/app/src/profile/AndroidManifest.xml b/src/serious_python/example/searxng_example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..399f6981 --- /dev/null +++ b/src/serious_python/example/searxng_example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/src/serious_python/example/searxng_example/android/build.gradle b/src/serious_python/example/searxng_example/android/build.gradle new file mode 100644 index 00000000..f7eb7f63 --- /dev/null +++ b/src/serious_python/example/searxng_example/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.7.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/src/serious_python/example/searxng_example/android/gradle.properties b/src/serious_python/example/searxng_example/android/gradle.properties new file mode 100644 index 00000000..4efbcd2b --- /dev/null +++ b/src/serious_python/example/searxng_example/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true +android.bundle.enableUncompressedNativeLibs=false \ No newline at end of file diff --git a/src/serious_python/example/searxng_example/android/gradle/wrapper/gradle-wrapper.properties b/src/serious_python/example/searxng_example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..3c472b99 --- /dev/null +++ b/src/serious_python/example/searxng_example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/src/serious_python/example/searxng_example/android/settings.gradle b/src/serious_python/example/searxng_example/android/settings.gradle new file mode 100644 index 00000000..44e62bcf --- /dev/null +++ b/src/serious_python/example/searxng_example/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/src/serious_python/example/searxng_example/app/requirements.txt b/src/serious_python/example/searxng_example/app/requirements.txt new file mode 100644 index 00000000..f7140ff4 --- /dev/null +++ b/src/serious_python/example/searxng_example/app/requirements.txt @@ -0,0 +1,67 @@ +aiohappyeyeballs==2.6.1 +aiohttp==3.13.2 +aiosignal==1.4.0 +annotated-types==0.7.0 +anyio==4.11.0 +async-timeout==5.0.1 +attrs==25.4.0 +babel==2.17.0 +beautifulsoup4==4.14.2 +blinker==1.9.0 +certifi==2025.11.12 +click==8.3.0 +colorama==0.4.6 +fasttext-predict==0.9.2.4 +Flask[async]==3.1.2 +flask-babel==4.0.0 +frozenlist==1.8.0 +h11==0.16.0 +h2==4.3.0 +hpack==4.1.0 +httpcore==1.0.9 +httptools==0.7.1 +httpx[http2]==0.28.1 +httpx-socks[asyncio]==0.10.1 +hyperframe==6.1.0 +idna==3.11 +isodate==0.7.2 +itsdangerous==2.2.0 +Jinja2==3.1.6 +lxml==6.0.2 +markdown-it-py==4.0.0 +MarkupSafe==3.0.3 +mcp-utils==1.0.0 +mdurl==0.1.2 +msgspec==0.20.0 +multidict==6.7.0 +platformdirs==4.5.0 +propcache==0.4.1 +pydantic==2.12.4 +pydantic_core==2.41.5 +Pygments==2.19.2 +python-dateutil==2.9.0.post0 +python-dotenv==1.2.1 +python-socks==2.7.2 +pytz==2025.2 +PyYAML==6.0.3 +queuelib==1.8.0 +requests==2.32.5 +rich==14.2.0 +searxng @ file:pypackages/searxng-2025.11.27+c3799ba9e-py3-none-any.whl +shellingham==1.5.4 +six==1.17.0 +sniffio==1.3.1 +soupsieve==2.8 +strif==3.0.1 +typer==0.20.0 +typer-slim==0.20.0 +typing-inspection==0.4.2 +typing_extensions==4.15.0 +uvicorn==0.38.0 +valkey==6.1.1 +waitress==3.0.2 +watchfiles==1.1.1 +websockets==15.0.1 +Werkzeug==3.1.3 +whitenoise==6.11.0 +yarl==1.22.0 diff --git a/src/serious_python/example/searxng_example/app/src/common/__init__.py b/src/serious_python/example/searxng_example/app/src/common/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/serious_python/example/searxng_example/app/src/common/config.py b/src/serious_python/example/searxng_example/app/src/common/config.py new file mode 100644 index 00000000..2f1c89f6 --- /dev/null +++ b/src/serious_python/example/searxng_example/app/src/common/config.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +""" +Configuration module - responsible for loading configurations from environment variables + +This module loads configuration from environment variables and provides +default values when environment variables are not set. +""" + +import os +import sys +from typing import Optional, Dict, Any + +import logging + +# SearXNG Configuration +SEARXNG_HOST = os.getenv("SEARXNG_HOST", "127.0.0.1") +SEARXNG_PORT = int(os.getenv("SEARXNG_PORT", "8888")) + +TAVILY_TIMEOUT = os.environ.get('TAVILY_TIMEOUT', "10") +TAVILY_CONTENT_LENGTH = os.environ.get('TAVILY_CONTENT_LENGTH', "2500") +TAVILY_MAX_RESULTS = os.environ.get('TAVILY_MAX_RESULTS', "10") +TAVILY_USER_AGENT = os.environ.get('TAVILY_USER_AGENT',"Mozilla/5.0 (compatible; TavilyBot/1.0)") + + +# Default log format +DEFAULT_LOG_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' + +def setup_logger(level: str = "INFO", log_format: Optional[str] = None) -> logging.Logger: + """ + Configure and return the application logger. + + Args: + level: Log level, optional values:DEBUG, INFO, WARNING, ERROR, CRITICAL + log_format: Log format; if None, the default format will be used. + + Returns: + logging.Logger: Configured logger + """ + # Set log level + numeric_level = getattr(logging, level.upper(), logging.INFO) + logger.setLevel(numeric_level) + + # If there is no processor, add a console processor. + if not logger.handlers: + handler = logging.StreamHandler(sys.stdout) + formatter = logging.Formatter(log_format or DEFAULT_LOG_FORMAT) + handler.setFormatter(formatter) + logger.addHandler(handler) + + return logger + +# Function to export configuration information +def get_config_info() -> Dict[str,Any]: + """ + Returns a dictionary of the current configuration information. + + Returns: + dict: A dictionary containing all configuration parameters + """ + return { + "searxng": { + "host": os.getenv("SEARXNG_HOST", SEARXNG_HOST), + "port": os.getenv("SEARXNG_PORT", str(SEARXNG_PORT)), + }, + "crawler": { + "max_results": int(os.getenv("TAVILY_MAX_RESULTS", TAVILY_MAX_RESULTS)), + "content_length": int(os.getenv("TAVILY_CONTENT_LENGTH", TAVILY_CONTENT_LENGTH)), + "timeout": int(os.getenv("TAVILY_TIMEOUT", TAVILY_TIMEOUT)), + "user_agent": str(os.getenv("TAVILY_USER_AGENT", TAVILY_USER_AGENT)), + }, + } + +logger = logging.getLogger(__name__) diff --git a/src/serious_python/example/searxng_example/app/src/main.py b/src/serious_python/example/searxng_example/app/src/main.py new file mode 100644 index 00000000..154ec6b0 --- /dev/null +++ b/src/serious_python/example/searxng_example/app/src/main.py @@ -0,0 +1,11 @@ +from common.config import setup_logger +from tavily.adapter import TavilyAdapterConfig, TavilyAdapter +from runner.simplexng import SearXNGServerConfig, SimpleXNGServer + +# Default settings for the logger +sxng_config=SearXNGServerConfig() +setup_logger(level='ERROR') + +server = SimpleXNGServer(server_config=sxng_config) +TavilyAdapter.configure_tavily_adapter(tavily_config=TavilyAdapterConfig(settings=None)) +server.start_server() diff --git a/src/serious_python/example/searxng_example/app/src/mcp/__init__.py b/src/serious_python/example/searxng_example/app/src/mcp/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/serious_python/example/searxng_example/app/src/mcp/py.typed b/src/serious_python/example/searxng_example/app/src/mcp/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/src/serious_python/example/searxng_example/app/src/mcp/server.py b/src/serious_python/example/searxng_example/app/src/mcp/server.py new file mode 100644 index 00000000..f650f56d --- /dev/null +++ b/src/serious_python/example/searxng_example/app/src/mcp/server.py @@ -0,0 +1,141 @@ +import asyncio +import json +import typing as t +import httpx + +from flask import Flask, Response +from flask.typing import RouteCallable +from mcp_utils.core import MCPServer +from mcp_utils.schema import TextContent, CallToolResult +from pydantic import Field +from searx.extended_types import sxng_request + +from shared.types import SearxCategory, SearxTimeRange, InMemoryFlipFlopQueue +from tavily.adapter import adapter_after_request, adapter_before_request + +# Create a basic MCP server +mcp: MCPServer = MCPServer(name='mcp-server', version='1.0', response_queue=InMemoryFlipFlopQueue()) + +class SearxngMcpAdapter: + __instance = None + __endpoint: RouteCallable | None = None + + @staticmethod + def get_mcp_adapter(): + if not SearxngMcpAdapter.__instance : + SearxngMcpAdapter.__instance = SearxngMcpAdapter() + return SearxngMcpAdapter.__instance + + + @staticmethod + def search() -> Response: + if not SearxngMcpAdapter.__endpoint: + from searx.webapp import search + SearxngMcpAdapter.__endpoint = search + return SearxngMcpAdapter.__endpoint() + + +@mcp.tool(name="web_search") +def web_search( + query: str = Field(description="Search query", default=None), + language: str = Field( + description="Language code for search results (e.g., 'auto','en', 'de', 'fr'). Default: 'en'", + default="auto", + ), + time_range: t.Literal['day', 'week', 'month', 'year','all'] | str | None = Field( + description="Time range for search results. Options: 'day', 'week', 'month', 'year', 'all'. Default: all (no time restriction).", + default='all' + ), + categories: t.List[t.Literal['general','news','images','music','videos','files','weather','social media','map','science','books','movies','web','scientific publications','dictionaries','software wikis','code' ]] | t.List[str] | None = Field( + description = "Categories to search in (e.g., 'general', 'images', 'news').", + default_factory=list + ), + engines: t.Optional[t.List[str]] = Field( + description="Specific search engines to use (e.g., 'google', 'yahoo', 'wikipedia', 'brave').", + default_factory=list + ), + safe_search: t.Literal[0, 1, 2] = Field( + description="Safe-Search filter (0:normal, 1:moderate, 2:strict). Default: 1 (moderate).", + default=1, + ), + page_no: int = Field( + description="Page number for results. Must be minimum 1. Default: 1.", + default=1, + ge=1, + ), + max_results: t.Optional[int] = Field( + description="Maximum number of search results to return. Range: 1-50. Default: 10.", + default=5, + ge=1, + le=50, + ), + scrape_content: t.Optional[t.Literal[0, 1]] = Field( + description="Whether or not to crawl and scrape contents of url results (0:no, 1:yes). Default: 0 (no).", + default=0 + ), + include_raw_content: t.Literal[0, 1] = Field( + description="Include the cleaned and parsed HTML content of each search result. (0:no, 1:yes). Default: 0 (no).", + default=0 + ), + content_length: t.Optional[int] = Field( + description="Maximum content length of search results. Range: 100-5000. Default: 2500.", + default=2500, + ge=100, + le=5000, + ), + ) -> CallToolResult: + """Perform web searches using SearXNG, a privacy-respecting metasearch engine, returning relevant web content with customizable parameters. + Returns a Dictionary response with status, message, data (search results), and error if any.""" + params = { + 'q': query, + 'format': 'json', + 'language': language, + 'pageno': str(page_no), + 'engines': ",".join(engines) if engines and len(engines) > 0 else "wikipedia,duckduckgo,google,brave,yahoo", + 'safesearch': str(safe_search), + 'scrape_content': str(scrape_content) if scrape_content else '0', + 'include_raw_content': str(include_raw_content) if include_raw_content else '0', + 'max_results': str(max_results) if max_results else '10', + 'content_length': str(content_length) if content_length else '2500' + } + if categories and len(categories) > 0: + sxng_categories = [ str(v) for v in categories if str(v) in SearxCategory.__members__ ] + params['categories'] = ",".join(sxng_categories) if len(sxng_categories) > 0 else "general,web" + + if time_range and (str(time_range) in SearxTimeRange.__members__ ): + params['time_range'] = str(time_range) # time_range if time_range else 'None', + + sxng_request.form.update(params) + adapter_before_request() + + response = SearxngMcpAdapter.search() + try: + loop = asyncio.get_running_loop() + except Exception: + asyncio.set_event_loop(asyncio.new_event_loop()) + loop = asyncio.get_event_loop() + + try: + response = loop.run_until_complete(adapter_after_request(response=response)) + finally: + loop.close() + + search_response: t.Dict[str, t.Any] = response.json + + contents = [TextContent(text=r["text"] if scrape_content == 1 and len(r.get("text","")) > 0 else r["content"], type="text") for r in search_response.get("results", []) if r and len(r) > 0] + + answer = contents[0] if len(contents) > 0 else TextContent(text="", type="text") + + result = CallToolResult(content=[answer], isError=False) + return result + +# @mcp.tool(name="get_weather") +# def get_weather_forecast( +# latitude: float = Field( +# description="Latitude of the location" +# ), +# longitude: float = Field( +# description="Longitude of the location" +# ), +# ) -> CallToolResult: +# """Get weather forecast for a location.""" diff --git a/src/serious_python/example/searxng_example/app/src/runner/__init__.py b/src/serious_python/example/searxng_example/app/src/runner/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/serious_python/example/searxng_example/app/src/runner/__init__.py @@ -0,0 +1 @@ + diff --git a/src/serious_python/example/searxng_example/app/src/runner/py.typed b/src/serious_python/example/searxng_example/app/src/runner/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/src/serious_python/example/searxng_example/app/src/runner/settings/settings_template.yml b/src/serious_python/example/searxng_example/app/src/runner/settings/settings_template.yml new file mode 100644 index 00000000..6367daf4 --- /dev/null +++ b/src/serious_python/example/searxng_example/app/src/runner/settings/settings_template.yml @@ -0,0 +1,2695 @@ +# SimpleXNG Settings Template +# Based on utils/templates/etc/searxng/settings.yml + +use_default_settings: true + +general: + debug: false + instance_name: "SimpleXNG" + privacypolicy_url: false + donation_url: false + contact_url: false + enable_metrics: false + +search: + safe_search: 0 + autocomplete: "" + autocomplete_min: 4 + favicon_resolver: "" + default_lang: "auto" + suspended_times: + SearxEngineAccessDenied: 0 + formats: + - html + - json + +server: + # Will be overridden by CLI arguments + port: 11888 + bind_address: "127.0.0.1" + secret_key: "local-searxng-key-change-for-production" + limiter: false + base_url: false + public_instance: false + image_proxy: false + http_protocol_version: "1.1" + method: "POST" + default_http_headers: + X-Content-Type-Options: nosniff + X-Download-Options: noopen + X-Robots-Tag: noindex, nofollow + Referrer-Policy: no-referrer + X-Forwarded-For: "127.0.0.1" + X-Real-IP: "127.0.0.1" + +valkey: + url: false + +redis: + # Disable Redis for local use + url: false + +ui: + static_use_hash: false + static_path: "" + templates_path: "" + query_in_title: false + infinite_scroll: false + default_theme: simple + center_alignment: false + default_locale: "" + theme_args: + simple_style: auto + search_on_category_select: false + +outgoing: + request_timeout: 3.0 + useragent_suffix: "" + pool_connections: 100 + pool_maxsize: 10 + enable_http2: true + +plugins: + searx.plugins.calculator.SXNGPlugin: + active: true + + searx.plugins.hash_plugin.SXNGPlugin: + active: true + + searx.plugins.self_info.SXNGPlugin: + active: true + + searx.plugins.unit_converter.SXNGPlugin: + active: true + + searx.plugins.ahmia_filter.SXNGPlugin: + active: false + + searx.plugins.hostnames.SXNGPlugin: + active: true + + searx.plugins.time_zone.SXNGPlugin: + active: true + + searx.plugins.oa_doi_rewrite.SXNGPlugin: + active: false + + searx.plugins.tor_check.SXNGPlugin: + active: false + + searx.plugins.tracker_url_remover.SXNGPlugin: + active: true + +categories_as_tabs: + general: + news: + science: + social media: + +engines: + - name: 360search + engine: 360search + shortcut: 360so + disabled: true + + - name: 360search videos + engine: 360search_videos + shortcut: 360sov + disabled: true + + - name: 9gag + engine: 9gag + shortcut: 9g + disabled: true + + - name: acfun + engine: acfun + shortcut: acf + disabled: true + + - name: adobe stock + engine: adobe_stock + shortcut: asi + categories: ["images"] + # https://docs.searxng.org/dev/engines/online/adobe_stock.html + adobe_order: relevance + adobe_content_types: ["photo", "illustration", "zip_vector", "template", "3d", "image"] + timeout: 6 + disabled: true + + - name: adobe stock video + engine: adobe_stock + shortcut: asv + network: adobe stock + categories: ["videos"] + adobe_order: relevance + adobe_content_types: ["video"] + timeout: 6 + disabled: true + + - name: adobe stock audio + engine: adobe_stock + shortcut: asa + network: adobe stock + categories: ["music"] + adobe_order: relevance + adobe_content_types: ["audio"] + timeout: 6 + disabled: true + + - name: alexandria + engine: json_engine + shortcut: alx + categories: general + paging: true + search_url: https://api.alexandria.org/?a=1&q={query}&p={pageno} + results_query: results + title_query: title + url_query: url + content_query: snippet + timeout: 1.5 + disabled: true + about: + website: https://alexandria.org/ + official_api_documentation: https://github.com/alexandria-org/alexandria-api/raw/master/README.md + use_official_api: true + require_api_key: false + results: JSON + + - name: astrophysics data system + engine: astrophysics_data_system + shortcut: ads + # read https://docs.searxng.org/dev/engines/online/astrophysics_data_system.html + api_key: "" + inactive: true + + - name: alpine linux packages + engine: alpinelinux + disabled: true + shortcut: alp + + - name: annas archive + engine: annas_archive + shortcut: aa + timeout: 5 + categories: [files, books] + + - name: ansa + engine: ansa + shortcut: ans + disabled: true + + # - name: annas articles + # engine: annas_archive + # shortcut: aaa + # # https://docs.searxng.org/dev/engines/online/annas_archive.html + # aa_content: 'magazine' # book_fiction, book_unknown, book_nonfiction, book_comic + # aa_ext: 'pdf' # pdf, epub, .. + # aa_sort: oldest' # newest, oldest, largest, smallest + + - name: apk mirror + engine: apkmirror + timeout: 4.0 + shortcut: apkm + disabled: true + + - name: apple app store + engine: apple_app_store + shortcut: aps + disabled: true + + # Requires Tor + - name: ahmia + engine: ahmia + categories: onions + enable_http: true + shortcut: ah + + - name: anaconda + engine: xpath + paging: true + first_page_num: 0 + search_url: https://anaconda.org/search?q={query}&page={pageno} + results_xpath: //tbody/tr + url_xpath: ./td/h5/a[last()]/@href + title_xpath: ./td/h5 + content_xpath: ./td[h5]/text() + categories: it + timeout: 6.0 + shortcut: conda + disabled: true + + - name: arch linux wiki + engine: archlinux + shortcut: al + disabled: true + + - name: nixos wiki + engine: mediawiki + shortcut: nixw + base_url: https://wiki.nixos.org/ + search_type: text + disabled: true + categories: [it, software wikis] + + - name: artic + engine: artic + shortcut: arc + timeout: 4.0 + disabled: true + + - name: arxiv + engine: arxiv + shortcut: arx + categories: [science, scientific publications] + + - name: ask + engine: ask + shortcut: ask + disabled: true + + # - name: azure + # engine: azure + # shortcut: az + # categories: [it, cloud] + # azure_tenant_id: "your_tenant_id" + # azure_client_id: "your_client_id" + # azure_client_secret: "your_client_secret" + # disabled: true + + # tmp suspended: dh key too small + # - name: base + # engine: base + # shortcut: bs + + - name: bandcamp + engine: bandcamp + shortcut: bc + categories: [music] + + - name: baidu + baidu_category: general + categories: [general] + engine: baidu + shortcut: bd + disabled: true + + - name: baidu images + baidu_category: images + categories: [images] + engine: baidu + shortcut: bdi + disabled: true + + - name: baidu kaifa + baidu_category: it + categories: [it] + engine: baidu + shortcut: bdk + disabled: true + + - name: wikipedia + engine: wikipedia + shortcut: wp + # add "list" to the array to get results in the results list + display_type: ["infobox"] + categories: [general] + disabled: false + + - name: bilibili + engine: bilibili + shortcut: bil + disabled: true + + - name: bing + engine: bing + shortcut: bi + disabled: true + categories: [general, web] + + - name: bing images + engine: bing_images + shortcut: bii + disabled: true + categories: [images, web] + + - name: bing news + engine: bing_news + shortcut: bin + disabled: true + categories: [news] + + - name: bing videos + engine: bing_videos + shortcut: biv + disabled: true + categories: [videos, web] + + - name: bitchute + engine: bitchute + shortcut: bit + disabled: true + categories: [videos] + + - name: bitbucket + engine: xpath + paging: true + search_url: https://bitbucket.org/repo/all/{pageno}?name={query} + url_xpath: //article[@class="repo-summary"]//a[@class="repo-link"]/@href + title_xpath: //article[@class="repo-summary"]//a[@class="repo-link"] + content_xpath: //article[@class="repo-summary"]/p + categories: [it, repos] + timeout: 4.0 + disabled: true + shortcut: bb + about: + website: https://bitbucket.org/ + wikidata_id: Q2493781 + official_api_documentation: https://developer.atlassian.com/bitbucket + use_official_api: false + require_api_key: false + results: HTML + + - name: bpb + engine: bpb + shortcut: bpb + disabled: true + + - name: btdigg + engine: btdigg + shortcut: bt + disabled: true + + - name: openverse + engine: openverse + categories: images + shortcut: opv + disabled: true + + - name: media.ccc.de + engine: ccc_media + shortcut: c3tv + # We don't set language: de here because media.ccc.de is not just + # for a German audience. It contains many English videos and many + # German videos have English subtitles. + disabled: true + + - name: chefkoch + engine: chefkoch + shortcut: chef + disabled: true + # to show premium or plus results too: + # skip_premium: false + + # WARNING: links from chinaso.com voilate users privacy + # Before activate these engines its mandatory to read + # - https://github.com/searxng/searxng/issues/4694 + # - https://docs.searxng.org/dev/engines/online/chinaso.html + + - name: chinaso news + engine: chinaso + shortcut: chinaso + categories: [news] + chinaso_category: news + chinaso_news_source: all + disabled: true + + - name: chinaso images + engine: chinaso + network: chinaso news + shortcut: chinasoi + categories: [images] + chinaso_category: images + disabled: true + + - name: chinaso videos + engine: chinaso + network: chinaso news + shortcut: chinasov + categories: [videos] + chinaso_category: videos + disabled: true + + - name: cloudflareai + engine: cloudflareai + shortcut: cfai + # get api token and accont id from https://developers.cloudflare.com/workers-ai/get-started/rest-api/ + cf_account_id: 'your_cf_accout_id' + cf_ai_api: 'your_cf_api' + # create your ai gateway by https://developers.cloudflare.com/ai-gateway/get-started/creating-gateway/ + cf_ai_gateway: 'your_cf_ai_gateway_name' + # find the model name from https://developers.cloudflare.com/workers-ai/models/#text-generation + cf_ai_model: 'ai_model_name' + # custom your preferences + # cf_ai_model_display_name: 'Cloudflare AI' + # cf_ai_model_assistant: 'prompts_for_assistant_role' + # cf_ai_model_system: 'prompts_for_system_role' + timeout: 30 + disabled: true + + - name: core.ac.uk + engine: core + shortcut: cor + # read https://docs.searxng.org/dev/engines/online/core.html + api_key: "" + inactive: true + + - name: crossref + engine: crossref + shortcut: cr + timeout: 30 + disabled: true + + - name: crowdview + engine: json_engine + shortcut: cv + categories: [general] + paging: false + search_url: https://crowdview-next-js.onrender.com/api/search-v3?query={query} + results_query: results + url_query: link + title_query: title + content_query: snippet + title_html_to_text: true + content_html_to_text: true + disabled: true + about: + website: https://crowdview.ai/ + + - name: yep + engine: yep + shortcut: yep + categories: general + search_type: web + timeout: 5 + disabled: true + + - name: yep images + engine: yep + shortcut: yepi + categories: images + search_type: images + disabled: true + + - name: yep news + engine: yep + shortcut: yepn + categories: news + search_type: news + disabled: true + + - name: currency + engine: currency_convert + shortcut: cc + categories: [currency] + + - name: deezer + engine: deezer + shortcut: dz + disabled: true + categories: [videos] + + - name: destatis + engine: destatis + shortcut: destat + disabled: true + + - name: deviantart + engine: deviantart + shortcut: da + timeout: 3.0 + disabled: true + + - name: ddg definitions + engine: duckduckgo_definitions + shortcut: ddd + weight: 2 + disabled: true + # tests: *tests_infobox + + # cloudflare protected + # - name: digbt + # engine: digbt + # shortcut: dbt + # timeout: 6.0 + # disabled: true + + - name: docker hub + engine: docker_hub + shortcut: dh + categories: [it, packages] + disabled: true + + - name: encyclosearch + engine: json_engine + shortcut: es + categories: [general] + paging: true + search_url: https://encyclosearch.org/encyclosphere/search?q={query}&page={pageno}&resultsPerPage=15 + results_query: Results + url_query: SourceURL + title_query: Title + content_query: Description + disabled: true + about: + website: https://encyclosearch.org + official_api_documentation: https://encyclosearch.org/docs/#/rest-api + use_official_api: true + require_api_key: false + results: JSON + + - name: erowid + engine: xpath + paging: true + first_page_num: 0 + page_size: 30 + search_url: https://www.erowid.org/search.php?q={query}&s={pageno} + url_xpath: //dl[@class="results-list"]/dt[@class="result-title"]/a/@href + title_xpath: //dl[@class="results-list"]/dt[@class="result-title"]/a/text() + content_xpath: //dl[@class="results-list"]/dd[@class="result-details"] + categories: [] + shortcut: ew + disabled: true + about: + website: https://www.erowid.org/ + wikidata_id: Q1430691 + official_api_documentation: + use_official_api: false + require_api_key: false + results: HTML + + # - name: elasticsearch + # shortcut: els + # engine: elasticsearch + # base_url: http://localhost:9200 + # username: elastic + # password: changeme + # index: my-index + # enable_http: true + # # available options: match, simple_query_string, term, terms, custom + # query_type: match + # # if query_type is set to custom, provide your query here + # # custom_query_json: {"query":{"match_all": {}}} + # # show_metadata: false + # disabled: true + + - name: wikidata + engine: wikidata + shortcut: wd + timeout: 3.0 + weight: 2 + # add "list" to the array to get results in the results list + display_type: ["infobox"] + # tests: *tests_infobox + categories: [general] + disabled: true + + - name: duckduckgo + engine: duckduckgo + shortcut: ddg + disabled: false + categories: [general, web] + + - name: duckduckgo images + engine: duckduckgo_extra + categories: [images, web] + ddg_category: images + shortcut: ddi + disabled: false + + - name: duckduckgo videos + engine: duckduckgo_extra + categories: [videos, web] + ddg_category: videos + shortcut: ddv + disabled: false + + - name: duckduckgo news + engine: duckduckgo_extra + categories: [news, web] + ddg_category: news + shortcut: ddn + disabled: false + + - name: duckduckgo weather + engine: duckduckgo_weather + shortcut: ddw + disabled: false + categories: [weather] + + - name: apple maps + engine: apple_maps + shortcut: apm + disabled: true + timeout: 5.0 + categories: [map] + + - name: emojipedia + engine: emojipedia + timeout: 4.0 + shortcut: em + disabled: true + + - name: tineye + engine: tineye + shortcut: tin + timeout: 9.0 + disabled: true + + - name: etymonline + engine: xpath + paging: true + search_url: https://etymonline.com/search?page={pageno}&q={query} + url_xpath: //a[contains(@class, "word__name--")]/@href + title_xpath: //a[contains(@class, "word__name--")] + content_xpath: //section[contains(@class, "word__defination")] + first_page_num: 1 + shortcut: et + categories: [dictionaries] + disabled: true + about: + website: https://www.etymonline.com/ + wikidata_id: Q1188617 + official_api_documentation: + use_official_api: false + require_api_key: false + results: HTML + + # - name: ebay + # engine: ebay + # shortcut: eb + # base_url: 'https://www.ebay.com' + # disabled: true + # timeout: 5 + + - name: 1x + engine: www1x + shortcut: 1x + timeout: 3.0 + disabled: true + + - name: fdroid + engine: fdroid + shortcut: fd + disabled: true + + - name: findthatmeme + engine: findthatmeme + shortcut: ftm + disabled: true + + - name: flickr + categories: images + shortcut: fl + disabled: true + # You can use the engine using the official stable API, but you need an API + # key, see: https://www.flickr.com/services/apps/create/ + # engine: flickr + # api_key: 'apikey' # required! + # Or you can use the html non-stable engine, activated by default + engine: flickr_noapi + + - name: free software directory + engine: mediawiki + shortcut: fsd + categories: [it, software wikis] + base_url: https://directory.fsf.org/ + search_type: title + timeout: 5.0 + disabled: true + about: + website: https://directory.fsf.org/ + wikidata_id: Q2470288 + + # - name: freesound + # engine: freesound + # shortcut: fnd + # disabled: true + # timeout: 15.0 + # API key required, see: https://freesound.org/docs/api/overview.html + # api_key: MyAPIkey + + - name: frinkiac + engine: frinkiac + shortcut: frk + disabled: true + + - name: fyyd + engine: fyyd + shortcut: fy + timeout: 8.0 + disabled: true + + - name: geizhals + engine: geizhals + shortcut: geiz + disabled: true + + - name: genius + engine: genius + shortcut: gen + disabled: true + + - name: gentoo + engine: mediawiki + shortcut: ge + categories: [it, software wikis] + base_url: "https://wiki.gentoo.org/" + api_path: "api.php" + search_type: text + timeout: 10 + disabled: true + + - name: gitlab + engine: gitlab + base_url: https://gitlab.com + shortcut: gl + disabled: true + categories: [it, repos] + about: + website: https://gitlab.com/ + wikidata_id: Q16639197 + + # - name: gnome + # engine: gitlab + # base_url: https://gitlab.gnome.org + # shortcut: gn + # about: + # website: https://gitlab.gnome.org + # wikidata_id: Q44316 + + - name: github + engine: github + shortcut: gh + disabled: true + categories: [it, repos] + + - name: github code + engine: github_code + shortcut: ghc + disabled: true + categories: [code] + ghc_auth: + # type is one of: + # * none + # * personal_access_token + # * bearer + # When none is passed, the token is not requried. + type: "none" + token: "token" + # specify whether to highlight the matching lines to the query + ghc_highlight_matching_lines: true + ghc_strip_new_lines: true + ghc_strip_whitespace: false + timeout: 10.0 + + - name: codeberg + # https://docs.searxng.org/dev/engines/online/gitea.html + engine: gitea + base_url: https://codeberg.org + shortcut: cb + disabled: true + + - name: gitea.com + engine: gitea + base_url: https://gitea.com + shortcut: gitea + disabled: true + + - name: goodreads + engine: goodreads + shortcut: good + timeout: 4.0 + disabled: true + + - name: google + engine: google + shortcut: go + disabled: false + categories: [general, web] + # additional_tests: + # android: *test_android + + - name: google images + engine: google_images + shortcut: goi + disabled: false + categories: [images, web] + # additional_tests: + # android: *test_android + # dali: + # matrix: + # query: ['Dali Christ'] + # lang: ['en', 'de', 'fr', 'zh-CN'] + # result_container: + # - ['one_title_contains', 'Salvador'] + + - name: google news + engine: google_news + shortcut: gon + disabled: false + categories: [news] + # additional_tests: + # android: *test_android + + - name: google videos + engine: google_videos + shortcut: gov + disabled: true + # additional_tests: + # android: *test_android + + - name: google scholar + engine: google_scholar + shortcut: gos + disabled: false + categories: [science, scientific publications] + + - name: google play apps + engine: google_play + categories: [files, apps] + shortcut: gpa + play_categ: apps + disabled: true + + - name: google play movies + engine: google_play + categories: [videos] + shortcut: gpm + play_categ: movies + disabled: true + + - name: material icons + engine: material_icons + shortcut: mi + disabled: true + + - name: habrahabr + engine: xpath + paging: true + search_url: https://habr.com/en/search/page{pageno}/?q={query} + results_xpath: //article[contains(@class, "tm-articles-list__item")] + url_xpath: .//a[@class="tm-title__link"]/@href + title_xpath: .//a[@class="tm-title__link"] + content_xpath: .//div[contains(@class, "article-formatted-body")] + categories: it + timeout: 4.0 + disabled: true + shortcut: habr + about: + website: https://habr.com/ + wikidata_id: Q4494434 + official_api_documentation: https://habr.com/en/docs/help/api/ + use_official_api: false + require_api_key: false + results: HTML + + - name: hackernews + engine: hackernews + shortcut: hn + disabled: true + + - name: hex + engine: hex + shortcut: hex + disabled: true + # Valid values: name inserted_at updated_at total_downloads recent_downloads + sort_criteria: "recent_downloads" + page_size: 10 + + - name: crates.io + engine: crates + shortcut: crates + disabled: true + timeout: 6.0 + + - name: hoogle + engine: xpath + search_url: https://hoogle.haskell.org/?hoogle={query} + results_xpath: '//div[@class="result"]' + title_xpath: './/div[@class="ans"]//a' + url_xpath: './/div[@class="ans"]//a/@href' + content_xpath: './/div[@class="from"]' + page_size: 20 + categories: [it, packages] + shortcut: ho + disabled: true + about: + website: https://hoogle.haskell.org/ + wikidata_id: Q34010 + official_api_documentation: https://hackage.haskell.org/api + use_official_api: false + require_api_key: false + results: JSON + + - name: il post + engine: il_post + shortcut: pst + disabled: true + + - name: huggingface + engine: huggingface + shortcut: hf + disabled: true + + - name: huggingface datasets + huggingface_endpoint: datasets + engine: huggingface + shortcut: hfd + disabled: true + + - name: huggingface spaces + huggingface_endpoint: spaces + engine: huggingface + shortcut: hfs + disabled: true + + - name: imdb + engine: imdb + shortcut: imdb + timeout: 6.0 + disabled: false + categories: [movies] + + - name: imgur + engine: imgur + shortcut: img + disabled: true + + - name: ina + engine: ina + shortcut: in + timeout: 6.0 + disabled: true + + # - name: invidious + # engine: invidious + # # if you want to use invidious with SearXNG you should setup one locally + # # https://github.com/searxng/searxng/issues/2722#issuecomment-2884993248 + # base_url: + # - https://invidious.example1.com + # - https://invidious.example2.com + # shortcut: iv + # timeout: 3.0 + + - name: ipernity + engine: ipernity + shortcut: ip + disabled: true + + - name: iqiyi + engine: iqiyi + shortcut: iq + disabled: true + + - name: jisho + engine: jisho + shortcut: js + timeout: 3.0 + disabled: true + + - name: kickass + engine: kickass + base_url: + - https://kickasstorrents.to + - https://kickasstorrents.cr + - https://kickasstorrent.cr + - https://kickass.sx + - https://kat.am + shortcut: kc + timeout: 4.0 + disabled: true + + - name: lemmy communities + engine: lemmy + lemmy_type: Communities + shortcut: leco + disabled: true + + - name: lemmy users + engine: lemmy + network: lemmy communities + lemmy_type: Users + shortcut: leus + disabled: true + + - name: lemmy posts + engine: lemmy + network: lemmy communities + lemmy_type: Posts + shortcut: lepo + disabled: true + + - name: lemmy comments + engine: lemmy + network: lemmy communities + lemmy_type: Comments + shortcut: lecom + disabled: true + + - name: library genesis + engine: xpath + # search_url: https://libgen.is/search.php?req={query} + search_url: https://libgen.rs/search.php?req={query} + url_xpath: //a[contains(@href,"book/index.php?md5")]/@href + title_xpath: //a[contains(@href,"book/")]/text()[1] + content_xpath: //td/a[1][contains(@href,"=author")]/text() + categories: files + timeout: 7.0 + disabled: true + inactive: true + shortcut: lg + about: + website: https://libgen.fun/ + wikidata_id: Q22017206 + official_api_documentation: + use_official_api: false + require_api_key: false + results: HTML + + - name: z-library + engine: zlibrary + shortcut: zlib + timeout: 7.0 + disabled: true + # https://github.com/searxng/searxng/issues/3610 + inactive: true + + - name: library of congress + engine: loc + shortcut: loc + categories: [images] + disabled: true + + - name: libretranslate + engine: libretranslate + # https://github.com/LibreTranslate/LibreTranslate?tab=readme-ov-file#mirrors + base_url: + - https://libretranslate.com/translate + # api_key: abc123 + shortcut: lt + disabled: true + categories: [general, translate] + + - name: lingva + engine: lingva + shortcut: lv + disabled: true + categories: [general, translate] + # set lingva instance in url, by default it will use the official instance + # url: https://lingva.thedaviddelta.com + + - name: lobste.rs + engine: xpath + search_url: https://lobste.rs/search?q={query}&what=stories&order=relevance + results_xpath: //li[contains(@class, "story")] + url_xpath: .//a[@class="u-url"]/@href + title_xpath: .//a[@class="u-url"] + content_xpath: .//a[@class="domain"] + categories: [it] + shortcut: lo + timeout: 5.0 + disabled: true + about: + website: https://lobste.rs/ + wikidata_id: Q60762874 + official_api_documentation: + use_official_api: false + require_api_key: false + results: HTML + + - name: marginalia + engine: marginalia + shortcut: mar + # To get an API key, please follow the instructions at + # - https://about.marginalia-search.com/article/api/ + # api_key: ... + disabled: true + inactive: true + + - name: mastodon users + engine: mastodon + mastodon_type: accounts + base_url: https://mastodon.social + shortcut: mau + disabled: true + + - name: mastodon hashtags + engine: mastodon + mastodon_type: hashtags + base_url: https://mastodon.social + shortcut: mah + disabled: true + + # - name: matrixrooms + # engine: mrs + # # https://docs.searxng.org/dev/engines/online/mrs.html + # # base_url: https://mrs-api-host + # shortcut: mtrx + # disabled: true + + - name: mdn + shortcut: mdn + engine: json_engine + categories: [it] + paging: true + search_url: https://developer.mozilla.org/api/v1/search?q={query}&page={pageno} + results_query: documents + url_query: mdn_url + url_prefix: https://developer.mozilla.org + title_query: title + content_query: summary + disabled: true + about: + website: https://developer.mozilla.org + wikidata_id: Q3273508 + official_api_documentation: null + use_official_api: false + require_api_key: false + results: JSON + + - name: metacpan + engine: metacpan + shortcut: cpan + disabled: true + number_of_results: 20 + + # https://docs.searxng.org/dev/engines/offline/search-indexer-engines.html#module-searx.engines.meilisearch + # - name: meilisearch + # engine: meilisearch + # shortcut: mes + # enable_http: true + # base_url: http://localhost:7700 + # index: my-index + # auth_key: Bearer XXXX + + - name: microsoft learn + engine: microsoft_learn + shortcut: msl + disabled: true + categories: [it] + + - name: mixcloud + engine: mixcloud + shortcut: mc + disabled: true + + # MongoDB engine + # Required dependency: pymongo + # - name: mymongo + # engine: mongodb + # shortcut: md + # exact_match_only: false + # host: '127.0.0.1' + # port: 27017 + # enable_http: true + # results_per_page: 20 + # database: 'business' + # collection: 'reviews' # name of the db collection + # key: 'name' # key in the collection to search for + + - name: mozhi + engine: mozhi + base_url: + - https://mozhi.aryak.me + - https://translate.bus-hit.me + - https://nyc1.mz.ggtyler.dev + # mozhi_engine: google - see https://mozhi.aryak.me for supported engines + timeout: 4.0 + shortcut: mz + disabled: true + + - name: mwmbl + engine: mwmbl + # api_url: https://api.mwmbl.org + shortcut: mwm + disabled: true + + - name: niconico + engine: niconico + shortcut: nico + disabled: true + + - name: npm + engine: npm + shortcut: npm + timeout: 5.0 + disabled: true + + - name: nyaa + engine: nyaa + shortcut: nt + disabled: true + + - name: mankier + engine: json_engine + search_url: https://www.mankier.com/api/v2/mans/?q={query} + results_query: results + url_query: url + title_query: name + content_query: description + categories: it + shortcut: man + disabled: true + about: + website: https://www.mankier.com/ + official_api_documentation: https://www.mankier.com/api + use_official_api: true + require_api_key: false + results: JSON + + # https://docs.searxng.org/dev/engines/online/mullvad_leta.html + - name: mullvadleta + engine: mullvad_leta + disabled: true + leta_engine: google + categories: [general, web] + shortcut: ml + + - name: mullvadleta brave + engine: mullvad_leta + network: mullvadleta + disabled: true + leta_engine: brave + categories: [general, web] + shortcut: mlb + + - name: odysee + engine: odysee + shortcut: od + disabled: true + + - name: ollama + engine: ollama + shortcut: ollama + disabled: true + + - name: openairedatasets + engine: json_engine + paging: true + search_url: https://api.openaire.eu/search/datasets?format=json&page={pageno}&size=10&title={query} + results_query: response/results/result + url_query: metadata/oaf:entity/oaf:result/children/instance/webresource/url/$ + title_query: metadata/oaf:entity/oaf:result/title/$ + content_query: metadata/oaf:entity/oaf:result/description/$ + content_html_to_text: true + categories: [science] + shortcut: oad + timeout: 5.0 + disabled: true + about: + website: https://www.openaire.eu/ + wikidata_id: Q25106053 + official_api_documentation: https://api.openaire.eu/ + use_official_api: false + require_api_key: false + results: JSON + + - name: openairepublications + engine: json_engine + paging: true + search_url: https://api.openaire.eu/search/publications?format=json&page={pageno}&size=10&title={query} + results_query: response/results/result + url_query: metadata/oaf:entity/oaf:result/children/instance/webresource/url/$ + title_query: metadata/oaf:entity/oaf:result/title/$ + content_query: metadata/oaf:entity/oaf:result/description/$ + content_html_to_text: true + categories: [science] + shortcut: oap + timeout: 5.0 + disabled: true + about: + website: https://www.openaire.eu/ + wikidata_id: Q25106053 + official_api_documentation: https://api.openaire.eu/ + use_official_api: false + require_api_key: false + results: JSON + + - name: openalex + engine: openalex + shortcut: oa + # https://docs.searxng.org/dev/engines/online/openalex.html + # Recommended by OpenAlex: join the polite pool with an email address + # mailto: "[email protected]" + timeout: 5.0 + disabled: false + categories: [science, scientific publications] + + - name: openclipart + engine: openclipart + shortcut: ocl + inactive: true + disabled: true + timeout: 30 + + - name: openlibrary + engine: openlibrary + shortcut: ol + timeout: 10 + disabled: true + categories: [general, books] + + - name: openmeteo + engine: open_meteo + shortcut: om + disabled: false + categories: [weather] + + # - name: opensemanticsearch + # engine: opensemantic + # shortcut: oss + # base_url: 'http://localhost:8983/solr/opensemanticsearch/' + + - name: openstreetmap + engine: openstreetmap + shortcut: osm + disabled: false + categories: [map] + + - name: openrepos + engine: xpath + paging: true + search_url: https://openrepos.net/search/node/{query}?page={pageno} + url_xpath: //li[@class="search-result"]//h3[@class="title"]/a/@href + title_xpath: //li[@class="search-result"]//h3[@class="title"]/a + content_xpath: //li[@class="search-result"]//div[@class="search-snippet-info"]//p[@class="search-snippet"] + categories: files + timeout: 4.0 + disabled: true + shortcut: or + about: + website: https://openrepos.net/ + wikidata_id: + official_api_documentation: + use_official_api: false + require_api_key: false + results: HTML + + - name: packagist + engine: json_engine + paging: true + search_url: https://packagist.org/search.json?q={query}&page={pageno} + results_query: results + url_query: url + title_query: name + content_query: description + categories: [it, packages] + disabled: true + timeout: 5.0 + shortcut: pack + about: + website: https://packagist.org + wikidata_id: Q108311377 + official_api_documentation: https://packagist.org/apidoc + use_official_api: true + require_api_key: false + results: JSON + + - name: pdbe + engine: pdbe + shortcut: pdb + disabled: true + # Hide obsolete PDB entries. Default is not to hide obsolete structures + # hide_obsolete: false + + - name: photon + engine: photon + shortcut: ph + disabled: true + + - name: pinterest + engine: pinterest + shortcut: pin + disabled: true + + - name: piped + engine: piped + shortcut: ppd + categories: videos + piped_filter: videos + timeout: 3.0 + inactive: true + disabled: true + + # URL to use as link and for embeds + frontend_url: https://srv.piped.video + # Instance will be selected randomly, for more see https://piped-instances.kavin.rocks/ + backend_url: + - https://pipedapi.ducks.party + - https://api.piped.private.coffee + + - name: piped.music + engine: piped + network: piped + shortcut: ppdm + categories: music + piped_filter: music_songs + timeout: 3.0 + inactive: true + + - name: piratebay + engine: piratebay + shortcut: tpb + # You may need to change this URL to a proxy if piratebay is blocked in your + # country + url: https://thepiratebay.org/ + timeout: 3.0 + + - name: pixabay images + engine: pixabay + pixabay_type: images + categories: images + shortcut: pixi + disabled: true + + - name: pixabay videos + engine: pixabay + pixabay_type: videos + categories: videos + shortcut: pixv + disabled: true + + - name: pixiv + shortcut: pv + engine: pixiv + disabled: true + inactive: true + pixiv_image_proxies: + - https://pximg.example.org + # A proxy is required to load the images. Hosting an image proxy server + # for Pixiv: + # --> https://pixivfe.pages.dev/hosting-image-proxy-server/ + # Proxies from public instances. Ask the public instances owners if they + # agree to receive traffic from SearXNG! + # --> https://codeberg.org/VnPower/PixivFE#instances + # --> https://github.com/searxng/searxng/pull/3192#issuecomment-1941095047 + # image proxy of https://pixiv.cat + # - https://i.pixiv.cat + # image proxy of https://www.pixiv.pics + # - https://pximg.cocomi.eu.org + # image proxy of https://pixivfe.exozy.me + # - https://pximg.exozy.me + # image proxy of https://pixivfe.ducks.party + # - https://pixiv.ducks.party + # image proxy of https://pixiv.perennialte.ch + # - https://pximg.perennialte.ch + + - name: podcastindex + engine: podcastindex + shortcut: podcast + disabled: true + + # Required dependency: psychopg2 + # - name: postgresql + # engine: postgresql + # database: postgres + # username: postgres + # password: postgres + # limit: 10 + # query_str: 'SELECT * from my_table WHERE my_column = %(query)s' + # shortcut : psql + + - name: presearch + engine: presearch + search_type: search + categories: [general, web] + shortcut: ps + timeout: 4.0 + disabled: true + + - name: presearch images + engine: presearch + network: presearch + search_type: images + categories: [images, web] + timeout: 4.0 + shortcut: psimg + disabled: true + + - name: presearch videos + engine: presearch + network: presearch + search_type: videos + categories: [general, web] + timeout: 4.0 + shortcut: psvid + disabled: true + + - name: presearch news + engine: presearch + network: presearch + search_type: news + categories: [news, web] + timeout: 4.0 + shortcut: psnews + disabled: true + + - name: pub.dev + engine: xpath + shortcut: pd + search_url: https://pub.dev/packages?q={query}&page={pageno} + paging: true + results_xpath: //div[contains(@class,"packages-item")] + url_xpath: ./div/h3/a/@href + title_xpath: ./div/h3/a + content_xpath: ./div/div/div[contains(@class,"packages-description")]/span + categories: [packages, it] + timeout: 3.0 + disabled: true + first_page_num: 1 + about: + website: https://pub.dev/ + official_api_documentation: https://pub.dev/help/api + use_official_api: false + require_api_key: false + results: HTML + + - name: public domain image archive + engine: public_domain_image_archive + shortcut: pdia + disabled: true + + - name: pubmed + engine: pubmed + shortcut: pub + categories: [science, scientific publications] + + - name: pypi + shortcut: pypi + engine: pypi + disabled: true + + - name: quark + quark_category: general + categories: [general] + engine: quark + shortcut: qk + disabled: true + + - name: quark images + quark_category: images + categories: [images] + engine: quark + shortcut: qki + disabled: true + + - name: qwant + qwant_categ: web + engine: qwant + shortcut: qw + categories: [general, web] + disabled: true + # additional_tests: + # rosebud: *test_rosebud + + - name: qwant news + qwant_categ: news + engine: qwant + shortcut: qwn + categories: [news] + network: qwant + disabled: true + + - name: qwant images + qwant_categ: images + engine: qwant + shortcut: qwi + categories: [images, web] + network: qwant + disabled: true + + - name: qwant videos + qwant_categ: videos + engine: qwant + shortcut: qwv + categories: [videos, web] + network: qwant + disabled: true + + # - name: library + # engine: recoll + # shortcut: lib + # base_url: 'https://recoll.example.org/' + # search_dir: '' + # mount_prefix: /export + # dl_prefix: 'https://download.example.org' + # timeout: 30.0 + # categories: files + # disabled: true + + # - name: recoll library reference + # engine: recoll + # base_url: 'https://recoll.example.org/' + # search_dir: reference + # mount_prefix: /export + # dl_prefix: 'https://download.example.org' + # shortcut: libr + # timeout: 30.0 + # categories: files + # disabled: true + + - name: radio browser + engine: radio_browser + shortcut: rb + disabled: true + + - name: reddit + engine: reddit + shortcut: re + page_size: 25 + disabled: true + + - name: reuters + engine: reuters + shortcut: reu + categories: [news] + # https://docs.searxng.org/dev/engines/online/reuters.html + # sort_order = "relevance" + + - name: right dao + engine: xpath + paging: true + page_size: 12 + search_url: https://rightdao.com/search?q={query}&start={pageno} + results_xpath: //div[contains(@class, "description")] + url_xpath: ../div[contains(@class, "title")]/a/@href + title_xpath: ../div[contains(@class, "title")] + content_xpath: . + categories: [general] + shortcut: rd + disabled: true + about: + website: https://rightdao.com/ + use_official_api: false + require_api_key: false + results: HTML + + - name: rottentomatoes + engine: rottentomatoes + shortcut: rt + disabled: true + categories: [movies] + + # Required dependency: valkey + # - name: myvalkey + # shortcut : rds + # engine: valkey_server + # exact_match_only: false + # host: '127.0.0.1' + # port: 6379 + # enable_http: true + # password: '' + # db: 0 + + # tmp suspended: bad certificate + # - name: scanr structures + # shortcut: scs + # engine: scanr_structures + # disabled: true + + - name: searchmysite + engine: xpath + shortcut: sms + categories: [general] + paging: true + search_url: https://searchmysite.net/search/?q={query}&page={pageno} + results_xpath: //div[contains(@class,'search-result')] + url_xpath: .//a[contains(@class,'result-link')]/@href + title_xpath: .//span[contains(@class,'result-title-txt')]/text() + content_xpath: ./p[@id='result-hightlight'] + disabled: true + about: + website: https://searchmysite.net + + - name: selfhst icons + engine: selfhst + shortcut: si + disabled: true + + - name: sepiasearch + engine: sepiasearch + shortcut: sep + disabled: true + categories: [videos] + + - name: sogou + engine: sogou + shortcut: sogou + disabled: true + + - name: sogou images + engine: sogou_images + shortcut: sogoui + disabled: true + + - name: sogou videos + engine: sogou_videos + shortcut: sogouv + disabled: true + + - name: sogou wechat + engine: sogou_wechat + shortcut: sogouw + disabled: true + + - name: soundcloud + engine: soundcloud + shortcut: sc + disabled: true + + - name: stackoverflow + engine: stackexchange + shortcut: st + api_site: 'stackoverflow' + categories: [it, q&a] + disabled: true + + - name: askubuntu + engine: stackexchange + shortcut: ubuntu + api_site: 'askubuntu' + categories: [it, q&a] + disabled: true + + - name: superuser + engine: stackexchange + shortcut: su + api_site: 'superuser' + categories: [it, q&a] + disabled: true + + - name: discuss.python + engine: discourse + shortcut: dpy + base_url: 'https://discuss.python.org' + categories: [it, q&a] + disabled: true + + - name: caddy.community + engine: discourse + shortcut: caddy + base_url: 'https://caddy.community' + categories: [it, q&a] + disabled: true + + - name: pi-hole.community + engine: discourse + shortcut: pi + categories: [it, q&a] + base_url: 'https://discourse.pi-hole.net' + disabled: true + + - name: searchcode code + engine: searchcode_code + shortcut: scc + disabled: true + inactive: true + + # - name: searx + # engine: searx_engine + # shortcut: se + # instance_urls : + # - http://127.0.0.1:8888/ + # - ... + # disabled: true + + - name: semantic scholar + engine: semantic_scholar + shortcut: se + categories: [science, scientific publications] + + # Spotify needs API credentials + # - name: spotify + # engine: spotify + # shortcut: stf + # api_client_id: ******* + # api_client_secret: ******* + + # - name: solr + # engine: solr + # shortcut: slr + # base_url: http://localhost:8983 + # collection: collection_name + # sort: '' # sorting: asc or desc + # field_list: '' # comma separated list of field names to display on the UI + # default_fields: '' # default field to query + # query_fields: '' # query fields + # enable_http: true + + - name: springer nature + engine: springer + shortcut: springer + timeout: 5 + # read https://docs.searxng.org/dev/engines/online/springer.html + api_key: "" + inactive: true + disabled: true + categories: [science, scientific publications] + + - name: startpage + engine: startpage + shortcut: sp + startpage_categ: web + categories: [general, web] + disabled: true + # additional_tests: + # rosebud: *test_rosebud + + - name: startpage news + engine: startpage + startpage_categ: news + categories: [news, web] + shortcut: spn + disabled: true + + - name: startpage images + engine: startpage + startpage_categ: images + categories: [images, web] + shortcut: spi + disabled: true + + - name: steam + engine: steam + shortcut: stm + disabled: true + + - name: tokyotoshokan + engine: tokyotoshokan + shortcut: tt + timeout: 6.0 + disabled: true + + - name: solidtorrents + engine: solidtorrents + shortcut: solid + timeout: 4.0 + disabled: true + base_url: + - https://solidtorrents.to + - https://bitsearch.to + + # For this demo of the sqlite engine download: + # https://liste.mediathekview.de/filmliste-v2.db.bz2 + # and unpack into searx/data/filmliste-v2.db + # Query to test: "!mediathekview concert" + # + # - name: mediathekview + # engine: sqlite + # shortcut: mediathekview + # categories: [general, videos] + # result_type: MainResult + # database: searx/data/filmliste-v2.db + # query_str: >- + # SELECT title || ' (' || time(duration, 'unixepoch') || ')' AS title, + # COALESCE( NULLIF(url_video_hd,''), NULLIF(url_video_sd,''), url_video) AS url, + # description AS content + # FROM film + # WHERE title LIKE :wildcard OR description LIKE :wildcard + # ORDER BY duration DESC + + - name: tagesschau + engine: tagesschau + # when set to false, display URLs from Tagesschau, and not the actual source + # (e.g. NDR, WDR, SWR, HR, ...) + use_source_url: true + shortcut: ts + disabled: true + + - name: tmdb + engine: xpath + paging: true + categories: [movies] + search_url: https://www.themoviedb.org/search?page={pageno}&query={query} + results_xpath: //div[contains(@class,"movie") or contains(@class,"tv")]//div[contains(@class,"card")] + url_xpath: .//div[contains(@class,"poster")]/a/@href + thumbnail_xpath: .//img/@src + title_xpath: .//div[contains(@class,"title")]//h2 + content_xpath: .//div[contains(@class,"overview")] + shortcut: tm + disabled: true + + # Requires Tor + - name: torch + engine: xpath + paging: true + search_url: + http://xmh57jrknzkhv6y3ls3ubitzfqnkrwxhopf5aygthi7d6rplyvk3noyd.onion/cgi-bin/omega/omega?P={query}&DEFAULTOP=and + results_xpath: //table//tr + url_xpath: ./td[2]/a + title_xpath: ./td[2]/b + content_xpath: ./td[2]/small + categories: onions + enable_http: true + shortcut: tch + disabled: true + + # TubeArchivist is a self-hosted Youtube archivist software. + # https://docs.searxng.org/dev/engines/online/tubearchivist.html + # + # - name: tubearchivist + # engine: tubearchivist + # shortcut: tuba + # base_url: + # ta_token: + # ta_link_to_mp4: false + + # torznab engine lets you query any torznab compatible indexer. Using this + # engine in combination with Jackett opens the possibility to query a lot of + # public and private indexers directly from SearXNG. More details at: + # https://docs.searxng.org/dev/engines/online/torznab.html + # + # - name: Torznab EZTV + # engine: torznab + # shortcut: eztv + # base_url: http://localhost:9117/api/v2.0/indexers/eztv/results/torznab + # enable_http: true # if using localhost + # api_key: xxxxxxxxxxxxxxx + # show_magnet_links: true + # show_torrent_files: false + # # https://github.com/Jackett/Jackett/wiki/Jackett-Categories + # torznab_categories: # optional + # - 2000 + # - 5000 + + # tmp suspended - too slow, too many errors + # - name: urbandictionary + # engine : xpath + # search_url : https://www.urbandictionary.com/define.php?term={query} + # url_xpath : //*[@class="word"]/@href + # title_xpath : //*[@class="def-header"] + # content_xpath: //*[@class="meaning"] + # shortcut: ud + + - name: unsplash + engine: unsplash + shortcut: us + disabled: true + + - name: yandex + engine: yandex + categories: [general, web] + search_type: web + shortcut: yd + + - name: yandex images + engine: yandex + categories: [images, web] + search_type: images + shortcut: ydi + + - name: yandex music + engine: yandex_music + shortcut: ydm + disabled: true + # https://yandex.com/support/music/access.html + inactive: true + + - name: yahoo + engine: yahoo + shortcut: yh + categories: [general, web] + + - name: yahoo news + engine: yahoo_news + shortcut: yhn + categories: [news] + + - name: youtube + shortcut: yt + # You can use the engine using the official stable API, but you need an API + # key See: https://console.developers.google.com/project + # + # engine: youtube_api + # api_key: 'apikey' # required! + # + # Or you can use the html non-stable engine, activated by default + engine: youtube_noapi + categories: [videos, music] + + - name: dailymotion + engine: dailymotion + shortcut: dm + categories: [videos] + + - name: vimeo + engine: vimeo + shortcut: vm + categories: [videos] + + - name: wiby + engine: json_engine + paging: true + search_url: https://wiby.me/json/?q={query}&p={pageno} + url_query: URL + title_query: Title + content_query: Snippet + categories: [general, web] + shortcut: wib + disabled: true + about: + website: https://wiby.me/ + + - name: wikibooks + engine: mediawiki + weight: 0.5 + shortcut: wb + categories: [general, wikimedia] + base_url: "https://{language}.wikibooks.org/" + search_type: text + disabled: true + about: + website: https://www.wikibooks.org/ + wikidata_id: Q367 + + - name: wikinews + engine: mediawiki + shortcut: wn + categories: [news, wikimedia] + base_url: "https://{language}.wikinews.org/" + search_type: text + disabled: true + srsort: create_timestamp_desc + about: + website: https://www.wikinews.org/ + wikidata_id: Q964 + + - name: wikiquote + engine: mediawiki + weight: 0.5 + shortcut: wq + categories: [general, wikimedia] + base_url: "https://{language}.wikiquote.org/" + search_type: text + disabled: true + # additional_tests: + # rosebud: *test_rosebud + about: + website: https://www.wikiquote.org/ + wikidata_id: Q369 + + - name: wikisource + engine: mediawiki + weight: 0.5 + shortcut: ws + categories: [general, wikimedia] + base_url: "https://{language}.wikisource.org/" + search_type: text + disabled: true + about: + website: https://www.wikisource.org/ + wikidata_id: Q263 + + - name: wikispecies + engine: mediawiki + shortcut: wsp + categories: [general, science, wikimedia] + base_url: "https://species.wikimedia.org/" + search_type: text + disabled: true + about: + website: https://species.wikimedia.org/ + wikidata_id: Q13679 + tests: + wikispecies: + matrix: + query: "Campbell, L.I. et al. 2011: MicroRNAs" + lang: en + result_container: + - not_empty + - ['one_title_contains', 'Tardigrada'] + test: + - unique_results + + - name: wiktionary + engine: mediawiki + shortcut: wt + categories: [dictionaries, wikimedia] + base_url: "https://{language}.wiktionary.org/" + search_type: text + disabled: true + about: + website: https://www.wiktionary.org/ + wikidata_id: Q151 + + - name: wikiversity + engine: mediawiki + weight: 0.5 + shortcut: wv + categories: [general, wikimedia] + base_url: "https://{language}.wikiversity.org/" + search_type: text + disabled: true + about: + website: https://www.wikiversity.org/ + wikidata_id: Q370 + + - name: wikivoyage + engine: mediawiki + weight: 0.5 + shortcut: wy + categories: [general, wikimedia] + base_url: "https://{language}.wikivoyage.org/" + search_type: text + disabled: true + about: + website: https://www.wikivoyage.org/ + wikidata_id: Q373 + + - name: wikicommons.images + engine: wikicommons + shortcut: wci + categories: [images] + wc_search_type: image + disabled: true + + - name: wikicommons.videos + engine: wikicommons + shortcut: wcv + categories: [videos] + wc_search_type: video + disabled: true + + - name: wikicommons.audio + engine: wikicommons + shortcut: wca + categories: [music] + wc_search_type: audio + disabled: true + + - name: wikicommons.files + engine: wikicommons + shortcut: wcf + categories: [files] + wc_search_type: file + disabled: true + + - name: wolframalpha + shortcut: wa + # You can use the engine using the official stable API, but you need an API + # key. See: https://products.wolframalpha.com/api/ + # + # engine: wolframalpha_api + # api_key: '' + # + # Or you can use the html non-stable engine, activated by default + engine: wolframalpha_noapi + timeout: 6.0 + categories: [general] + disabled: true + + - name: dictzone + engine: dictzone + shortcut: dc + disabled: true + + - name: mymemory translated + engine: translated + shortcut: tl + timeout: 5.0 + disabled: true + # You can use without an API key, but you are limited to 1000 words/day + # See: https://mymemory.translated.net/doc/usagelimits.php + # api_key: '' + + # Required dependency: mysql-connector-python + # - name: mysql + # engine: mysql_server + # database: mydatabase + # username: user + # password: pass + # limit: 10 + # query_str: 'SELECT * from mytable WHERE fieldname=%(query)s' + # shortcut: mysql + + # Required dependency: mariadb + # - name: mariadb + # engine: mariadb_server + # database: mydatabase + # username: user + # password: pass + # limit: 10 + # query_str: 'SELECT * from mytable WHERE fieldname=%(query)s' + # shortcut: mdb + + - name: 1337x + engine: 1337x + shortcut: 1337x + disabled: true + + - name: duden + engine: duden + shortcut: du + disabled: true + + - name: seznam + shortcut: szn + engine: seznam + disabled: true + + # - name: deepl + # engine: deepl + # shortcut: dpl + # # You can use the engine using the official stable API, but you need an API key + # # See: https://www.deepl.com/pro-api?cta=header-pro-api + # api_key: '' # required! + # timeout: 5.0 + # disabled: true + + - name: mojeek + shortcut: mjk + engine: mojeek + categories: [general, web] + disabled: true + + - name: mojeek images + shortcut: mjkimg + engine: mojeek + categories: [images, web] + search_type: images + paging: false + disabled: true + + - name: mojeek news + shortcut: mjknews + engine: mojeek + categories: [news, web] + search_type: news + paging: false + disabled: true + + - name: moviepilot + engine: moviepilot + shortcut: mp + disabled: true + + - name: naver + categories: [general, web] + engine: naver + shortcut: nvr + disabled: true + + - name: naver images + naver_category: images + categories: [images] + engine: naver + shortcut: nvri + disabled: true + + - name: naver news + naver_category: news + categories: [news] + engine: naver + shortcut: nvrn + disabled: true + + - name: naver videos + naver_category: videos + categories: [videos] + engine: naver + shortcut: nvrv + disabled: true + + - name: rubygems + shortcut: rbg + engine: xpath + paging: true + search_url: https://rubygems.org/search?page={pageno}&query={query} + results_xpath: /html/body/main/div/a[@class="gems__gem"] + url_xpath: ./@href + title_xpath: ./span/h2 + content_xpath: ./span/p + suggestion_xpath: /html/body/main/div/div[@class="search__suggestions"]/p/a + first_page_num: 1 + categories: [it, packages] + disabled: true + about: + website: https://rubygems.org/ + wikidata_id: Q1853420 + official_api_documentation: https://guides.rubygems.org/rubygems-org-api/ + use_official_api: false + require_api_key: false + results: HTML + + - name: peertube + engine: peertube + shortcut: ptb + paging: true + # alternatives see: https://instances.joinpeertube.org/instances + # base_url: https://tube.4aem.com + categories: videos + disabled: true + timeout: 6.0 + + - name: mediathekviewweb + engine: mediathekviewweb + shortcut: mvw + disabled: true + + - name: yacy + # https://docs.searxng.org/dev/engines/online/yacy.html + engine: yacy + categories: [general] + search_type: text + # see https://github.com/searxng/searxng/pull/3631#issuecomment-2240903027 + base_url: + - https://yacy.searchlab.eu + shortcut: ya + disabled: true + # if you aren't using HTTPS for your local yacy instance disable https + # enable_http: false + search_mode: 'global' + # timeout can be reduced in 'local' search mode + timeout: 5.0 + + - name: yacy images + engine: yacy + network: yacy + categories: [images] + search_type: image + shortcut: yai + disabled: true + base_url: + - https://yacy.searchlab.eu + # timeout can be reduced in 'local' search mode + timeout: 5.0 + + - name: rumble + engine: rumble + shortcut: ru + base_url: https://rumble.com/ + paging: true + categories: [videos] + disabled: true + + - name: repology + engine: repology + shortcut: rep + disabled: true + inactive: true + + - name: livespace + engine: livespace + shortcut: ls + categories: [videos] + disabled: true + timeout: 5.0 + + - name: wordnik + engine: wordnik + shortcut: wnik + timeout: 5.0 + disabled: true + categories: [dictionaries, define] + + - name: woxikon.de synonyme + engine: xpath + shortcut: woxi + categories: [dictionaries] + timeout: 5.0 + disabled: true + search_url: https://synonyme.woxikon.de/synonyme/{query}.php + url_xpath: //div[@class="upper-synonyms"]/a/@href + content_xpath: //div[@class="synonyms-list-group"] + title_xpath: //div[@class="upper-synonyms"]/a + no_result_for_http_status: [404] + about: + website: https://www.woxikon.de/ + wikidata_id: # No Wikidata ID + use_official_api: false + require_api_key: false + results: HTML + language: de + + - name: seekr news + engine: seekr + shortcut: senews + categories: [news] + seekr_category: news + disabled: true + + - name: seekr images + engine: seekr + network: seekr news + shortcut: seimg + categories: [images] + seekr_category: images + disabled: true + + - name: seekr videos + engine: seekr + network: seekr news + shortcut: sevid + categories: [videos] + seekr_category: videos + disabled: true + + - name: stract + engine: stract + shortcut: str + disabled: true + + - name: svgrepo + engine: svgrepo + shortcut: svg + timeout: 10.0 + disabled: true + + - name: tootfinder + engine: tootfinder + shortcut: toot + disabled: true + categories: [social media] + + - name: uxwing + engine: uxwing + shortcut: ux + disabled: true + + - name: voidlinux + engine: voidlinux + shortcut: void + disabled: true + + - name: wallhaven + engine: wallhaven + # api_key: abcdefghijklmnopqrstuvwxyz + shortcut: wh + disabled: true + + # wikimini: online encyclopedia for children + # The fulltext and title parameter is necessary for Wikimini because + # sometimes it will not show the results and redirect instead + - name: wikimini + engine: xpath + shortcut: wkmn + search_url: https://fr.wikimini.org/w/index.php?search={query}&title=Sp%C3%A9cial%3ASearch&fulltext=Search + url_xpath: //li/div[@class="mw-search-result-heading"]/a/@href + title_xpath: //li//div[@class="mw-search-result-heading"]/a + content_xpath: //li/div[@class="searchresult"] + categories: [general] + disabled: true + about: + website: https://wikimini.org/ + wikidata_id: Q3568032 + use_official_api: false + require_api_key: false + results: HTML + language: fr + + - name: wttr.in + engine: wttr + shortcut: wttr + timeout: 9.0 + categories: [weather] + + - name: brave + engine: brave + shortcut: br + time_range_support: true + paging: true + categories: [general, web] + brave_category: search + # brave_spellcheck: true + + - name: brave.images + engine: brave + network: brave + shortcut: brimg + categories: [images, web] + brave_category: images + + - name: brave.videos + engine: brave + network: brave + shortcut: brvid + categories: [videos, web] + brave_category: videos + + - name: brave.news + engine: brave + network: brave + shortcut: brnews + categories: [news] + brave_category: news + + # - name: brave.goggles + # engine: brave + # network: brave + # shortcut: brgog + # time_range_support: true + # paging: true + # categories: [general, web] + # brave_category: goggles + # Goggles: # required! This should be a URL ending in .goggle + + - name: lib.rs + shortcut: lrs + engine: lib_rs + disabled: true + + # - name: sourcehut + # shortcut: srht + # engine: sourcehut + # # https://docs.searxng.org/dev/engines/online/sourcehut.html + # # sourcehut_sort_order: longest-active + # disabled: true + # inactive: true + + - name: goo + shortcut: goo + engine: xpath + paging: true + search_url: https://search.goo.ne.jp/web.jsp?MT={query}&FR={pageno}0 + url_xpath: //div[@class="result"]/p[@class='title fsL1']/a/@href + title_xpath: //div[@class="result"]/p[@class='title fsL1']/a + content_xpath: //p[contains(@class,'url fsM')]/following-sibling::p + first_page_num: 0 + categories: [general, web] + disabled: true + inactive: true + timeout: 4.0 + about: + website: https://search.goo.ne.jp + wikidata_id: Q249044 + use_official_api: false + require_api_key: false + results: HTML + language: ja + + - name: bt4g + engine: bt4g + shortcut: bt4g + disabled: true + categories: [files] + + - name: pkg.go.dev + engine: pkg_go_dev + shortcut: pgo + disabled: true + + - name: senscritique + engine: senscritique + shortcut: scr + timeout: 4.0 + disabled: true + + - name: minecraft wiki + engine: mediawiki + shortcut: mcw + categories: ["software wikis"] + base_url: https://minecraft.wiki/ + api_path: "api.php" + search_type: text + disabled: true + about: + website: https://minecraft.wiki/ + wikidata_id: Q105533483 + +# Doku engine lets you access to any Doku wiki instance: +# A public one or a privete/corporate one. +# - name: ubuntuwiki +# engine: doku +# shortcut: uw +# base_url: 'https://doc.ubuntu-fr.org' + +# Be careful when enabling this engine if you are +# running a public instance. Do not expose any sensitive +# information. You can restrict access by configuring a list +# of access tokens under tokens. +# - name: git grep +# engine: command +# command: ['git', 'grep', '{{QUERY}}'] +# shortcut: gg +# tokens: [] +# disabled: true +# delimiter: +# chars: ':' +# keys: ['filepath', 'code'] + +# Be careful when enabling this engine if you are +# running a public instance. Do not expose any sensitive +# information. You can restrict access by configuring a list +# of access tokens under tokens. +# - name: locate +# engine: command +# command: ['locate', '{{QUERY}}'] +# shortcut: loc +# tokens: [] +# disabled: true +# delimiter: +# chars: ' ' +# keys: ['line'] + +# Be careful when enabling this engine if you are +# running a public instance. Do not expose any sensitive +# information. You can restrict access by configuring a list +# of access tokens under tokens. +# - name: find +# engine: command +# command: ['find', '.', '-name', '{{QUERY}}'] +# query_type: path +# shortcut: fnd +# tokens: [] +# disabled: true +# delimiter: +# chars: ' ' +# keys: ['line'] + +# Be careful when enabling this engine if you are +# running a public instance. Do not expose any sensitive +# information. You can restrict access by configuring a list +# of access tokens under tokens. +# - name: pattern search in files +# engine: command +# command: ['fgrep', '{{QUERY}}'] +# shortcut: fgr +# tokens: [] +# disabled: true +# delimiter: +# chars: ' ' +# keys: ['line'] + +# Be careful when enabling this engine if you are +# running a public instance. Do not expose any sensitive +# information. You can restrict access by configuring a list +# of access tokens under tokens. +# - name: regex search in files +# engine: command +# command: ['grep', '{{QUERY}}'] +# shortcut: gr +# tokens: [] +# disabled: true +# delimiter: +# chars: ' ' +# keys: ['line'] + +doi_resolvers: + oadoi.org: 'https://oadoi.org/' + doi.org: 'https://doi.org/' + sci-hub.se: 'https://sci-hub.se/' + sci-hub.st: 'https://sci-hub.st/' + sci-hub.ru: 'https://sci-hub.ru/' + +default_doi_resolver: 'oadoi.org' \ No newline at end of file diff --git a/src/serious_python/example/searxng_example/app/src/runner/simplexng.py b/src/serious_python/example/searxng_example/app/src/runner/simplexng.py new file mode 100644 index 00000000..2aaef829 --- /dev/null +++ b/src/serious_python/example/searxng_example/app/src/runner/simplexng.py @@ -0,0 +1,196 @@ +""" +SimpleXNG: A simple way to run SearXNG locally +""" +import logging +import os +import secrets +import signal +import sys +import webbrowser +from pathlib import Path +from threading import Timer +from typing import Any + +import searx +import waitress +import yaml +from flask import Response, redirect, url_for +from platformdirs import user_config_dir +from pydantic import BaseModel +from searx.extended_types import sxng_request +from strif import AtomicVar + +from common.config import logger +from mcp.server import SearxngMcpAdapter +from tavily.adapter import TavilyAdapter, TavilyAdapterConfig + +SIMPLEXNG_APP_NAME = os.environ.get('SIMPLEXNG_APP_NAME', "AI4All") +SIMPLEXNG_APP_AUTHOR = os.environ.get('SIMPLEXNG_APP_AUTHOR', "Konnek Inc") + +SEARXNG_SETTINGS_FILE = f"{SIMPLEXNG_APP_NAME.lower()}_settings.yml" +SEARXNG_SETTINGS_DIR = user_config_dir(SIMPLEXNG_APP_NAME, SIMPLEXNG_APP_AUTHOR) + +# Web crawler configuration +CONTENT_FILTER_THRESHOLD = float(os.getenv("CONTENT_FILTER_THRESHOLD", "0.6")) +WORD_COUNT_THRESHOLD = int(os.getenv("WORD_COUNT_THRESHOLD", "10")) + +_settings_path: AtomicVar[Path | None] = AtomicVar(None) + +# SearXNG Server Config +class SearXNGServerConfig(BaseModel): + """ + SearXNG Server Configuration + Attributes: + log_level: logging level of server (default: logging.INFO) + host: Host to bind to (default: localhost). + port: Port to run on (default: 8888) + settings: Path to custom settings.yml file + verbose: Enable verbose logging + """ + log_level: int = logging.INFO + host: str = "127.0.0.1" + port: int = 11888 + app_name: str = SIMPLEXNG_APP_NAME + settings: str = Path(SEARXNG_SETTINGS_DIR) / SEARXNG_SETTINGS_FILE + verbose: bool = False + + +class SimpleXNGServer: + def __init__(self, server_config: SearXNGServerConfig): + self.searxng_server_config = server_config + self.log = logging.getLogger(self.searxng_server_config.app_name) + self.log.setLevel(level=self.searxng_server_config.log_level) + + @staticmethod + def get_bundled_template() -> Path: + return Path(__file__).parent / "settings" / "settings_template.yml" + + @staticmethod + def get_settings_path() -> Path | None: + return _settings_path.copy() + + def configure_server(self): + """ + One-time initialization of settings. + """ + settings_path = Path(self.searxng_server_config.settings) + with _settings_path.lock: + if _settings_path.value: + raise RuntimeError("Settings already initialized") + if settings_path.exists(): + logger.warning("Using specified settings file: %s", settings_path) + else: + # Create from template and host/port + if not settings_path.parent.exists(): + settings_path.parent.mkdir(parents=True, exist_ok=True) + + # This allows dynamic configuration of host/port/secret + template_path = SimpleXNGServer.get_bundled_template() + settings = yaml.safe_load(template_path.read_text()) + + settings["general"]["debug"] = bool(searx.sxng_debug) + settings["server"]["port"] = self.searxng_server_config.port + settings["server"]["bind_address"] = self.searxng_server_config.host + # Generate a cryptographically secure random secret key + settings["server"]["secret_key"] = secrets.token_hex(16) + + content = ( + f"# Generated from template {template_path.name}\n" + f"# Port: {self.searxng_server_config.port}, Host: {self.searxng_server_config.host}\n" + f"# Random secret key generated automatically\n\n" + f"{yaml.dump(settings, default_flow_style=False)}" + ) + settings_path.write_text(content) + + logger.warning("Wrote new settings file (including random secret key): %s", settings_path) + + _settings_path.set(settings_path) + + # Set configs for SearXNG to use this path (and its parent as the config path) + os.environ["SEARXNG_SETTINGS_PATH"] = str(settings_path) + os.environ["SEARXNG_HOST"] = self.searxng_server_config.host + os.environ["SEARXNG_PORT"] = str(self.searxng_server_config.port) + searx.init_settings() + + + def start_server(self): + """ + Start the appropriate server. + """ + + self.configure_server() + + url = f"http://{self.searxng_server_config.host}:{self.searxng_server_config.port}" + server_name = "Flask" if searx.sxng_debug else "Waitress" + + self.log.info(f"Starting {self.searxng_server_config.app_name} with {server_name} server...") + self.log.info(f"URL: {url}") + + self.log.info(f'SEARXNG_SETTINGS_PATH={os.environ["SEARXNG_SETTINGS_PATH"]}') + self.log.info(f'SEARXNG_HOST={os.environ["SEARXNG_HOST"]}') + self.log.info(f'SEARXNG_PORT={os.environ["SEARXNG_PORT"]}') + self.log.info(f"searxng_config={self.searxng_server_config}") + + from searx.webapp import app, search # pyright: ignore + from tavily.adapter import adapter + + @adapter.route('/query', methods=["POST"]) + def query(): + return search() + + app.register_blueprint(adapter) + + from mcp.server import mcp + + @app.route("/mcp", methods=["POST"]) + def mcp_route(): + message = mcp.handle_message(sxng_request.json) + result: str = message.model_dump_json() + return Response(response=result, mimetype='application/json') + + if searx.sxng_debug: + Timer(2, lambda: webbrowser.open(url)).start() + self.log.info("Opening browser...") + app.run(host=self.searxng_server_config.host, port=self.searxng_server_config.port, debug=True) # pyright: ignore[reportUnknownMemberType] + else: + waitress.serve( + app, # pyright: ignore[reportUnknownArgumentType] + host=self.searxng_server_config.host, + port=self.searxng_server_config.port, + threads=4, + connection_limit=100, + cleanup_interval=30, + ) + + # Reset _settings_path + with _settings_path.lock: + _settings_path.set(None) + + +def main() -> None: + """ + Main CLI entry point. + """ + + def signal_handler(_signum: int, _frame: Any) -> None: + """ + Handle Ctrl+C gracefully. + """ + log.warning("Shutting down SearXNG...") + sys.exit(0) + + log = logging.getLogger(__name__) + # Set up signal handling + signal.signal(signal.SIGINT, signal_handler) + + try: + server = SimpleXNGServer(server_config=SearXNGServerConfig()) + TavilyAdapter.configure_tavily_adapter(tavily_config=TavilyAdapterConfig(settings=None)) + server.start_server() + except Exception as e: + log.error(f"Error: {e.__class__.__name__}: {e}") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/src/serious_python/example/searxng_example/app/src/shared/__init__.py b/src/serious_python/example/searxng_example/app/src/shared/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/serious_python/example/searxng_example/app/src/shared/py.typed b/src/serious_python/example/searxng_example/app/src/shared/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/src/serious_python/example/searxng_example/app/src/shared/types.py b/src/serious_python/example/searxng_example/app/src/shared/types.py new file mode 100644 index 00000000..a874939f --- /dev/null +++ b/src/serious_python/example/searxng_example/app/src/shared/types.py @@ -0,0 +1,176 @@ +import asyncio +from enum import Enum +from typing import Optional, Any + +from mcp_utils.core import ResponseQueueProtocol +from mcp_utils.schema import MCPResponse +from pydantic import BaseModel, Field +from queuelib.queue import FifoMemoryQueue + + +class SearxCategory(str, Enum): + general = 'general' + news = 'news' + images = 'images' + music = 'music' + videos = 'videos' + files = 'files' + weather = 'weather' + social_media = 'social media' + map = 'map' + books = 'books' + web = 'web' + it = 'it' + repos = 'repos' + software_wikis = 'software wikis' + packages = 'packages' + code = 'code' + currency = 'currency' + dictionaries = 'dictionaries' + shopping = 'shopping' + movies = 'movies' + q_and_a = 'q&a' + radio = 'radio' + science = 'science' + scientific_publications = 'scientific publications' + +class SearxTimeRange(str, Enum): + day = 'day' + week = 'week' + month = 'month' + year = 'year' + +class TavilyResult(BaseModel): + url: str = Field(description="Url used for result", default=None) + title: str = Field(description="Title of result", default=None) + content: str = Field(description="Content for result", default=None) + score: float = Field(description="Score rank for result", default=0.0) + text: Optional[str] = Field(description="Extracted text for result", default=None) + raw_content: Optional[str] = Field(description="Raw html for result", default=None) + + +class TavilyResponse(BaseModel): + query: str = Field(description="Search query", default=None) + follow_up_questions: Optional[list[str]] = Field(description="Follow-up questions", default=None) + answer: Optional[str] = Field(description="Answer to query", default=None) + images: Optional[list[str]] = Field(description="Image result provided to query", default=None) + results: list[TavilyResult] = Field(description="List of results for query", default=[]) + response_time: float = Field(description="List of results for query", default=None) + request_id: str = Field(description="Request id for query", default=None) + +class InMemoryResponseQueue(ResponseQueueProtocol): + def __init__(self): + super().__init__(self) + self._queues : dict[str, FifoMemoryQueue] = {} + + def push_response( + self, + session_id: str, + response: MCPResponse, + ) -> None: + """ + Push a response to the queue for a specific session + + Args: + session_id: The session ID + response: The response to push + """ + _queue = self._queues.get(session_id, FifoMemoryQueue()) + _queue.push(response) + self._queues[session_id] = _queue + + async def wait_for_response( + self, session_id: str, timeout: float | None = None + ) -> MCPResponse | None: + """ + Wait for a response from the queue for a specific session + + Args: + session_id: The session ID + timeout: How long to wait for a response in seconds. + If None, wait indefinitely. + If 0, return immediately if no response is available. + + Returns: + The next queued response or None if timeout occurs + """ + + if timeout == 0: + # Non-blocking check + _queue = self._queues.get(session_id, FifoMemoryQueue()) + data = _queue.pop() if _queue.len() > 0 else None + self._queues[session_id] = _queue + else: + # Blocking wait with timeout + # coroutine to execute in a new task + async def response(): + # generate a random value between 0 and 1 + waiting = True + result = None + _queue = self._queues.get(session_id, FifoMemoryQueue()) + while waiting: + result, waiting = (_queue.pop(), False) if _queue.len() > 0 else (None, True) + # block for a moment + await asyncio.sleep(0.1) + self._queues[session_id] = _queue + return result + try: + data = await asyncio.wait_for(response(),timeout=timeout) + except: + data = None + + return data + + def clear_session(self, session_id: str) -> None: + """ + Clear all queued responses for a session + + Args: + session_id: The session ID to clear + """ + self._queues.pop(session_id, FifoMemoryQueue()) + +class InMemoryFlipFlopQueue(ResponseQueueProtocol): + def __init__(self): + super().__init__(self) + self._queues : dict[str, MCPResponse | None] = {} + + def push_response( + self, + session_id: str, + response: MCPResponse, + ) -> None: + """ + Push a response to the queue for a specific session + + Args: + session_id: The session ID + response: The response to push + """ + self._queues[session_id] = response + + async def wait_for_response( + self, session_id: str, timeout: float | None = None + ) -> MCPResponse | None: + """ + Wait for a response from the queue for a specific session + + Args: + session_id: The session ID + timeout: How long to wait for a response in seconds. + If None, wait indefinitely. + If 0, return immediately if no response is available. + + Returns: + The next queued response or None if timeout occurs + """ + return self._queues.pop(session_id, None) + + def clear_session(self, session_id: str) -> None: + """ + Clear all queued responses for a session + + Args: + session_id: The session ID to clear + """ + self._queues.pop(session_id, None) diff --git a/src/serious_python/example/searxng_example/app/src/tavily/__init__.py b/src/serious_python/example/searxng_example/app/src/tavily/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/serious_python/example/searxng_example/app/src/tavily/adapter.py b/src/serious_python/example/searxng_example/app/src/tavily/adapter.py new file mode 100644 index 00000000..87968361 --- /dev/null +++ b/src/serious_python/example/searxng_example/app/src/tavily/adapter.py @@ -0,0 +1,215 @@ +""" +Tavily-compatible client for SearXNG +Provides same interface as tavily-python package but uses SearXNG backend +""" +import asyncio +import os +import time +import uuid +from pathlib import Path + +import aiohttp +import yaml + +from bs4 import BeautifulSoup +from flask import Blueprint, Response +from flask.typing import RouteCallable +from platformdirs import user_config_dir +from pydantic import BaseModel +from searx.extended_types import SXNG_Request +from searx.extended_types import sxng_request + +from shared.types import TavilyResult, TavilyResponse + +TAVILY_APP_NAME = os.environ.get('TAVILY_APP_NAME', "tavily_adapter") +TAVILY_APP_AUTHOR = os.environ.get('TAVILY_APP_AUTHOR', "Konnek Inc") + +TAVILY_CONFIG_FILE= f"{TAVILY_APP_NAME.lower()}_config.yml" +TAVILY_CONFIG_DIR = user_config_dir(TAVILY_APP_NAME, TAVILY_APP_AUTHOR) + +class TavilyAdapterConfig(BaseModel): + """ + Configuration loader for Tavily adapter + """ + timeout: int | None = 10 + user_agent: str | None = "Mozilla/5.0 (compatible; SearchBot/1.0)" + settings: str | None = Path(TAVILY_CONFIG_DIR) / TAVILY_CONFIG_FILE + +def get_tavily_config(cfg: TavilyAdapterConfig = TavilyAdapterConfig()) -> TavilyAdapterConfig: + """ + Load configuration from unified YAML file + """ + default_settings = Path(__file__).parent / "settings" / "tavily_defaults.yml" + defaults = yaml.safe_load(default_settings.read_text()) + if cfg.settings: + config_path = Path(cfg.settings) + if config_path.exists(): + settings = yaml.safe_load(config_path.read_text()) + app_settings = settings["crawler"] if settings.get("crawler") else defaults["crawler"] + return TavilyAdapterConfig( + timeout= int(cfg.timeout if cfg.timeout else app_settings["timeout"]), + user_agent=cfg.user_agent if cfg.user_agent else app_settings["user_agent"], + settings = str(config_path) + ) + + return TavilyAdapterConfig( + timeout= int(os.getenv("TAVILY_TIMEOUT", cfg.timeout)), + user_agent= str(os.getenv("TAVILY_USER_AGENT", cfg.user_agent)), + settings = "" + ) + + + +class TavilyAdapter: + __instance = None + __adapter_config: TavilyAdapterConfig | None = TavilyAdapterConfig() + def __init__(self, api_key: str = "", route: RouteCallable | None = None): + self.api_key = api_key # Not used, but kept for compatibility + self._search = route + + @property + def search(self): + return self._search + + @search.setter + def search(self, value): + self._search = value + + @search.deleter + def search(self): + del self._search + + @staticmethod + async def _fetch_raw_content(session: aiohttp.ClientSession, url: str, include_raw_content: bool, content_length: int) -> dict[str, str] | None: + """ + Scraps a page and returns the first 2500 characters of text + """ + try: + async with session.get( + url, + timeout=aiohttp.ClientTimeout(total=TavilyAdapter.__adapter_config.timeout), + headers={'User-Agent': TavilyAdapter.__adapter_config.user_agent} + ) as response: + if response.status != 200: + return None + + html = await response.text() + soup = BeautifulSoup(html, 'html.parser') + + # Remove unnecessary things + for tag in soup(['script', 'style', 'nav', 'header', 'footer', 'aside']): + tag.decompose() + + # Take the text + text = soup.get_text(strip=True, separator=" ") + + # Crop to the specified size + if len(text) > content_length: + text = text[:content_length] + "..." + result = {'url': url, 'text': text, 'raw': html if include_raw_content else ''} + return result + except Exception: + return None + + @staticmethod + def update_request(request: SXNG_Request): + """ + Update the + Args: + request: SXNG_Request that is to be updated + + Returns: + An updated SXNG_Request + """ + request.form.update({ + 'pageno': request.form.get('pageno','1'), + 'format': 'json', + }) + + @staticmethod + async def crawl( + response: Response + ) -> TavilyResponse: + """ + Search using SearXNG with Tavily-compatible interface + + Args: + response: SearXNG Response from metasearch + Returns: + A TavilyResponse as dictionary + """ + start_time = time.time() + request_id = str(uuid.uuid4()) + include_raw_content: bool = int(sxng_request.form.get('include_raw_content','0')) == 0 + scrape_content: bool = int(sxng_request.form.get('scrape_content', '0')) == 1 + content_length: int = int(sxng_request.form.get('content_length', '2500')) + max_results: int = int(sxng_request.form.get('max_results', '10')) + searxng_results = [ r for r in response.json.get("results", []) if r and isinstance(r, dict) and r.get("url")] + accepted_results = searxng_results[:max_results] + raw_contents: dict[str, tuple] | None= None + if scrape_content and accepted_results: + urls_to_scrape = [r["url"] for r in accepted_results if r.get("url")] + async with aiohttp.ClientSession() as scrape_session: + tasks = [TavilyAdapter._fetch_raw_content(scrape_session, url, include_raw_content, content_length) for url in urls_to_scrape] + page_contents = await asyncio.gather(*tasks, return_exceptions=True) + raw_contents = { content['url'] : (content['text'], content['raw']) for content in page_contents if content and isinstance(content, dict)} + + # tokenized_corpus: dict[str, list[str]] = {r["url"]: r.get("content", '').split(" ") for r in accepted_results} + # tokenized_query = sxng_request.form.get('q').split(" ") + # bm25 = BM25Plus(tokenized_corpus.values()) + # doc_scores = bm25.get_scores(tokenized_query) + # try: + # float_list = [float(x) for x in doc_scores.tolist()] + # scores: dict[str, float] | None = dict(zip(tokenized_corpus.keys(), float_list)) + # except (ValueError, TypeError): + # scores = None + + results = [TavilyResult( + url=result["url"], + title=result.get("title", ""), + content=result.get("content", ""), + score= float(result["score"]) if result.get("score") else 0.9 - (i * 0.05), + text=raw_contents.get(result["url"])[0] if raw_contents and raw_contents.get(result["url"]) and len(raw_contents.get(result["url"]))>0 else "", + raw_content= raw_contents.get(result["url"])[1] if raw_contents and raw_contents.get(result["url"]) and len(raw_contents.get(result["url"]))>1 else "", + ) for i, result in enumerate(accepted_results) if result and result.get("url")] + + response_time = time.time() - start_time + + return TavilyResponse( + query=sxng_request.form.get('q'), + follow_up_questions=None, + answer=None, + images=[], + results=results, + response_time=response_time, + request_id=request_id, + ) + + @staticmethod + def configure_tavily_adapter(tavily_config: TavilyAdapterConfig): + TavilyAdapter.__adapter_config = tavily_config + TavilyAdapter.__instance = TavilyAdapter() + + @staticmethod + def get_tavily_adapter(): + if not TavilyAdapter.__instance : + TavilyAdapter.__instance = TavilyAdapter() + return TavilyAdapter.__instance + + @staticmethod + def get_tavily_config(): + return TavilyAdapter.__adapter_config + +adapter = Blueprint(name='tavily', import_name=__name__, url_prefix="/adapter") + +@adapter.before_request +def adapter_before_request(): + TavilyAdapter.update_request(sxng_request) + + +@adapter.after_request +async def adapter_after_request(response: Response): + results: TavilyResponse = await TavilyAdapter.crawl(response) + results_json: str = results.model_dump_json() + response.data = results_json + return response \ No newline at end of file diff --git a/src/serious_python/example/searxng_example/app/src/tavily/py.typed.py b/src/serious_python/example/searxng_example/app/src/tavily/py.typed.py new file mode 100644 index 00000000..e69de29b diff --git a/src/serious_python/example/searxng_example/app/src/tavily/settings/tavily_defaults.yml b/src/serious_python/example/searxng_example/app/src/tavily/settings/tavily_defaults.yml new file mode 100644 index 00000000..cf718981 --- /dev/null +++ b/src/serious_python/example/searxng_example/app/src/tavily/settings/tavily_defaults.yml @@ -0,0 +1,3 @@ +crawler: + timeout: 10 + user_agent: "Mozilla/5.0 (compatible; SearchBot/1.0)" \ No newline at end of file diff --git a/src/serious_python/example/searxng_example/ios/.gitignore b/src/serious_python/example/searxng_example/ios/.gitignore new file mode 100644 index 00000000..7a7f9873 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/src/serious_python/example/searxng_example/ios/Flutter/AppFrameworkInfo.plist b/src/serious_python/example/searxng_example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..9625e105 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/src/serious_python/example/searxng_example/ios/Flutter/Debug.xcconfig b/src/serious_python/example/searxng_example/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..ec97fc6f --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/src/serious_python/example/searxng_example/ios/Flutter/Release.xcconfig b/src/serious_python/example/searxng_example/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..c4855bfe --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/src/serious_python/example/searxng_example/ios/Podfile b/src/serious_python/example/searxng_example/ios/Podfile new file mode 100644 index 00000000..164df534 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Podfile @@ -0,0 +1,44 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '12.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/src/serious_python/example/searxng_example/ios/Podfile.lock b/src/serious_python/example/searxng_example/ios/Podfile.lock new file mode 100644 index 00000000..60902061 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Podfile.lock @@ -0,0 +1,36 @@ +PODS: + - Flutter (1.0.0) + - package_info_plus (0.4.5): + - Flutter + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - serious_python_darwin (0.6.0): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - Flutter (from `Flutter`) + - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - serious_python_darwin (from `.symlinks/plugins/serious_python_darwin/darwin`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + package_info_plus: + :path: ".symlinks/plugins/package_info_plus/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" + serious_python_darwin: + :path: ".symlinks/plugins/serious_python_darwin/darwin" + +SPEC CHECKSUMS: + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 + path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + serious_python_darwin: d5c85ae2cd4539b52c71ea8ba8af357aa6311647 + +PODFILE CHECKSUM: 7be2f5f74864d463a8ad433546ed1de7e0f29aef + +COCOAPODS: 1.12.1 diff --git a/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.pbxproj b/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..c9cbbc0a --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,727 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 5B44F7E31402F865514A0858 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96528167AEF905EF935C1B41 /* Pods_Runner.framework */; }; + 6E599DE725A7D68A3238C543 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E1AD4EBDB62E03C336C3EE77 /* Pods_RunnerTests.framework */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0D382C05287807FE4CCE1EC4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 18C74EFCCAE277889ECB1AC4 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 362FE1DD228E14D42ECA2A89 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 8FDF69CA5955F9CAEB4BAD4C /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 96528167AEF905EF935C1B41 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 970D04A203EFCE2DE0A80099 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + AAF0F2A04A9A113E2FDEB3FE /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + E1AD4EBDB62E03C336C3EE77 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 865116BAEE02335192FC14A4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6E599DE725A7D68A3238C543 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5B44F7E31402F865514A0858 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 579CE9A32D94B33B7F5FA9C5 /* Pods */ = { + isa = PBXGroup; + children = ( + AAF0F2A04A9A113E2FDEB3FE /* Pods-Runner.debug.xcconfig */, + 18C74EFCCAE277889ECB1AC4 /* Pods-Runner.release.xcconfig */, + 0D382C05287807FE4CCE1EC4 /* Pods-Runner.profile.xcconfig */, + 970D04A203EFCE2DE0A80099 /* Pods-RunnerTests.debug.xcconfig */, + 8FDF69CA5955F9CAEB4BAD4C /* Pods-RunnerTests.release.xcconfig */, + 362FE1DD228E14D42ECA2A89 /* Pods-RunnerTests.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + 579CE9A32D94B33B7F5FA9C5 /* Pods */, + C81B3572AEA9583327A6C83F /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + C81B3572AEA9583327A6C83F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 96528167AEF905EF935C1B41 /* Pods_Runner.framework */, + E1AD4EBDB62E03C336C3EE77 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 22AE4D140A0649DD74A96896 /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + 865116BAEE02335192FC14A4 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 1EE0442A2A194508FAABE79B /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + D1EC2B1361F0757AC0569474 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1430; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 1EE0442A2A194508FAABE79B /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 22AE4D140A0649DD74A96896 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + D1EC2B1361F0757AC0569474 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = GXXRQJK434; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.flaskExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 970D04A203EFCE2DE0A80099 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flaskExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8FDF69CA5955F9CAEB4BAD4C /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flaskExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 362FE1DD228E14D42ECA2A89 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flaskExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = GXXRQJK434; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.flaskExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = GXXRQJK434; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.flaskExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..87131a09 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/serious_python/example/searxng_example/ios/Runner.xcworkspace/contents.xcworkspacedata b/src/serious_python/example/searxng_example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/src/serious_python/example/searxng_example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/src/serious_python/example/searxng_example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/src/serious_python/example/searxng_example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/src/serious_python/example/searxng_example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/src/serious_python/example/searxng_example/ios/Runner/AppDelegate.swift b/src/serious_python/example/searxng_example/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..70693e4a --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d36b1fab --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..ed2805b338a859294842640a4d2d68a80706037f GIT binary patch literal 10931 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 mk0oneEP)SDWGw7hsN~k)CYt4dQDFxbs5* z_&e@Hj)wtt(&JE<3Eq*D;_gQLvqXoKv=I*gWqM9C(Tvu0>=?hTbOp9!6k6AF;>f6| sS5%jGEE}TA9h)e`Yuiu87)l?o1NFcJg>BGA&Hw-a07*qoM6N<$f|zHTd;kCd literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..91d6fd138c1f9f2c1d938568d16b8b7f83b85b4f GIT binary patch literal 405 zcmV;G0c!q^fh|0ByOkyNP*?{{><+E*YEqC z-upwp_es3*FtqX7=J3|!?+tCM30#y5S&0i*hE}M!(EtDd$4Nv%R5;7+kVz7PFcbwd z0SOw32nsSd&wBssX{K^PC2>vJ>#p~!KNvqGG3)|f1T_)ydeh8$vDceZ>oNbH^|*hJ z*t?Yc*1`WB&W>VYVEzu)q#7;;VjO)t*b!>d#F3&qipF@Q+8b_C-7#+$#@oBHx$4O9 zQkki6KS*{^jFnj?zz1tFR;KLmkzvi{0Q?B3yy{-B0%m-Y-UFd^9x@@WUR#7vA2P-H zDZS5T=z6|Enwka7Yj4b8QD-*8McvGB1Eb^(m--8y)vIpx00000NkvXXu0mjf0-Dzu literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..37bde44dc36e9551f3def297b58eec0138d840b6 GIT binary patch literal 449 zcmV;y0Y3hTP)#`sys`0e@rq~QDG_WqRH``z>YTa&-)`2OMb{#?lT<@f&B^8E>1o?yxO zFSzysPl?|2{?p>_3|^o6{r^tG`0Mib-01NERFwlgX7v02(eM4t?)_23_~PvJC93D> z@AfCJ?k20~XPd)ZlfMdAkp@eB0YY{d5q}&2008+(L_t(Y$L-VE4uUWcK+#$ju~Ifc za6tuk{r~^72119Jlni|!MD8QWN!uwUQ&ZpUIV{6jZzeODhUGYGLF=Qe+p>;^^)>d) zH7pzGjuM>Jnezy3`@G2r?{~a!Fj;`+8R`uN@LQxfhx0qi_xx6NwPC=mXf}00000NkvXXu0mjf9Pj4( literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..9fccf0f5060e91088c8ef2fe44a45b33816cb985 GIT binary patch literal 281 zcmV+!0p|XRP)hnCz2Ba@RH&`m!pgy?n@#@AuLYB&}Q)FGY`?v zcft0!vht0Z@M&ZeN fCWXh75gzRTXR8EE3oN&600000NkvXXu0mjfzqf_H literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2b94f80aaf54871e1c9be120423bc7340bdb0154 GIT binary patch literal 461 zcmV;;0W$uHP)2SjPCh)aA9#;(Vyea-zr> zdaMCXivU4%>iGV;=={^-?sLQGb)?A{hr$_!z8HbH7kH=vM0x-*R~t>;jsO4v^GQTO zR7l6|(&r9>FcgO2dg?%>;=sK?5%;?Pn^T7LL?Y$@5u?06NuIR*0?Yf$Hf5Afk+lM< z^ch*jvO$sU*m9J?JI7eIGFV6Po+x1xwLhPT=%$a$4GUhJivfvwTC=5q0*0a?rGHofGy3=9BJ7u1%qtQ*NZEm zViNCc*$(t9ajON$s9Ws;MYKzN?jV6R6TH`8dB5KcU62iO+lIoL00000NkvXXu0mjf DaIN!> literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..638ffdb4eb6da223ce7d75c0f06c72b4f7e8889a GIT binary patch literal 703 zcmV;w0zmzVP)0mMl}K~z}7?bK^ifQQhG7HeY|fvL lid#^Ok4NAXIXSt1xpx7IC@PekH?;r&002ovPDHLkV1h^fh|0ByOkyNP*?{{><+E*YEqC z-upwp_es3*FtqX7=J3|!?+tCM30#y5S&0i*hE}M!(EtDd$4Nv%R5;7+kVz7PFcbwd z0SOw32nsSd&wBssX{K^PC2>vJ>#p~!KNvqGG3)|f1T_)ydeh8$vDceZ>oNbH^|*hJ z*t?Yc*1`WB&W>VYVEzu)q#7;;VjO)t*b!>d#F3&qipF@Q+8b_C-7#+$#@oBHx$4O9 zQkki6KS*{^jFnj?zz1tFR;KLmkzvi{0Q?B3yy{-B0%m-Y-UFd^9x@@WUR#7vA2P-H zDZS5T=z6|Enwka7Yj4b8QD-*8McvGB1Eb^(m--8y)vIpx00000NkvXXu0mjf0-Dzu literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c61e3f4dc6d7f463db405175a39922192ab33eab GIT binary patch literal 585 zcmV-P0=E5$P)iGV}?EQ7n`Et+su*=}6;rk$**8x?Q@caMe_x@qY_%68i167j& zPmBXNU$Er-fz0x@99;S!saXLL-2RbR#!*_ccBOmD@cDnEWn*EQ{|D#8`BKw;77!MBj5X5)uvt~Gl zdiXoyYyOoB`cMxFcSsMnMGsm=^_VB|(LHDx)njg1R@|zG!m0Flup~*`s)r)@?J<

2)VCrlsy1a`F?fd2=SFY6fy159Mz+`QT9LxGONzhBZq{1lGJ?D*(PEbldQUL zF$=x1z&0)``?iZPw7oI9QTg(3q3uN+GcL2z_wt;}lWl42q|CmM!XKYBc2H(o6rZ`& zmEdLe#a6CUz-88@O#zpQHZ>n!MyzeJ5xtsh1j~p>6XIpw?as@bYka&h3{GGMgP|2) X<^Uk;aI9Oq00000NkvXXu0mjfBWg5F literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..be12f278a6f7a363ccd01e1892191f74654793f2 GIT binary patch literal 861 zcmV-j1ETziP)_}lajh!s zu5hWVuDa@~tFF2*ORaaeg)m8V-y4K9h3c5GXZ6)38#b&?1`CENF_55WAte{&< z>TJz-r`B3Iw-?WN-;~_H{iU{GPUF9J`R^qMU=7?FuGZpkF&F1G^Q@M69EXd!Zr*w1 z2<3%b3oxhrC=PwxUtab-FUdakikDe8g3dDcir+AP-nh%V^xRl{W^Ug4Zudb&XkL;z zx3#*CvW!bt`xn<-yQ^K2OMA5}xn7=B=6DX7ylB$bCP z);(%(xYZL1VEYiu7sPsHFq nzbF^XMl-XZX_}^K|5M)qhD2TMK-=pm00000NkvXXu0mjfeRaqY literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..be12f278a6f7a363ccd01e1892191f74654793f2 GIT binary patch literal 861 zcmV-j1ETziP)_}lajh!s zu5hWVuDa@~tFF2*ORaaeg)m8V-y4K9h3c5GXZ6)38#b&?1`CENF_55WAte{&< z>TJz-r`B3Iw-?WN-;~_H{iU{GPUF9J`R^qMU=7?FuGZpkF&F1G^Q@M69EXd!Zr*w1 z2<3%b3oxhrC=PwxUtab-FUdakikDe8g3dDcir+AP-nh%V^xRl{W^Ug4Zudb&XkL;z zx3#*CvW!bt`xn<-yQ^K2OMA5}xn7=B=6DX7ylB$bCP z);(%(xYZL1VEYiu7sPsHFq nzbF^XMl-XZX_}^K|5M)qhD2TMK-=pm00000NkvXXu0mjfeRaqY literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e409f2f7788e8258a5aa4c317521bc5ab3416c89 GIT binary patch literal 1673 zcmV;426p+0P)Y?fd{!nE+Lo((wHUTb+Q@`6#pUD6sD; zy#6e=_Nd|en%w&M`~Ax7{C}#<)$#qT#@(pI+yPXT07;UQ+WIZG_5o0j0ZobmN`n9{ zQ_t@F&hGrq?fj70`TR$2T#*AweE>Ub09v4>;QIg_I^_2L ztK$20(D{zn_^HL*3Rj70%=tLH_b#{gK7g|TB112~|HSJ2l-v4y(fQow@Fl9|nYz}8 zug`j(zVw*u0RR96H%UZ6RCwC$+j(;mF&GB$gx!$cC0wqeg2fZXt7=O<@jhDb`}+Q0 z#5c(z>av@(vcnrD&mZmdVCFaPgyd-`#K*_S$H&LV$H&LV$H&LV2Sw_ZA$THUVjD(~ zgvI3Kv)yCH?Cv&SkeHwdOUT7=&~2O2?Y{lY1ddUI`2_8TT!nH<z#Lne zF`X%Le|F96ZWpC%*y~(0yVyl3o-QhEyC_H1MeELXQR-N)gLBZi{tUg&X0O9#cCOdC zX!c#SvgEs{bG^>hF1n7r&YS-$Vx8|radlC63j7aDDIx{dZl^-u)&qKP!qC^RMF(PhHK z^33eOuhHu{hoSl0KSVE+czI?a$ftvLQD$eR(UQ&b34Oj1g+}th&0L$wGQ&VUpdq(0 z=hsGLG3Rc$WHTg|YF>62@?tZk7Uq-rwNbq~*G28kJnBZ;T!H!-sP}U(TDP7vnClgo zfxwiSTXs>Q&0%P1W<;eLb;xacoxPb?Y6gaodq|$a(V8_xsk!-HRGZ;fZP$h%RYj>` ze8yg<%{=5Qp0iG@)fVQ{ZzCIXXfRi#)?GAbK2jS*+<10tbLC-L&5L`THm7N=5!v)Q zgSiUz!n0eOYoO)_?V?qw%giG%r=@Cc=%SUVDX7CD^9=yYl&p{nx~NrCHJkOUtM8)r zosUKZ=68x)Hfvr{7d5Nf1$*7xT)3{Q>Z0bev3cR|y-sNJ4Y20b=3ZBQG?%djW?+`9 z`KruHoHy&eZjqWJn6qN$%=%0zP@^#ald&?709l}3{n}8;cO)*)T8~uk^)KEOM+F)+AI>Y`e zP$PIFuu==9E-`OPbnDbc|0)^xP^m`+=GW8BO)yJ!f5Qc}G(Wj}SEB>1?)30s zXx`eIp|u*-v++8pbLPhnwzq$yk*SGRkJ6lZGEr!$4)Cetf7M`~?%aF)Ct9of*iLj% z&&~IDrWtxuqqTYity-EtJa{q%^!65*C3&vCLK0N!G@Y5B?*RJV1k6f2S9cJqM>DfT zPqu~r0T-(=HPyQOTjtyS57SBO>C-@q z7pZYI)i@z9A3q2{JOpxKvZjiqJ>V*$;pmlqPGcSlZK=kW1HE9RpgQ=vZdW$e58! zhs|nK{TkE)W*wBO(X}T~6R8dyQ}?90iGWh`u^4O{#?iSsKwj>R+($e`7XEi08W)u#P?j1z5-aC07#PD^ZggF^#DeLEod`7jPUv_q{^9rH z8t(W3zadsGRj{B^DtRw_u=#~ThmChM_SU^P*n6Ux%XQWpz{Xq4t|O{DqGhdzkwewO z{ROh#z;+_Sik4>xs##y6xyFnp>Y{otv0WXcX2G(78tsU$a2bm< zL33HK?Rrfq3**_{$g-o~t7VIiC(5&VIcwwZs+im&Ey`PSbEr+eBW=3DX&?ip>@#l{a@-@W_1r*EprMQTK%nVCz*;iSnH1vLrYy7?Dj{a zZqhQd6tzX%(Trn+)HNF}%-F{rr=m*0{=a;s#YDL00000NkvXXu0mjf!+nk;B!uRL){b9-YNx}D?-TM6f{zbp{ z`~3X}Tb%$&k_1|u0Hi1+#X{rLA{m%$Kamk?i! z03AC38#YRsOM{_^QvLw*iJ>7=~dOhGB>zGs6(z11VuB65JyI4j)*Vf4>Fp5fbhf zrflR3xdU(>riheR&O(sQA5B68j)|o93e1Gr{JlxYfJ@LTB3I?K5>#^} z>Ls{e*O6lk&cNPR2=I=#>g9wp4IUiKWZU*nra%8XRM`ec%3_8fE9kfX&c{Kp*K zcww4_Y)GhISIx%X69%ub)13*9-JQGe-f^d2y6}Q^}3_Q_8Pr;DZHn-+4JglJKL?M zRzkdQjoqE|Zg;=c&@NZhJojvU=e*Nyrf1SRM8tQ`t{)-XFW3|MzCkLnfZHeN+{A#^TwHZ+!{p9 zq?%c*%w{Z<=GMTm8KyaBqw(Y0Cy2orXm)b;<)MwUwa*ZNd*TsZ4*@(OBaMvY n0P0_TfMFPhVHk#CZX3S=^^2mI>Ux-D00000NkvXXu0mjf`r&}Z literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/src/serious_python/example/searxng_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..889cb0a49f57c4fc8f45503c28693932be1b1b1c GIT binary patch literal 1417 zcmV;41$O$0P)AJ3O2PMD$oLqr^>U%d=l1<#%J_z@&PKrZF1Ysc`u@@H{E623uH*YZ zz4t4=|0lBYn%w#&wDkc-ess_I0aTVw!}y4=&jC`C0#1noG*fwc-8!#-TGX}_?g)C zZq4{k!uZ_g@DrQdoW0kIu+W69&uN^)W|_hOJ&U7ve8m6&1X4*vK~#9!?c8fq6EPG9 z;1f34-E6VicC}ss3tm=`7Hew-Me%;u|Nm=Dw=0L4lw@%_dlDwEqa(wYXOg^!1ZIGc zkdTm&kdTm&kdTm&kSa2%ksPQap;iQtMo2h%cf*=@$F$Hqfo|Gw{mWi!Z=NseZ~0M` zYdeF4)F~u%S&MOVvh@LwGkGgz#$@TnRbplg_jxPhCM9R-x?)P8i%9HD<^;1_lNm$p zP%;ysi-_k~o{yoG8o-KdZ+Zz1OT4Jo{ZAiRanxq1w|8A$TNPqy$D za<=K7F#WlDSeV?8f#lB(>8dy1Ep~k%aVIKtnSU;n%Nh~QzJ<8n^qK1^KF)-u<7qPy$=;)0>vuWuK2hQhswLf!9yg`88u&eBD-a@KE*ET;g z8m11_n~uy|Ydaai+0r?{Fs~*;8@PHHpw&Nm(=pik=2sJ8 zA{XY>L?{6hV`n0ifQhj%_10%DGf(Fzcbr+Z-tA34g*w2LI#Y+H>(opEM_e(@dARfb z2qaJ@fo(hU!MEEWV<3%y54UX0x5MHm2wJEBcyw!R)65*VuiPVt3L{i8$K!SsxdDB1 z3e}h|#znimfX4XFr-+nlMNQ0I1?^Q(${ z4-OViN1!6d)+2K|9S)V#DX6HR$b2@N72{KX{Kyz$;$sCPl(_*-P2IwBrF(ZT*S+XLJGepiJICy=i^!UF#z|GlmUwdGZ5508y|^_WXGX zf*2~``>)$e@)G}}{`~$5L_3eI_u + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/serious_python/example/searxng_example/ios/Runner/Base.lproj/Main.storyboard b/src/serious_python/example/searxng_example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/serious_python/example/searxng_example/ios/Runner/Info.plist b/src/serious_python/example/searxng_example/ios/Runner/Info.plist new file mode 100644 index 00000000..c2f15c6e --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Flask Example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + searxng_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/src/serious_python/example/searxng_example/ios/Runner/Runner-Bridging-Header.h b/src/serious_python/example/searxng_example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..308a2a56 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/src/serious_python/example/searxng_example/ios/RunnerTests/RunnerTests.swift b/src/serious_python/example/searxng_example/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 00000000..86a7c3b1 --- /dev/null +++ b/src/serious_python/example/searxng_example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/src/serious_python/example/searxng_example/lib/main.dart b/src/serious_python/example/searxng_example/lib/main.dart new file mode 100644 index 00000000..33a0dafa --- /dev/null +++ b/src/serious_python/example/searxng_example/lib/main.dart @@ -0,0 +1,125 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:serious_python/serious_python.dart'; + +void main() { + startPython(); + runApp(const MyApp()); +} + +void startPython() async { + SeriousPython.run("app/app.zip", environmentVariables: {"a": "1", "b": "2"}); +} + +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + late TextEditingController _controller; + String? _result; + + @override + void initState() { + super.initState(); + _controller = TextEditingController(); + getServiceResult(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + Future getServiceResult() async { + while (true) { + try { + var response = await http.get(Uri.parse("http://127.0.0.1:55001")); + setState(() { + _result = response.body; + }); + return; + } catch (_) { + await Future.delayed(const Duration(milliseconds: 200)); + } + } + } + + @override + Widget build(BuildContext context) { + Widget? result; + if (_result != null) { + result = Text(_result!); + } else { + result = const CircularProgressIndicator(); + } + + return MaterialApp( + theme: ThemeData(useMaterial3: true), + home: Scaffold( + appBar: AppBar( + title: const Text('Python REPL'), + ), + body: SafeArea( + child: Column(children: [ + Expanded( + child: Center( + child: result, + ), + ), + Container( + padding: const EdgeInsets.all(5), + child: Row( + children: [ + Expanded( + child: TextFormField( + controller: _controller, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: 'Enter Python code', + ), + smartQuotesType: SmartQuotesType.disabled, + smartDashesType: SmartDashesType.disabled, + keyboardType: TextInputType.multiline, + minLines: 1, + maxLines: 10, + enabled: _result != null, + )), + const SizedBox( + width: 8, + ), + ElevatedButton( + onPressed: _result != null + ? () { + setState(() { + _result = null; + }); + http + .post( + Uri.parse( + "http://127.0.0.1:55001/python"), + headers: { + 'Content-Type': 'application/json' + }, + body: json.encode( + {"command": _controller.text})) + .then((resp) => setState(() { + _controller.text = ""; + _result = resp.body; + })); + } + : null, + child: const Text("Run")) + ], + ), + ) + ]))), + ); + } +} diff --git a/src/serious_python/example/searxng_example/linux/.gitignore b/src/serious_python/example/searxng_example/linux/.gitignore new file mode 100644 index 00000000..d3896c98 --- /dev/null +++ b/src/serious_python/example/searxng_example/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/src/serious_python/example/searxng_example/linux/CMakeLists.txt b/src/serious_python/example/searxng_example/linux/CMakeLists.txt new file mode 100644 index 00000000..9f6ed219 --- /dev/null +++ b/src/serious_python/example/searxng_example/linux/CMakeLists.txt @@ -0,0 +1,139 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "searxng_example") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "com.example.searxng_example") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# not the value here, or `flutter run` will no longer work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/src/serious_python/example/searxng_example/linux/flutter/CMakeLists.txt b/src/serious_python/example/searxng_example/linux/flutter/CMakeLists.txt new file mode 100644 index 00000000..d5bd0164 --- /dev/null +++ b/src/serious_python/example/searxng_example/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/src/serious_python/example/searxng_example/linux/flutter/generated_plugin_registrant.cc b/src/serious_python/example/searxng_example/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 00000000..4dbcd894 --- /dev/null +++ b/src/serious_python/example/searxng_example/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) serious_python_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "SeriousPythonLinuxPlugin"); + serious_python_linux_plugin_register_with_registrar(serious_python_linux_registrar); +} diff --git a/src/serious_python/example/searxng_example/linux/flutter/generated_plugin_registrant.h b/src/serious_python/example/searxng_example/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 00000000..e0f0a47b --- /dev/null +++ b/src/serious_python/example/searxng_example/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/src/serious_python/example/searxng_example/linux/flutter/generated_plugins.cmake b/src/serious_python/example/searxng_example/linux/flutter/generated_plugins.cmake new file mode 100644 index 00000000..6d77107e --- /dev/null +++ b/src/serious_python/example/searxng_example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + serious_python_linux +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/src/serious_python/example/searxng_example/linux/main.cc b/src/serious_python/example/searxng_example/linux/main.cc new file mode 100644 index 00000000..e7c5c543 --- /dev/null +++ b/src/serious_python/example/searxng_example/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/src/serious_python/example/searxng_example/linux/my_application.cc b/src/serious_python/example/searxng_example/linux/my_application.cc new file mode 100644 index 00000000..ba2ab011 --- /dev/null +++ b/src/serious_python/example/searxng_example/linux/my_application.cc @@ -0,0 +1,104 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "searxng_example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "searxng_example"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/src/serious_python/example/searxng_example/linux/my_application.h b/src/serious_python/example/searxng_example/linux/my_application.h new file mode 100644 index 00000000..72271d5e --- /dev/null +++ b/src/serious_python/example/searxng_example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/src/serious_python/example/searxng_example/macos/.gitignore b/src/serious_python/example/searxng_example/macos/.gitignore new file mode 100644 index 00000000..746adbb6 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/src/serious_python/example/searxng_example/macos/Flutter/Flutter-Debug.xcconfig b/src/serious_python/example/searxng_example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 00000000..4b81f9b2 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/src/serious_python/example/searxng_example/macos/Flutter/Flutter-Release.xcconfig b/src/serious_python/example/searxng_example/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 00000000..5caa9d15 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/src/serious_python/example/searxng_example/macos/Flutter/GeneratedPluginRegistrant.swift b/src/serious_python/example/searxng_example/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 00000000..6bcae484 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,14 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import path_provider_foundation +import serious_python_darwin + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SeriousPythonPlugin.register(with: registry.registrar(forPlugin: "SeriousPythonPlugin")) +} diff --git a/src/serious_python/example/searxng_example/macos/Podfile b/src/serious_python/example/searxng_example/macos/Podfile new file mode 100644 index 00000000..b52666a1 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Podfile @@ -0,0 +1,43 @@ +platform :osx, '10.15' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/src/serious_python/example/searxng_example/macos/Podfile.lock b/src/serious_python/example/searxng_example/macos/Podfile.lock new file mode 100644 index 00000000..29066625 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Podfile.lock @@ -0,0 +1,36 @@ +PODS: + - FlutterMacOS (1.0.0) + - package_info_plus (0.0.1): + - FlutterMacOS + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - serious_python_darwin (0.7.0): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - FlutterMacOS (from `Flutter/ephemeral`) + - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) + - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) + - serious_python_darwin (from `Flutter/ephemeral/.symlinks/plugins/serious_python_darwin/darwin`) + +EXTERNAL SOURCES: + FlutterMacOS: + :path: Flutter/ephemeral + package_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos + path_provider_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin + serious_python_darwin: + :path: Flutter/ephemeral/.symlinks/plugins/serious_python_darwin/darwin + +SPEC CHECKSUMS: + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce + path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + serious_python_darwin: 0a8c46a529057f91064a327d9c4037e773eef339 + +PODFILE CHECKSUM: 9ebaf0ce3d369aaa26a9ea0e159195ed94724cf3 + +COCOAPODS: 1.14.3 diff --git a/src/serious_python/example/searxng_example/macos/Runner.xcodeproj/project.pbxproj b/src/serious_python/example/searxng_example/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..18e78875 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,791 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 70DD4839623CB676776399F3 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 548A240DA134EA4087E0F195 /* Pods_RunnerTests.framework */; }; + DDFC9F9001D319D95A5CF60C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D812C755E14C4E5DB444838D /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2629974C32C79086ADA39ADC /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 27097D4FAA1E921277A516D2 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* searxng_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = searxng_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 3A957693B9A4702AF65EC727 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 548A240DA134EA4087E0F195 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6E578E07C23DB3D3504885B2 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 8495C9548FCC5F61A98535B3 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + D6193355C1ED786CF0CB5585 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + D812C755E14C4E5DB444838D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 70DD4839623CB676776399F3 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DDFC9F9001D319D95A5CF60C /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + CF3A62181C2613D4F67718E4 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* searxng_example.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + CF3A62181C2613D4F67718E4 /* Pods */ = { + isa = PBXGroup; + children = ( + 2629974C32C79086ADA39ADC /* Pods-Runner.debug.xcconfig */, + 8495C9548FCC5F61A98535B3 /* Pods-Runner.release.xcconfig */, + D6193355C1ED786CF0CB5585 /* Pods-Runner.profile.xcconfig */, + 3A957693B9A4702AF65EC727 /* Pods-RunnerTests.debug.xcconfig */, + 6E578E07C23DB3D3504885B2 /* Pods-RunnerTests.release.xcconfig */, + 27097D4FAA1E921277A516D2 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + D812C755E14C4E5DB444838D /* Pods_Runner.framework */, + 548A240DA134EA4087E0F195 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 1814E9C1CD1BD4E59951D766 /* [CP] Check Pods Manifest.lock */, + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 88C1B0D60BC70E03B6C3518B /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + 590DD7A4F3044A9A023D543F /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* searxng_example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1430; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 1814E9C1CD1BD4E59951D766 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + 590DD7A4F3044A9A023D543F /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 88C1B0D60BC70E03B6C3518B /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3A957693B9A4702AF65EC727 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flaskExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/searxng_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/searxng_example"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6E578E07C23DB3D3504885B2 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flaskExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/searxng_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/searxng_example"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 27097D4FAA1E921277A516D2 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flaskExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/searxng_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/searxng_example"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/src/serious_python/example/searxng_example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/src/serious_python/example/searxng_example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/src/serious_python/example/searxng_example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/src/serious_python/example/searxng_example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..110ca60a --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/serious_python/example/searxng_example/macos/Runner.xcworkspace/contents.xcworkspacedata b/src/serious_python/example/searxng_example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/src/serious_python/example/searxng_example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/src/serious_python/example/searxng_example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/src/serious_python/example/searxng_example/macos/Runner/AppDelegate.swift b/src/serious_python/example/searxng_example/macos/Runner/AppDelegate.swift new file mode 100644 index 00000000..d53ef643 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..a2ec33f1 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..38938ac42138911631ec9c97dfed03ffc6977102 GIT binary patch literal 102992 zcmeEugvA&VBlLAgz!B0 z0;lH<0$=c+Jy5<4De9qH1wXlCsi$J4t`6Y=-xEUcLT!Kj03P@m4fqcNIhTnCIS0Pt zfqx;H&_DkRgJhoj_x;&74ot4mLm+Yxl{@l}yzn+AFVxcw`mY?L8mqS6<=4GbzfI2c z!lRUE-t64>0*>>tyK-V9%~vI(T*xnZv76}GzY>MLm1;Fam&F|U)5WTM?@38YJXA5+ z7`eG?wKQLPg?9GBHx9(*2v%m;Shgep&jWOqhYHt|H*`b0aPCkpUrYhLJ8wk&3t?$R^Czy zJ7|27*$LC^O3Jx{s^9IgO}Ssp7=Ew6ROQ+2FwO@)&vZ6~~a!O?uQ?|@E$-mJRsTo~tC zX99mp60kR*>ARaKV7#V2US_F^9eEPHAClpVsyX=@Ow=$-ZQ_*`u=hjRw;7396l`#( ziB!VAWR2R+aTu>GY&84wd@Mq+Q7rc(=lXJ=>Rom|PqiX)$_w~Q6G zWyVj-)S<1Gbx$>NEPZ{}MiFVcXE)eJ8y} z&s)b+>V{m?oymT(x%~G0xt;5tH5}86w#Sac3w6@`)BDMO!?{(ClWX0H{$>UTVPp4| z=@+v(Pw%N8P&(;R$6!BloW2$nIMr1@5OmTzkaqGPJ+w-Q$Ch)P=7L`?5;X>O*!n4O zoHoYYT)a|^(Z`&AU|vQD3(&`eWC!)i0vLJQyQNC`$s$THVF|T?Os404WO7U{f%=?F zVXYc32${6F@e2FK!@{)}4CmczXl}9TzAJbx!_IkIxvjnP^0{;8lrMa}j`l1lKt9T$ z7i{(s_cp>EF(DvOLZ-f6s1I*j@8Z@4Tce|3VLp3t=b0uV^!V{}OjIM+MSz2tV0;l3 zm*yJUs!`LdKub?D=2ZH1bn80t`A=U6@L&=b`XGHOFOLcLLJ^*P)$2ud_4#BTH<%TN z^U*%|#=Hm0o$YN8#IK2)XgtvA2>afS&OMA4Opui!{C)kHv?k=;2S71~!6`v0sCDu1 znA=v&%b>OnlcF}wK6(8>bvPm^1d26Ioc7v$Cnp-bQF)o0S?ewy4dh~tej5cekMM;y zn&3n9TJ_#DX?YEnA=PZ0E}P%`g_&=UT;)IfxlDW$DSH<3H4;#+{VC03ytX%cc}&_o z$3-sWb6p@zn1l<;2>T=;cTR4wN@#IiIZ&U{AMb4fFCK9Xd8Ypibvxzr&u9gB4#t=Z zzT7F?(9sJ%`>!f;qHLDv)_H1pd|EW2xE<~4Ijxz^JB?J)mGK`6oMO*hCLa>Yv5dk5FP>#H$$STIK_ty((qRg7AbvMmbZ_k)Yhu2^xncxyVe-WJ}B&f{W9VGwA`*BIv z-nQ7F<@Ws2q4sk@CW2KcQ^D9F&v0;`ew!U3_XtmX>nI9?tr5P6336jSN-D_pyy&&e zQfN)2_el8STNpDGpYm;<7KJd}f(XpPZ%1VdzY4}po+ZzexGDdR@DA16JhM9{LHL*DnD_&e zu=fL`8fM+shX%8^aO5i6-RQ&X#{M&)7ThzF^i0&!I5l#ta*d>!K`l|AHd80RoPj^TP`+#b zFgXQ7-~!BQQ&(p-u@Mv0p9|2bEL}k#)-JqZ<@f_&Gb^B`uL&;592GkGuU{9}?H9lk zJ|E}t@XgK*!mdvrN6!iaJe6@h?BXS;LN6ce?~_S+(wgwn=!9fKX$NDQ+t8zsrk_ zmO|gfrc7g&?xVL;3>OY6qZd-7A1MD>vxA+9RB1|J`F>RgZ#0tI80JCXcDWDwr49?#40x0Znc9z z$O!iYgsi7y0^)B+hhe2~nZFwEWI#PfLm zF`1{cQ4rlAbJ!g-4R!)b*ol!@k4zRN@T^DN+Ge#sTQs8E`g9_6j`fcZ29w)J3vbsV zF`YKiB?pVml?muZT>v_WLB1J;pUuOMw`0m2(C=$fLQ4WkJ1? znbA%I4 zAix{14VvX+0Y39I;T?*%yJ^GW$cZIW*{%BBDG?!|?ND+}*2hMCA%8rENy{&g)6{!0 zo_A^|%F~|2+YXU{2tmv_DZ9Q!fVZUubs@)xDuOE+Ck`LoS}67y)Yipz%*@PGu@5Ly zT%TXK@b8^n4upH*j+cwEC{N_6>MB(xWdJ;TS~mUeyF1V2Uc;6ig@?z9qo2z`q0buU zJty6Dv9FaG@?`h=6k3T%N#Uv{%bri6t7Q29?!GvzvEH&XfiwU(ot{=ukP{cVTBD`` zx)4{*$FK{56Zn|vt=b8c=`aCCU0od;_y|+nE*)y|XWKv!K#k`u)8qtfhst8GLqX6Q zR;I*4xp(?RN4$6Sb2WVk!5slid@14nP1E6&yfQ2orjnH2eFKZee_}#QB9Q*{a0@tu z@9V<%52d(D+{U9WwUTY?#y!6Cg@=$r$*kv4-{~-M;+70-7)QKh&GgG!FAEhpd@f&Iv9ugg%#?%TI*=y&PWAhR zPHEK}Wt}(^9-!*(Vn*&MwN21#%0KI6azS0wy*@}$oGg8|8z$k?FI!+#QdYK05p_DS z?u9q5X7q|dgQ;g!jgHjsoR=g#LN>eCtQF_4XaiMkc350N^GVk~zD*|AMCoM(CbnYi z#Inp`MXD}?efPF0_At6`{pKqND4a_A((zR z6GZANDmR4wkQff}gnamV?*sQmm^O}f%d1tAV`?u))YcSUbdvj0^XEUAD&vCMD-f4Y zLT=U2&YVsV_gNbvpSSGm=J4p<34e4M5Acl7$5D=!P@MbYpIl*018951v&B&ea%L35 zKKj_=SrmA=E@t!Fc=*qG0Hb}unGhD$e=ZS>&tcGeUX0809A;~RSZkKwc=p{fuMVXE zk0Ngt0ytfbRE@Bkf5Lb=qUZ|239|ED(f`+|T*#&YO{tx4+;B7}9DT#{Tpaw#!NUun zEi)=TYC0rx(MXs1?9h)MlH-$e=ZM!Qj))Yo1A^3h@ zHR0OXzu1`wL_ET2u8|Rx|GN@do0?pYreGbqgSS`eWaT}Odqq>q#Q=4_uVQl7z*DT; z?==}z9x4oh90taUtjOP^XJ~c>=@Ma35@gx zyUnrB@EdR(W)jaBTK{aE#6^fU@FzYdzUb!_Har*AkAlY^4_5`lTe~#P@XB*axn{D`~)XP^MJfa;yAqQi$ARsNX30d$xBZP~29sXyciCKF24j zKm&CTj^Uc2VsHO}XJB3C#`i!?cn_UU9X7&U8Av`Z_JzX6TInloUl6kKG|@xCT*>uc z%4sbki{gR(^)0nM zW@ctH-RR_|#0>v~Q6NGI5io{s;o>ERw2Y8wcPZK|0-#8;yb?@pa`f>LPWMsiOx(W( z5EAGCb!G4i6NYxhDj@(785t8esFGkJPJ6SlyVsPN5=zH|)e}~w|0)#NMUWo=z!wcQc36xXa_;9%iZepxYdNCmqTxL}4@F5RMz9aug zb@p>FfS5R#o+vSIes)7m(D(bm8c8k7`Ff+eqd0763 z5OH7|)GvwUVW}Am@9@;3c`6WIhXS* z8LdM$d);Sl1s0ueE``yQ4n1avEnUp5_MSA&gl_C|)QF;LJ+V7Y(pN{%7U>I>5&mq^{s#VfKjik1 z<&D20)L)P(62gf@xfdJm76T{6aCT3;7v3W^9wUA^tbIC&^N32Ru2)Pm3@_|Q@-dz3 zxTQi`Xl0=XA6<>fWgj1e3ON+ znt+jZhyXWu=B?)9UJeOCBVP%3N(leDCBl~oDWVx|U1RsbJx%z@z}5g^lP-%bUOHY( zg$?k{nlgaDlz8}aZ~wP%cOKF}aCK^?W3qH{6o2iP1?)Tl!Pe2qFcL>gE9&_3Bstw~ zJR=2>7F0KIRVlL&OwtvL=2kBez9psR#b`ldNKnLk~?CRC4M}xdY z)pLx%aRzW)D&h%sdl@`R*hMu%f*56ZXJ;Llod~uw-YdV1S3J=M_bXr$J()NTH%rRH zbmG~{8F0w5#{<(S8H1sJ%GjBPQ0uWV`PLUDIq)_bgi?2`^3q-lrJ~l z0aP{a7ard2T;R<5t1dtS-C#?-8SsJYt#rF}g7w>98)K}YN4=v1?S!QX2H^D{I5l?N z*kVw#D#F;Aevrk@%bJLah#bgTCtM-_YoSb8d>Um&|Ghy?S?r!J{J7Ip!)dfkkuqno z7hW`#ArU9>211JW>f6s@qGM7nlXD0i92iswrFnVW{*#Qqbg(}ge%I8jrCW3wbLz^8 zIQ5ZJAB6X$2WZ^QiUU($oNKvdf-MmEEg$1FQj*o^w%U*9y#@fx;@5ikMA=^al}0m& z+Sc)=IgFjBc}Qn-E@$>4iCn@psS#pNv85Vji>BcwNDxk*Z#-%d4A5pc@w^Y$(z^Fo zjR|K3LkU1_l=tE^WkDQUC5t(J6l$`LbX%+GxqTeDMUVi5edI2F+dI#7qz-PYdOpgs z+iEwOD2B7_4@U#DgPbhUD`U4Gif|-I7OQv>o>QpIYU+d3_Dcu(pp)&bCy)wO`Nou- zyKBsNayV4g=)SiQtBC_F2D7#YlY;)W1q7;3_;Y>#Nw4HqJ-(*Q@xnB2MOpUZ`o)>_ zY3tYg{ahvBauie@!F@((;cyD0=higcz5zI7O| zMJzhu9Aq-_`I(n-KirYAL?re^9RcDAhltR`VK|~BNZFW_<8aD%Yk6VDRr_eI>#y7i z36z3;h(HymfdT^(00r{Rg)D@(eIWXS$~igjO6_FveO=rw{$jz`IymHBwqS#;mzUSW zcF_MlZZF0STWed@$dnMFFq;rl9dX(AOMe+0)Id*tJ48HIcOE zax(%>fCR7bJ1_tK(J-Pm1-#-oU5|`qUj{_lw4o2`7^%*>aRn3`Pb?HdDF!BwH=AaH zUHfdLKvw4zAJi7|-}N2>#lLbD1c0VzbjsbUC7jZO6S3GQeOP7t!k+^S;0y=n+-ekF zQ%FMxu$X8%b<{*4BP4#~2AZG;ed)ipW(WU#am`Y4aRvxyh9EO(^QUDF%RpoMD;;An zl0P}kt}K=Z$(?EZawey(g}{$ZJ@UW2^($eUalI4fz3j>R-Nhu6lfJ`}5QroosMgqi z_XG^S4^BqkC??X3LpO`F2*N<9eB>i;lY0N#t60vz_hf~S$rul}dnWQ+UcG3xe4;~8 zQu2(A@4h%_6P_v+NvgKV*~uVzV@GW9w8yx^Lv#nS*zHv?{$JclF0&09G;HiSIXqls zypAMl>Ml1Fbb;vv*+#5ZKY9`|CkiF18srBm$!u*wOU` z0aLgrq-t)9gu3+V0=GQ)^W@+7foTDPFi;XADf_RTy$s{v;Aq5x z)O2#1vS|(P@?*2tJfL!|m0dX6$Y&l8d>3C%z3F^7=_v@Vf&BTm$afYe?XdHUpAons z2#%%N9UqYT&U==PgGHC!*C*x9!2 z<0l9hpHQRegw|;`ka~Ll2pIupV#wh15stpLNU{#KHz+8<{ufPy;2{x>cpJQ?#~n3j zH6gez#PdfcQ8>ykM3oD)`UO#g7kuMAYau2IP5Z;9vfG2j0sDR?r_}PV|HfM%KQ>)f zrrU`e%-21gCY%|(mdax2|265GSrSNzxORt#dg|bupIs)0BJ=X{0`ZBc{8+uTbN(y( zGYHiJP|q^z%R+Bp7=D4ejKkkqcC`*?bF=N^Mm{%?Eh%F zXApu5`u_cUQWL+O7S?`gubdvTlJuVWhnLR+u8i5Rg>X#V-N1imt|cZ9i zZHs&VRb^c8i|SCdzGux)I2A%S^d&9lI;Ad{dgdHcOkAxbH`I>Ch8rtgx^E3nOsjq< zi1^!a2gz+jQbc8rW`dN#(*C8+PVZi>J0ZYnlMKK1U6tv~lp+tl@txm{1JQ#C7P**U z$YHVEDDz+19aug6SxOuyYo}vHgKJ1(dux{;U@|3?GCn>ke=7`mtPPIW%H82E1<4KjlviQFspswS`weM2 z3>Z-!U0~V}_xJ(yZ@0huP>z8v;4q9c-Np%4Qu}UDuwN~?`X+fvWb%Diw%B)wx+gyI zfM~<2`nh2f-%WytYOx>xrFx*^zyfuh-3}pzA2rW|&5*sdD-ZaHKELpo{qZ$Ct`-?C ze@?EZstUebt^^^br8aVwf9BI2q z`=A9WTyDM^^H5Xox67`>pgRcy=0yYMlP~ScJpd!`A79XN#cMzut?43tw8G7Gfyvqs zlJ(ZF3QsVCXDly!^wF~$YtyT46CV8`8`Y7erKP7!1ud|@?I4#K*>pM$;6zvP74^TZ zQ5y_z56g~yYbtnm5zOB|`L9TuqIy<{RU;;wsF6o4H`n)1Fe^Vw*#2fMOj`Nf8L~j2 zah(SU^Bfx#l5EJhW)p+YBgh>q5NYb3GUM{Jz6Tq&ZR?Ua1@Q=_qQ5Q4q={D(BevhC zK$`Z6nu?uKrx)ZD!QNJ{E1rP2Kz5~wDSx%cS~63#-e-U9dj@VbgMn9av-bJIYx}<} zaaKeU`1H|rU|>2fP8a&>*%k;qo_~Q)4JN@ES}rDETw0gM9b(#6dQT$-8ax@A5{B5n zeGw9P7aFNFUjcTvmfPM(Npv{C`rHd~m$@0Jc+Qx2%NWDt!uQD?`&@e?ui0P)G_D88 zN_naGms$gs)or3w5KxGw`=Q%$jt~P<7g?N(Cqpy-St>T8{m=>S0%RYYSg77fKdfJV zBQS5~@?X1Q7KL!bJ8If#W!w^h=wW{phIZ*kUudB$A=aCqdvjB_$zXVbUL(|9Qp96x zYVu6rdsPQ*{@W$anjYV+Wlu-T_in#0V0=U!c8x!OksZtlCg}DLcEou5tWjd`c8+`D z0a;R*ts{$f98`bb!ir}gh{31cQ`5A3!9Aye+8ZFBQ8r>gDJ9@aw?&`Fr=)wxt{>)3 z%2Laz&(8Nq?RKSDC0P9xouCy~?#nTpub!ov}*T}F=AkeF*$h`V7R$hgi5&iG%vZVzaf`+kR!xl^P^oE9dwZ*CKM0X zGgN4Z&BI!H*eqAWg^RSR2F5gJ$}p`hLEzh#|4qfcx_lF8XxR|$}7pe%0iPjqeZ6V zpT1hh3P6IV?>xI|5)u;;YZZ>);Suw`X=rlbvnF6+x@meySERHW z{Wieuo^~${X`+Wm@JI&=@7s~}`e`%Q{Upyg%Xz-ovC2!$uVUK?*NPJb7uHqN3An9x6Wr~yLnQ2Cg#1ByA|I2Bj0HJhX)rih`(!= z(&^cUYOzEV|5lgf{p0Tkd`P^0j2~om$o2#y7SOiPFR$-!=q; zV1@R{rlK|X#h)~uE@X|Bsc57s z+1r7jyaa5J)jzQS@tyLn{%ZgJ zvIg)B-Gt0dl>s(89A#|`m_H*uIuk9^wJRnu=hdGrE7R+gi@B^y)E4>AeKTKwx?(yl zixNl~apnl4>nY^OjRy=r^a49qQg1LOn19T`S5i`%D)MBC2*iz=8>vhvyo%c8{s>Vn zfA07;#(p$vanruJxj7PqXA@*)e6hbP0@xZT#@J=ReaGOU7kW=z)~#Be3)n60SPRFueWrUEK#A+RwoYBi zI!P$MY2~V8QbDRp95YJ4ve4RG&|4+nKFhm9=!>^&j(hap@p1=zWynm4ktj9bWHr$U z)E-Ry?_4bicpORzA8CEi!Y2XNj0pk9BKzEaTZw}40&q4>AGw_FOSOLIKhrr2?3tRU z$kU7irN+(ajNVTf+$WvZ^8ulbt)B%Z)QyIYW=QMQhmB1Js$|oq)B`5GSV#?_I3ZWq z531BR;1jdx;#PMVyCbqsG|e7Ao@>yQ-jCbF;Yt9xdpeJ4AmMdiHkP|xZRTl2dcek7 zU_7s`iTTY7|FN`z+$m<7SMzjhuL-Gf+|O9)$Xk&%$Jg)2o3Yf+Gjs5MN>zrxh|8tg z`(>G5uH{69!+6brL?NSZqhSmMd8+;X@v<#YT1Cct5GeQlhh7bcmd&|8`BEd|jSl8Mp;?x@3M$P1t!K{kp+Dbqx89Bm~|MPSCf9+_JABl=or)XN{b>?3flT6txYb60lx808C^(JXS(b&c!>+HI4Dj=*)SM z?%OHUqHgoA$V0R94K)CJsgByTgwlGpYs+fMjvo?SQmkgXzD|;=Rh(c1GZx~ieWiz1 zo&|nS^PI{nKKE1l2aqd#VIzx%IO7Ap*cdy1vb|sBeAigs_tsVdkXaO~iEuyuO}m(k z%norD3`f)n&$ZRu8%cCm=M(tDT=o5yEI5fa=PE57t^w8R(KKTxG-IYe-Jb~N;;Rc? z-`s_t)>>_T;MNFz;&er4!!8gU^H`qS?UB?>{;?zssSaiLtS)W{f8Z76r8r6+x@#^O zCi|0p?ZL5A+d2>>T`#8a8(DqeEm7qGGEP-)=;HWubpk6~us_NfWm0s8gg)9EQ1NHL zO;T?p#|BS+w_R^h8AnF7WSdtVZ?{s4p`wMeVEY|_^m@u?#V4s332JX%4kU!4C7M#w zy_c>{^13Vc%Z@9!J9z4~9#h;wyf={-xpP;djbfXc#;me z$l#OBwCN%u$==|5h9-?>rGxroNIh^OQ!2c8eP$SGsCH`)wXr(wnit3?XBeKP-C_tcbuWF%Q&3cf-hXoFp$=% zey2h^U&l7BpM;4{Efc`=4z)`u*KY=5 zOtg}ZLrvBfAH0&`$IA|#7fmCa zi1AeJkC3Jg&hu3qVdq5}E@j1ccjp^2c#at7q?oI-uC=Q7(nr-c)}_XGt4~Kh44riG zoYZShFdON(Or8=qj@x=efaCwr3xCTpaQP*>kc7lZLMwx>+TjB@E8_by1IOc*-h1st zeUO-X+c($8G}EgdHZ0vLw&gQz#AvH<$Qk{1;cBR1b}wMP5D3@2w`eM>V!H1+P-ZTv zP|=s8%db}JR~!89`>Fu7$V5aHt+n9J9h0gE7}yys>|X||T{L`IPs^B~m+=?GA)NIm zgT)CAU6OP)zBwSOzOF>2YKUMpANxAlS}Ym1$tAK8e0s2H*JcRuf|woV6#SCh$mD0( zS9bx#-tqL@#6iZMHoP;$xWZk5w$ieL=A_eno{HnXfaLuZ5e>uMua3i{oxTrty27Rz zOCt@%tb<3dEVU=0PQeGbXtFO#8*&{+PEn0JS&xoe*(-VHu8JKnKaG{&dJ;-c%h{y@ zvggzpRyI4yu#l;!J+N6c92ycbMP_dNAIU6}7jJVHslo${El;DSEAs&=4@&dU;7LYt z<43L70f{^JM@Dr>M1#Qe=4mo9E9PR`FuK;`GIY4CJ>T!O(JPBwb`gzr{LacI#$&DN znK4nopR(XqwY(_@BdoYAwplTtA$z{ z-aT$J%kkstnAaz7CiDuFj`F?XV(EuXA$RYuR`X?@0+QU(YB3yV;UwpdU(pLJGmPr` z8aM)nGUU~ia4fTHYwVlt;mHjG!MvjgnrP&N3wqVzivE2C?47WOiKUD0i{5tz`%hH6 zUF&=}g4Wj4u-51J~ObbDo0$(XA7U-@;d^WeY z{$Vs)LS1BBS6K?SX@@Cz>lV(R(ZS3vs9+~0aBAp}YcQqfe}!9XYvsY-=Sd75T0y~i zuQ{=+H{)s}vX4|bjRnRT)^eMtRBpr0dwLsc>OQMdcwuv!y3{XNAm+y_bMC%Soq=Up zR>wE;O;=)c<9d-x$#x+Y-$+zEY)V~X%T`4+-UfkTEuN`-x8H+`h}N*u-WF^|IX!vd zt`GagO#`E#CK*6?D8tb*f5ENlp^Pb9#({pa_SIWzl7&%MF9@1h4%lplO3kua6`fRx z=zm!0)>r6!AN-o7?FlpdJa%3qeUBJ^n0n)pWI8Vpbuoz0g4G#Jw}MHs@J4zxU&Xi0 z?I-gu#6iI$hP5%aqV8d}moH!TdnEqTydYCGtD8Wh1<>pzPf*$d~9liT*zQ0_(9-95+ z_+kp9Z>{WH%qzjG1%r;Uya3VivF^*X8@wzCIcg}cZjqGXmR^Fky`Z~7WLR1`QLiv{ zHXf7ufIBE-@3umTbsLE(wozTm{W6uTw4SEiXuquOKk>h1m`VO zG&sTcNW%NuyuQSR!v`V}stS_&&hJR*+y+GXFtfG+Mj>7oll#qTIAcP@cVh}I65)=aXnOE+3IJcUP$X=2Vkwi z@D9xw-g*gkgVLrR9N$XicgNDkpHz6s5d%>3(UpC8`ic4b=ZHNM^tP`)1i$ZK=i@plZDo!F)j=rUNJh5$V_Kx*k?4=fSy1g23HgS$G)R z=^M;wR9=>3>KZdkC`;lE6%?cmUOuW}E?!FC@-<`%k11o`0q^#2KY4f2KDGn!myI+z z&Ztr2N8UDBG$k*qgVcuve!SpWlj^Hu(~M(m6L`x3g@Px_v2)4Pq;)bjIP+`G`Utu`Ov1Y`hbV5qaUiI zPEE795JtdW|HQc5gFGHc7t_BMC=3I!tY&;DUM(>MW!?cFxywrQ?V3DTp$P9@<9jUm zA~^X2iLYdgFods-iInYEsnlW)G(OF>%fPlzwN+tzd1`m<;+C`lecOXCFPq2QZ5@oO zTpgMvdY9@h*A2LhBve^`9V$PbeBo#?SuosPcEwf4E&36TI@0B2ERwd9B_rZ1ye zD=?nb!dN@nHWxFS(^|sXbQ41N>iMOfF?|iO*%v3DK=4Ju=4A0}-Z2vf^%+Nk;nQ&r zunK?wS>Z6QK-;il9I#GMwQVvLSLaSrdql%*foG#CcBOo_>S-r2}wFRngj99;uL@BNy}lwA>gINZ zy|S|>h0{@9Zu%!uQc|RVpZ3ykSJldI;43~ltpFiZfA=|HtVw?wZgSpiW-k>X)tj>Sr#Zm1(4x5Q5Q zq*(m1KPcF;fkXBuSE40RVw1KGt?r?cg*}){;Os^lMEo&%W$ema<@=wY>gqPBw9E4S z%i~{}&Y!D9`ve0&;5>b**}e&c`3WcMJkpmr$CNd}c{|2}O-Fzz_NAdF#l+D>?90p} z2XE1h3JonO^MQ%_>Sps!&tw^JJm(CRx}5Z!kq|AKK-Op}*GLcZgiGtp94p1bmU&N= z#6K+|EwM;sxknrb|6g>#apN!P&MXp4>7`P1B+KNFt7-!$2K^0?YBxRc*r;5*?i|eL zsvg0wHV^ak((%RyH!K-dRerZLoc!vsGlr&8($6*a6A{e2q3`GO1vr<#vg^d~f-p|S z42LZ_HL20tHl(}5v} zC&$k7&qC|E=RX=HpL_t-q)NbXQI8?;G2ta*V&fz5proDEp4JQl%fu`X-B<)311t3e z9@#nmU~PMXB+4@)7O5CPRd|nC`rWVoDpw7{T9RT`Ez-C-WeWjAmd04@f0JL z0j_1ir6PsPUk&g_OVV+YRyI16X}J7OVe@H2#3{wL>#dBY6V)Kmk1opT1(>yQtXdj@ zJ`Dj2WtN>7V@QFJ$4E(E&K0Y(E^Wxj<=8U%cLK#gzNUsoI*p4o)i091as`Cd@M5E5 z%?dQ*W9v!CZ7WWR(E!Mm$O^gF?8Y+rHijcbA05Zcn>UBHgo}s8_5$!cEgDiyl3Ij`OQ{MR?@b6JhnNM zwpzGCKl$CcB~}e11Mw=P*gC=D=ftwe_M{bQPSU|BP(qWhP*cc^gQBSr!DtbPq_E93 zd$GJ`4Q}J`H@2XLSH@1V*gPq|#+mB;+>vn#s#V}{$MH-{H-c4m^5RelGJqz>{wJhI zc8n=&;nDgae2WC(D7ab~A!(7Web3$Fe0%T$OIrKMJSw4h_)%Bu?MT^+9`YL0Jiunuma>(@(Hz+t07pH~b|H;Pk(^UT1e2Um~M zJ`gahDY+?pY`gHQr463v83&c$9AU>(PxDEdG)d!-@h&v~HF$+-4_R!ufd_Nxi+gXxc8zBwG|So# z2rtBDL5lIZ$RydgfgYio0Ug}AE9ZoNAFkXhZ7RZs@&LW}rh!MYC+ho566X~#jSZUW^Q&2IVo6^BH(=y|zu4)6i82{N* z=c!o0av~|t>&Goe?3ZWF->$TC-{y^F&j@+nVw;scC{S^Q7$o}pV=bebQk!e=)>fG0L@&|0LO*U(4lVY<+6TnWJ-NVtI`?7N{S=Us-gVA~g8?R}9 z6{7;!UM1iQrtjtcMzj-tnJE+f@L1NXake^Exz^ZEVg?g9p}eEdSH1lU)Djvc9Tx{| zMeI8jFYpTx)kP{K4!h46F(xQS7C$tp=mqP0bjL4I;bRCw>YHEp!R9zNl=iUiVdV3K z3JPK5Qu*wL=P>c)Y_g1)LV9`)SH{L`o?k369cpll1ahzG;IP3CSe8)*$R@$3hhTe7 zy=vaJb=o1|jgd*Gm31?Xlc442YCf59nN9S1&T`STW18bq%??3ft}gB~8ctq(LNsSi z1J%BA)u_fbd+_EynI+sn!?XJ7qJW~eeRCX3Ic4{U(>e#qJN~Y&Wik>HK1Pb2YNfxr zwzol3z#Gs&*OZ3#rx?OHwMrWErrN1-2sGzVg8QS}0qcm}gm*FHBa!ad1VMWfQEv}T zx-t9OKCa1q1?n}SX45DSm!}!o- zDp~bN-29d_8B>`_`^4I<$bYvBOwDpZ9=5eaSA;nYc)gJTr}PYsoq#&N!F5=?SzWlS zt2g?FFE=M^M}H(QHGxxfgI$&?I-8bi_`}2jaM^o?u?m|)!3@PRGZ91HKj=3`TZa-6 zou12V%3dHrJhrC;NbbXTTBz;%AtgCiM_H+V6=#O<-GBS3iNMs*9!M@c&Vm}`lcEDNFc_?lC< zej_y#q~sSKACScZ5vGZ0N>$xjq%LK@9qmMGIy4nt|2%ilhi{!ssj)JvZ zev+J+UXUyM0=I&lzy3~egQp=ueOUJgW|BaFb$BBKB*|fvuF$n~?j0u6$6Nt5a0R`6)_ zi2+D@878593emntE}^GmT*Y6Xz35TJZAZ@YgZHm`euP)2Q<$LMm6lYfsLy4RlBd@P_8(Q$C@uvZY$9H<5LjyI0olbUf_$ zs^i)sfzFTRX*I&j;LHK|r$y2eZKt`MlFmd1{0iNn-BE4x^?|bMdtu~VJZp6GfXVm;c$t7@vtc^^PiF^El zeM01Lw8Yv+mz2A|I>uVWfr$&Yz)2I*lwz?Go;X&`WzFNxO(M9>mXd2 zZOz^Qi?ncmGd!a8E01L zx~|x%mRa&8%q*)8RetMAKJzl|N_}hrT=^r2==vcukn3kp9A`We?;m=Cp{_(bH5tUl z$%5(uPOPT6(&ml%*bZmXu;YAxSiFoqJfj;Z_h{-Qs1v6CE{r>56i z@;6m??bXe86@54)7!Nip>&_0z0ZiMj6h8u{Or!>;^F?e{oA z0cBqsu87)|B^Z1fcB6S6+Go(@E7Fu29GgVu79zIW{8o*;ruE(8eFN-*zKHcMLx)-- z(7Ld(lfJL;dERRbp6JRKB?rHd>iqSBqwxTVFHLPTHuwRezaO6o8A-Occ<2$by1H6B zapRdqfIh3`uj@k%I3RC=_L^5 zofq;?lyXh|PJdQ8jO&0Vq#B3)(tQHagd0<)`IDz@jRv+nfYLgKd{i4wfd|rpvjO7g-px z-?FK>p)tVdc}5H4ST*Pz8TdB2c5E^L!v$@4>+fbM1ZqqOwl6p=U8FH98K*nZb-PzJ z^bzm9JDQk(j3-Y0A64%GPxbr$j~^#xB&*2C4p|Xp#!<*7WTni6?2^r)K`EoMx3c#p zgi`j3?2PQa4u`{WUcdXL-k=^*Y&)v=QWITJj`r6f%xKK6O`Za z;8=E$`E%Kt$lQjNp1#m{q>V zq5T|m(RBCx%UEmBLd(nUES_+$(jiW!BB3d|mbHlte!pk2s!H5d9latS&hc!)Aul6L zMyy9=9mQbV8}ww#+wDg~5#IE+c1t{ugT;m)FStQ6C;9bd(`v-mkrdk024MVSR2ac zrYw12JAoJ$;^}~6YcEm)zWN9 zoe8VvWOD)SggT?pdF~B2iV>*r}gn**@F+fe6=vzRm8=LM9QR<=n z(%l!2NZU{aJ6ZZ$dp4h<%F&N=S}H!S8B1rl2uya*8a)RY8XeA(>m$(mrLE`jwx;f6z-7drTgM$NkI(kXLEdBNInWZNsp}tD zTC+AOZZ1J*WD>j?Az$TQpt*XDXKRb25ls)LF6 zeLYuWOri&Uwrb48PaB81t3B!MHd_bpS0rPipySz`p5#_(Nwzs$Q`u&*aGmVfb$nJg`HBNT$@|&9E z9c*)itN>f`_>lTM43ODFD<5jz*B(=u1lx#4CII31{Ie&KdH>1nETTs3Z<0WSBT^dG zx62{T0usVgy+7^3Emw3aM=k6JjL#5V`S_+ZB#Gwk%d73u*2c|3CVi8P9(qr$7UmTW z@hkm=9DK|ivyvRmrL2Iulje_ll4Ya4WUk(|?I#n18(gh6DcihcUeuj(nSU9_5^W=X ztnVSn!3Ff2d$^6v(kRR5zSpCVf@vS>;D&Bi(~Y>1N15dth+Aoj@=m;dra0{QJ30&a z8K8K}bT?+!fa5YTH7RX`3?kEgb=V@9?f!R4iyLpmgt<5q(Cf+U$-z<5$m3Kv<&;culg2OViM2W=~d zR!idCTx_P}`79FMj!w~V&( z^o*53&~o#L!oG4%;~S6_{Q#9$VIyB0xC-2rUS%!+ax!;Yn>@=9zxyfB#L3z6Ce+y@ z*ssQ$w%Q!hY*u-(eX-dth~B+D9gBki( z-2aI5rl5$xpgegU`nc!X1~!3 zt+@##ytJeHE;#lBb=l?|oVe=9lAN<&_XE1$s&*FtX?FMYC)ulV5&q2QKAkWzZ6mm){IPnN)1Epqn5*{Sm!QXPtx z@yW^2%!uj}>@*sjaAJUy9CT4*!dLT*=gbVt#Lk{6_-5VDdCO$~NB(xvT&V>*^Mhd7 zkGYJ6i?doDJTZ?!fsR3aI{7(nIlu17@s(^mueH{7;KXQ8O?`dtZuIu?Vn__B{ZsD7 zsQJQb+WW)fWDeDZRc!!$KXxm^gHFonddCP7ZT+y7DVQqSU#Vs-cB~OHZ0-eo-^;#R z2q+0*7d22(epOKLQ&xhFK!TR~ajM=ae!Uor8yX{g-rmR+0feO&>3$7j_T9<89Wob^ z0IG}6b@Ep2b=NmF`W}-Y&WMRIQNS3#Li@gKSA5lsXStfu_+HX9^9QlogpBP55LD~DHl_q(0`p7TEfY&3 z^Jd9gFHUCL@=(Mpy7eJ?H8@$Pk6U6%&y)HLq!e02U6xV**_-*Y#b`o`P-?6o&&0i* z6?Kcrt0l+!*M-n$q6?t9$hSjqaHnG;w&4xGtGY}dp?MLHZcSv zHw?`N;TIrIv_W+KdfKP@+UOJP*xku-iz#FIb`$h<7fO_H1<13J0}u2Nq_K6Co>`Ir;2MdKg=V0B@Ch|Ik zAj!TiAum4)=4PbM%Bq^40KIS%%z-;J@~OH=ne;w%!wwEoIv)kC$CIhGa%VkoA3&{z zG%Qs|jpX7o^~GhLRQ3w;W|U2l7+lN2Gm`?3@0@O`=6M8UQ4oPEvdjd*sZCzx(KiXE zGfar>k;~~JV93b1VgBP-&7>w9FYw$aweYU>fOwftM+0TnICW~Kflgt3j-Q#JMy_vR zOmhJm1kZaQ@uU@-%A4gE14>cBkOnR;@1nl^aJ28B#;rckt-%H_5`fUu z*xJj7$8Kq7?6#w# z(EU7$V0gyqRx!lyXf>I1I;oDR9%i~Oq?6@3;?mSD4lt+XwlvWSW^yeGEs&j*aZ%@W zndFnx1-F(TGzz5PF*QW3ZYYpU}?59h?8UAfzPr{8*p&@YpD_teMF!x*yy z{h^CV(I4?HposZ8Dp-&&&ML7{xdf`B4vqzTt9ru&N^5I5%T$dD;-dq+vW*7xFN%%-MhFU z@&uC`YZXYtOZ)=&1oYqxRXOG^Ux&ES`d(I-C5ug0O#j@T+8mV5*PS3^Spop(96U;3 z+L0AZV64I6RnT)ni@8o|S4OS7$@}j%uN-a&rnoBv zB=`<6pTJLY1xxj%0+(TN^r2%(C2|u+PPNPI_Yt%HJaS5)$1YXHWX8obh>A+|cn$#d zMYzCqPwu_O++^q^zl(lR_T3CK<`aGEQ;1;dHDwmhEIPpA^QYV z^xx(=I9Ok8ablJNiHHeo!wUiE7R<8IQ3J?&>}<2m#xHRD+csU`sQ`SX@f0Q4`SLbB zf)yD%>COSznoHFIa+}(RcwS@N5GM(1-rG4I}5Jg?R0o202@#D#R1gG?$VLsc}5UmG4-*R-in5D|-l9wEf?%Pz^_7K$e$ zW~x6y-e|2r=9V8A)z#m35;XXSl-+M71DC2eMVGS!Z`X2!@%2lCxPDib%G)tQ<1OUe zjC+O$j=v{GrowoQO*=wxJd7R_uErz3eHD);G+LjQP!-PWqYGI;m)C8fKs#Ky+BvuC zd;<%0T_#vW(sqOpeTYT{#OccWt-xZ=3KZ*`?eh8&KGbZp-C?Tw=4>NCe@e(~)UM!J zcjEgB@@Y2h8sDh$tF;E%HdQ*up;zXI_==g`HZ+)fiUkwO%4f2=a*rD9$t6t6!?{WFpe?NBh5HF9JSGFT z5L^`-;Zah87owyAL6%T)mNy3<%y@+bkjyt5DO3D(hCiNr59`ot133^Qd}RS2#Pa~S z729yk2p4|Xq|>k$g#U1$yThz4@TG3%sQ`Z66yqmy6a-X-g=NeXh&f)-mXCt3KfA0S3Z4G%xh9Jm* zw>Q#!OsUYLpz1$DJ!5>lb+f>nj=k2?w0+O9M&X{)zA~e8SQfY& zxcV_)fy9+7?{qsA;g+FDg(>UL(-5$d+PLvA7F7o})h9o#FFiGRTJii0^#g zJ)yUcvFGoFJl5EKa?lcda_U50e8pLwMT}XPklJMsB=H3X1S5Fpu5EpXi%xj%-OX!D z5Y6>Zj-+SV0>1o7Vo(I?cTf&d@I&o$4YN~4)lqT3oc4wcD4ivnzKu}Dt=RXsJ23HX zVA8wMBz}aM-eaf^kS7Nbb9w+1S9=`hBM!6BL(%doSRa2jh$#1ns zc3Y#?_sDHM5Wg~L*x$G#G@CZ!m1@=)`r?NQ?*T4={s5n)q+JKD6G;RBd*aqdBKAYa zX@kvi3t?U`y=7$K)j9Z56Hiux`0dLY>P>qC{ebNLDSd+{^D5VIsY6F6HP!hohK5+2 z42`w;*YamvJF@Id7+U~a8}iUm%8yVsaWVaG@6#=C&f=0%ow?zmTc)WOeyf5(50B3c zf8OYgf^4`um#z5h<}^WbL*7omR!iZ&iS$Hun2N=k6oP(KR5fVcSZR!%SD>h?-^O&Z z67(QRYo(yYIACO^?@c)&cM^<`WluRnQ*(BcsnJ)QGzXlp9Nc^Mp>BCYDhF?K-?)4S z#FoD2-fIsOuKV~wLf(82;-mc4Gndm0u)Bw}*f`;*gm6&7`Zjn8&{#G|H=;`ur?OyI z`-O)!y~Fbe07)vEQ%axLAXBfY6axb0;7-BxhO~DSI<11-J~|4W$G%WyegE}?-~tDx zyar!Akn4xj$V$IEV+5s3j+;F$@-%+2d#!`L@XkZ)3Ybp1_xt05%4@i<^U_BkZw+P# z_yv7j)ro=zq@iM7wbwR3UiY?u{cq3d{H#L#%4=tb4B*x+=tHJtg(w?L{eo#&jk0%; zx(N6R8*jOk$)5gL6#o@Rat2)V_-t`w*-LwwmIMv$SYmJ{E3}=&tP8j zw(4>DTmq}q?*+5dc2Rt%`!7|q7>!^3Z6U!1mRC-6g3ykny{`7uDqN`LCFzx7Eis$Z z{VFmmlH-q;pAei(6y{JXj`H4MElMzY>2}?k;t6^GvG3h%59j1fPqfZGH|Bf`lwKcZ znGZqVp6nVboIK5Es)GEHzVC?+j@J3ahjV8A>oO*M7!bIlUS}PV`0vI3%_700mA5Aa z*QNAAWxzM=voI5Pez@MI1}h)tM<`GtPy7@jxeD9<}GHGXV6mz|sECsFR(F0CEE z;`|PT=Svvps~~|D(0C#6ISEyF?n(Ilrk9x+Ec?+v1pQm_RO;rgAQzl1(T7x6((3;O8Gr{R8L`BdQI zh`30f#lXZH>aa0V`PQvropVAx^ZOAyIYa&U8tbbP-d z&H;)8L6h?#e#{YKiqa?dd0V+MP_Uh1cyQlFGL5dUa531rf44CHGniNeS~rF>ZKQ!{ zQuFslXfJ9!oaL0a7CVpKRJ22oR#^bdK4%8EJ_o_a!i9Ng$@r8~7XsrI8M=L5``9 z?wERQ0Ktcx_=7af9%(m$jOg>H%evKs*6~ukZ=2YjY4D~%|&eTM)0_HLXi##RPLRcjwRgtJw_&` zX^w!P8$ePssEg$w5dZ91S%GSW(hFGrukXz#a4KIq3y=pLOYSFCM5*SN!~0X}(f*9h z3#xkfwH=&rQzmEl@g>~{o@g((QTv;rxh56_AJ0DjfxfmV>~!)!Jgh^ulhQ^Ac9+$D~q>1*n1VaHcx7BgEwM zYa@3Fm-Qp;dJEk`hw)EM-fQ-}ny%iFGY{GAKmsrVjIblg-Nf8Z6VlCdC6Om2^mq5y z-JXcNaXtWFMJ5H%jS}SSIzR;3-mr62)t877B$Ps_%;YwUk#zs)Q(NfRNyDu^P zI3XA22({f@%{pv6emX;^L4WV~*sSwC|3RL1Qp&=e9KriT-57w2FDM$MlnXRLZx zb8q1j{-uB&+3z#DeVmb^V`*moObE5lvTaw9e%!?i@&%Pk@BAukOrp?2bw0QI|8U+Z zANM`SfqLz$dbf9-&d=G1JUh+s=g^;L4$l?a6K`C!(p`XtM<1>keK`pxf5A4y5~*7y z6>IcBG4d6h>kzpWmi}~kUTA|-IV=E7DF<_{P97)f<{+;eJc-}4tW!d9>*XJ3xyE%_ zL+%S4iAAB~B9%ulDq?(Ns-HL3d6qERb0|KYX*iytJPk^=BBBSHF1%#0e16VS>_Rv3 zM*DS#uhc-H)Tfkk@GE(QZ~RdFSZZ`vs-0bACx2Re@=?Y+t)J6w0+6%=+IX(NvgoC8 zMuMWW_neskB(R7{A?9_3RsIQa^$BxI)%CL=&fe3M2Q}}A!0F>wGspY5p^!>_>~A#> zBR+??Vw|ex(Dl!D#;hMg8ZK=O)1ixsbyZd-H^hn4lMD|jt0(NT;@t4Sr?FZAQ1LGo zqgGLpXGIzfq|Dr@D}5DtDnKw&6)wHLRMM#Rc^qy_HzXW2%t|}aeXD!3G@sEK)$bm5 z_vaqy*nA}+6pV}+@VN&vYnzYwp#o=GB5>Fd@d3Zb6Pt?k9{tEs{0_#qSc>VA!l4Zd zsFx_xJ{%$;R2&*96_1PB^*nj9NST%7WV*HBIyc$AJUL;#oeXTnb}lLz>umA?j*wNf z0fO|Eg))nsLAcKK8TWin{-A~Y4k#Z|MY`eoh1)5RdlVY2B=YFDs$f=B_w|15j})#m zu}i1eX^a%)e^=MsFVcweLyye2jT7K1&$%7kUcU&80O_27XvitXp5r@%kliYQM>5{l zJTB_Ehnp<*aDUpvQr2GelK&57me40V94fm0B>|Vg=3L?JIcM+qHnkqQ(eEwfBd}!r zGq&ty*+Y7V2P&dohsUYSE}?(p@ecHWQ%Cr{9?1k=hLq0JnEwcrv^Q)Q2@vb=gfpblL4(bwD5s^&}AkvWccwdg;v!Q(s3%x(m#H8rJXV7DAGKFhz%9`$* zpg>@B=6pwx(9S}|`x#xMqUlNgdrWi$Ehp=(N;!yEW3wF68jFPgcmS9iQFltj?&rkJ zC!$mj1xwh*^K%p{@E@7&=Um?uz6nN~tkyPp$r~Ne&%X=S=!--?Vq9xS57N0{2HeWD zWC}N4{lYolAIVRW1QR3*|8?@-Q3uCi>7XqeGY#hkW_hM|aWRHRC&#fH58L?z#f3IP z%qNx-6nN6k4MJA$Zka*FrADJlhm6+zkl@-`41*iqul(e)Lh*@~_QTJZb{I zp*^w4tH{%K>wLT)RCZ=`aSclsoes5$Kd8V;%6iiCjCptfUp`onJX;aY5k}qsbu9fA zB%FYhDK(NUvo#zSGPB;)5)B_Djd+l_HvPD&R_3=;()Iak+)vmdvyRw$PC(mJyvI{? z18GSC!|^Osksh{J=_m7h0Qd21GZ zT6JXdqamAs0e%WVsh&9>wU6-a#v<+`zCGAZ0Gsp29v3msa&As1FOB+zcl(bv6ooC# zbtGj*$>kyD-!B;)L|5wH#B_g{<1OetIH=vS@!Os3yZp_gaeJBy#4%mKUTt_-z$4LG zO+d=k%Q^5f=w%QYdI8T%mA8gtBS^C9=zPYPx-r}I+`zLwRWXxw!Vrn2Urgr2`o8yf^QwkE?+2^rW=wZIf~mSR2@PZG zQ_bs6Bp%+ZP2O`5mwiIT59#9s1gsvMV9*@(>(?*g+utS!6_TS14SI8vfS1mzBWwwB zhurzoS^7IVx}h{>pwhNNW>}L%ENxC;!=-dL7sU^GIg|ClBbi1|Z&Ej6<-9sGMy^vm zJsvJCO5009uuFloqR<^-2Gs=|jY*kJ27Kj9#xLUwkF28}t}pH1m8;wCKsk>sssyoV zc9(u|?F-Df@Ifpl0i@Lh=v~Oql73f&UsoP^ow!(@`BM}f9M6h#C_^Zp4T5!>{1L9&`5jUm08xw@*`%gGg)Xl5=V=m%Z|ML{ZCOnsC6;tSJeS;z37Cv2Hxv7Vu8 zm70(xGc#&b%yiBDdC5iQ{s8J|k$!O`*A>SdK~?>@DC4pQ*NwgTdS0&e(4p6odlSz2 zQC?uaBt}ZdxI{bg$xUKKd17gf0PQ2$?KR7V6fJ)p(mA*NIu0eT`nr|sssj5FzK$jn zH2MH~&;xlQzUdQPIiwBqiVe%DRT0PHCq35cSEqjPX(*jD&c04VO$0wG2?0EaK2|nk zUL+?wGL*E=g5)Sl3ZhooBm2{>&OLZr;8~{WC6<>p%@u+dYCGGQ47E7)K&P*19V%x9C6ZoxydPX{vw1_jXslt0 z?fs948YxPWW*Dq&yaZQ7)BAf|&4)9>a!W54^G3;l&m&vI6@_T*!dqfzL`t7vk4uYX z_(+F1doJWv0O_knORzC?9S-gPeBHzq?aOyT2ESi7ZQ%Ok3xOl4tNM$B@OTlqt#H9T zWJ_bXy4RW~_hDBANzqu$QP~??o$L4C3&J}EPoBK|Swx;l`|>BSYTsGUu0(%H2z5aQ za{0X|ij$OQPw}F7hniI~QDC;Uk8S8&!c)t;6;r6qb_ef$zikC>(Qos6O(N7fBeeBz zMJ0H}YZJ=_U`1M5&!1TQj2>FJS^}Ez*m0HgsAI5c#iuDahlf)+8eTnGy!gf8wAbe3 z?G8~}@-i51U{HlN}@U( zbY}{Gz9Q@Fd1()&r@@_{k`zXJYn>?C_orzg-=c=Ei*HDF(jPmUk3dP-d9!ZR2KnC= ztBJ8-*z1?-LE)^qc!W{6t9}t!(;z^;egPW8?BRnigL_4JHLo3oPZj)zENN#HT5XR*%@&7wema{;9TI9L4U|~97-^@+ILfK;& zlsa#c@g}YQd&a2kiiH<{m+Qb81HQ!))s&}TpJF?Fw$gzgJ zWEG-Z!)=gf&B9j>9(fKTO~g4%olN+rbajLep=1?3VF#_=c&FD=nx?Q}`%No_b+nRW zr+;gK9N|Rv%Hs6K=~l|md$RN~u^7mI41>AsiUa7i=aW^Jt5uZKC9{23oa(>J*Z{P_}MpL>5|-#(r>s_*qB92S}MP?}y`K(Sh@ z(t~XW{vlnYZu~PGV>d`F&&W9U20oda#HP*3P$MqIdSW`fR(c;k&ZQDvVUm zplLfxL>n{2dgHciOJHZz=P2^po+pm=3U=fZu71(d1oOJ}*)-9mQa~CzGR~k!Z=4LuqWGEapzh>4m%Cp7b ze8v-r%@;ck-tJxDSr`f3{AoW}))do<+j!!Tq5gND#IVBFP#teo2kAmUZS6dymxf&W z_A{fmFkwNG3_9^wi)jkNEznfFqeLGF9kC#d-L)!pNo?8?@#0R`J2PQzCtFD;-`G zjW#ux7<2gA~yU4RKAe1LkI5(-j)dQRU#1z4?Fl+ z18*Yte@$|^kD?~Zb2Ned;n+hPq(cws{p%YWu5 zFpRy%94!2>^H3A-D*N2=xc-muhqxytW^VXH$^CFEWCFf=-!txuK>Mh| zBD?ahA>{1k2HNGOs#gkMRw_r}dB+}zS6yyb`JLNzUH|+{zJy!sM@K>tFD*tb?a zsi~ATTQmB>b^`0O)5(w(i5qZN<+&B%i>Hrh92}&F#!Tc_V)`E(71brquWFZvG5rG_2<& z*3C6|4TsvImwi}nor66#v#rE~gM<5%otz$4ISxbQ0U1nMPj3P3{Yh%xgVH*L{xpAX zOEBJe#SsQc#hoVzGi3%Zqiwm?GW{rmOPy`M;KtBm&l0Pd*s;I1W41Cm0I=aV4O;5CnYbk{m9BETm zEy)yqVYW)${pR~wC1c(2aYI=wd`r_~exr)YDIAzXaw%5-x0Z`R81$I_%E;K|fl`RU zms{_jvemGsk_BA8q!t8=;xBfW_C$hlH|m18bib*CPO>l?CuM@?&z}#x^%Wqx0AEoA z`-SX!USziPg_O%1yn=@f{S$aIjs>*7v(K){@sj2@NNthkH%_TN1mZ17LbQ&fn#A`@ zJ=Zgsk1gr$y=YG2@Leh4;fQSR=bH^Iscm1;R=52ho7-|;sI7FL0;wCEv%1cj(qE&M z$_A@%a9Q~=I$%Qp)C})8qNZH@EwzHfP)RFFH*VFQ|1mM_t`#b9mVQ1lVtwi3qim}> z`&}b!ct3&4G~F7KJ(Kqf{{P^S7Xa(ozSItd*H2{%i~&-`>)3<#oJ#R%Ww0^Qd<<3G z3`RZm@!=w-KGo7N*E8~#Xt#@O=7qh(;Dd_hOI1f3>cAN)s?+F3`^3LL_AtN=9Z>^J zL?vb@0aY6Ul?YGpA?QsJGvhDH+dfIy@#5Jp z%o{4RBALZk{rNwok^ncoqj~QD+_XUm0*gmkrhr-4;oVJq7)s853O(Z4B-K%6A4X9$ zokIPtO)JqUW(vo#9!H8@QKz z;=ma2+V8-sK3Q=eh$!>|6|z$Pd>kH^K-C{*nP$?=Tg5|`b|?=0Z8@u&0{2y11B(w~ z4qv78Pm^egD=RCvKW|1Yu0C_q?cX~sdRr98lz9oPNtF1*pPnNqXzvqOvx|wNjoC%ZY0dMzvK7@oRJ!TkUjZ~5L_V(Ux zDh{(1NcIwet|b3rT7@A(X_So_k#7<&E(r5%aFa)QK_MsLi`ef-`%t_3tJ zZxjsBupQ?FQqaix_PqnJwnn4?YkDLgm*$%!f=_wlu}JYXGtx~mhPEgoFIy~y)Sziq zxWv~NvXBuLJxjaB;P6e`5!P++uwO$Su*p`?ypsjHJ*|o$A^2^_{Y*e_T(5fCc<|yz z?fJHOIh?%V&#@!b35I)<_-rZ;f03|#JD>Zu+N6@38{bWKvU{U5M*nS0o}aiJ$sYAC zf(2er9g%X-lmIPA+$v;XDOFmec09v!YhL&!+d=u2NhCt@l*9CX_?g87#$Ah5hG0H9 zIq?GbVyBxM4c%IYEp6!k`4hy^LBPsIKfE+R1F(gIw9Y9D_JiFB!NqBXT9U8am>Avv zTpg^iqFGr`$DfI(3SJCmQ()Wp7On0u0tFXEVf);{u7Y_RROcFw@`WZqGV_kzz zOEBDLUcKQp(kh`c^@1BxkcK{=DYkm>{wO(Yf$pl3`yF9}-uJJ`q#K)tbX}#BF}! zGOFHD;d_$;c#i!Iy6f^0WB`}TM(aYHV(Qj z9WFGYe z7>$<-k81yK#W;AyxLbODV8zA6MgbdO`X>dOOQB+n8^zM4pgA=|F6#Q-jeeYPX~az1 zmQb#k09DGtVWX=QRK}2_@eePf;e(5Q`d~m92<;%TX(_D0Dci|t$v`(!#?l!LiKplI zZ1iu|k1w1$Ok?qLS=c|gVk?&H`R7*AXdhMB@>a&uCB1A*O<*JhH1z4Xhrb)jp zZ}%NqDQMtTPV})I0tezzPpz z@zA9|5>Q$bn{=>7zt`JS_HD%4l?bDTZ~MK1fC2CxybX{*ZkKlfP0t+#9Jyl?`3N?V zkKUGf16TTXAYu=nwTy3Cdj3S4gzf&eYr5-zE2XlK0e+7`Fb0q5LN#$L?w14+GOa>@ zB_(LrDRmHn8I+ffy;*(U;);rw%5?Y1U_#^Oa}GVQ-5@TPQyqk}J{WD@UcEFfm6jAc zGvzIE;$|0ICR)V?RUSPv;qK5=mY~={P^eM+Yan-2%^e*J*3dS7@wK!ySBZ*goAR{) zN_KK?X0q(>6|dp6*SgS>*4i=bs;*rwnrj67$O?;2gLDtfBDH1V~A8vq$D&f^5gtt!wDX zeSJ4dB55eQS+Yq=Q$`5;LB>?1B`QrA;|hGeEP~r;L)ORYe;51;L29d)x_$zPP!#uO zd)$)|-V|esg_P&SHf%8-vsGyigIyloAdNJ`X!^K>)u1Bh@A0HGL?!+o+;`v z7+gC6#-HqZ{2*Fe&TIcmHUW4w*C$)Fv(Q&IJ)#e!ySSMvv-M?pZuV;u8GjD^t!*9vE)4t;Zi0Xj7S1 zC9`~&fZYCR2<)Vu1jaNQp{ft$nLYtAfw$^`P&-rjU`qekQ>yb{g?B0I!-d7S6!Rq- z%@fT|N&H?(L2hL3A)=3Fx*8JEl*KpyT9j3`m&-`=sRQc) z{R4Hpv`eK*l1nkXQ+czAt|0Go84A1aMLpF!MuaCO-Z-0Lcxr~$=TEpSWN4Zz0a?F| z6h0Pa5a?G_RPaL;85XM{MrmXLbd0u7^@t7LA+!#|K@Bg#@Dt`#vqiiYsZKbhoWktP zG!#am{P}?8d1G%_!^YW-=eaZWJxsof>6Ca3#eb%dh$dSLsK|hE4j_LTku-pol#|;f zAt`KEQl@(9SEpt&V0SCPhj2upS$!roZg%~y>$mK7;>MHMZxF$LH>Y8JQT_ct?Z{^Z z<}ZIDHm`-Vc!$_j>d9rFS?2@j7h94P603FJIPoc6C2xcbUcC03i|9|w&87XUO>D{@ za?Q${KJY~40)(A;Ot8748+W{(yf@6vRhS8tSp57SH#bV-x#WhohSFZTOigwEOgr5X zmu%SWO`bqAHQ_IPNcv=6Ts}vVP)vfV&Xpu&2P+Vq%VePz;eN4mo{O}{*5Bv?(g*x? zPtyzbhE2L)zs-_)F`UJ;#1q%;vyR3Rpz{tJ=$P{?zO6g1%dJVBuAFbnLaF>%+HVg( z3pmsM;2yF- z07zi=Ge{WwnzZ*8@co|^UcI4A>aiKgZtmVF#V0X^3~-un?lIgcRR+Ys#&pF4_uFxM z#EQ5p%5sjoxU}{+ouKyKhoB(%&vpWAAm2xk9nS@2R|L4lB* znvgA3bdQ6q@n0}2)+IJ&-M~4o;Dfsv`pUMA4DL8*oHB3h?rZDOEN(fiLAnWJM(50z z8{-;cp#S*QKiGhjVy@`cA0J1fCAE=>N#4Qaq@|lJS^h8b0B#1wr#FZVq7ZVsdz)b2 z1P?p0ADvZY4;b6YJN#sidTuev2A}eOL~EX3f2l~j!?Q@_g;O(Q^hnu5I=M`1$lCLt zW`Jn0_dT$Ecae9V0LyFvNcxT=HXOFQ6fJ3>FD$*Pm&4qeUIB6goQNS&;MPXyaF7vl4^Aw!&`tXgwZ+-rZSph(|Vh! z*DSrm$oP?Sg}vK1CD`}=5p61_hnv7ah2pu8K9#Z&w{64-kPApH)DajY9Rpc+!ekXfBeEv0B_h`O^1EB8R|=0@VrKYLH( zf@_q{uh2*F3Cj^l9#uErkRyw*8E$l4#ebJK9mEv9cGPknIGm?7!9r2O66;y#0y0WBJ3G6U0vFZ0LLMIMNW5EZ%(TWK_y#DKEd>DhmudJC?YA}ITPCxuyQu7tK0unA_W*hGdu3 zUIAI5Wuk}!gl|L_CZ>}Thm&eN<_zd2^g16Y zJUlB?(Ad)Ct+7$1##Sx?8MfniX^%;NfIn)$l?lbns*g7PSc&FA&^vcNC?UhD(&0N>8%T7ryCALlzg7ID{w6t|l#sCUjSw zCs2(ZbBb>xw*Pt3^2C-P>XFx|c@KiB-q^-Gz*Pcguu%$fDP834`)R47l;2eT?Iedh zmA8Y_hzX$-pXRMv)^u3f$_fahCauF5jG5y9PD4dLg-FBs&NZTl<6M%F7ZR6@Hi1Lu zi8kZ~=_93Xxen5jY|4&vnabwd^OG8wZn>79MZ}B!-qQQMOEVgW5tW?b=eu!D$xt3} zME>QdIE#_QJB*Dxr;N`cmO@_((gsHHY}TypqA9YDOjMNl-ImF+1yklo^L}mZ(uFIt zd#qo{cGsLvlL-B`)mTRPjicpfLhHVu&$rU2D`2R}P+14nVk3&8=<;9v8Q@5z1M60R zoE-C6FbUP=FtqNdXWU+6-a^I^w!E!qfm;-j%GbA7-c`3#KRI5JW(o8v865^fs z2pPQb_*=*oyb=*f?#( zQ4+x;nrJ<75(Jr3``+$&Q4m>6{x7mtWEX<3)BgH{P*On_nBY!;*qrXT=0z7Cc8sTO ztvtC5wUD0wvLxKDPNv~h#dv3za@^*qe)4a;8X2Th`4=R>*E_IFLLPAk@Uf|kfkT~3 z=wE=7B$0x;5ImzHlxU}9Og!cYb6FFUWq=fUG8OUg+x+kK5G9HNd$dFExa7?ZW$wgqPYAk0Zh!{_${Pren~@k)Dn zSkV8^wp0DQbeyV(H&iSS2SW1Cx%HIHX-H>%2#&C{3xBhfV*YdT(C|;;E1cVAM=p*h z=ZDQx=j4KgvC|MqIiRn2{-dlwOoo8TfkyT=MH-`XNXa!eP>In4eS8~R*6*{cG*LR| znu7{)z0&0pnXta`di)`0ZEKxq9-OO{Su-OcMA7_nqyQi{a)PsIV~O`v35yq3~*siUVvki?18i zD;L;O4nANe&u%h2TBPfLBF^IVOOtfAd#8HhqXzNYu9QUmMzTOJQembIIE(cKm(rp( z_dlt81N$j&q?}6c5})FBIavL?N;3v4U9UxKPNMU=PFu^!D=*R|K5eOeD}d~?UE4M1 zL~g4r$lcMFk&5|xbs6V59A*b-{e}45)kW^dgf_*r|2)pdZTJAULvy?@B6Y|baS$$R z4zK+3ci^TkBV-g7?!oSTo5pR^LQ#@&s)M>{dS8JOBr9+DlqcmPW34P3R?98L)bfO*q_nP-% zIR4P-f{F%Ea`MjVmzcvXj&BK-qaYBT+U@ zo3(F^FW!{_eql;P#EH%>H26_o%A!|%BoMWCQ)*J6yPUHWZZUMv*+lE z$Mlp~wq9{~BtM2#^7cZf3BEl)5dNM-Udiw+<@qI7uL}ZfqU*U&nS_?*o{FyCvAEPp zb-mp-Vg@}nXFmeDsf71(NM``2k^XrA!CR$Kzx-}O^CQB22n$E}t3pp>YCsud?}^-G_SFpozQYHiA(?St-1*IcK1M<-9e z-B4L;pJtJb>?)QybM2yz*IChrTlt4u6VR|+Ej1Y8Dl z9hk(_QPy&QBmV$dG@1-)k0!`SLGNxzP@{GSCt0<4soJ`AHhc2rCgkrIY4Z3n+Gng4 z+J7LF=H~`3B=n$Lwsu!@I{-RZ50+2NyGI|5dWe_tnlgv#j+bnEOJOOD=`-Udc^s^4 zn7`;b+7ZjN?%c`PC(CY85@QH^JVUq@lUAgi^nulDq8s7BT!YJ=z-vqL!Onj%Y}Jbu zc$<{iSz+L_gHXRWwQp|is6Hkmnr>0JRJf(*ntY)J_oDLwYfZ4hRZJdHgci=y@QuUH z_)U~6u1-g5YvagZi)ale9Mtc+Zv2G6=KqN6P)pf|@Wtzbb5MQ$o9dVj$)?M*hVO5@ zB(Ocr2y*3r`LMT6a`cvN+6lvKpGf8|hiTd&FMT0lE(Am;hlrYDb?jueY$&C-rsyZSnpzN zU7K4=^y3-X38W0}S!wd`**y6#cwoh4;6kL+v3$Tln;++OID$2Ay^+80|A@NsaHzlk zJETyuBq2LRA$!O+qR1{1l6@JZ4CZ%7pYQW~ z9)I*#Gjref-q(4Z*E#1+Xc+iGQ^7{+tgM4o%EIC4M_UDvtq6F0t-H8D#pr3R@wZH4 z@502Bq@BOKpx&MMPNVVqHJe$M6CTH_aUtSE&`apFPl_xK4vrRz=4nKi$veu_=0f~0 zixkFK4)a~)Wt;vai*H@H1!(K?ZNk&qRxF?llb0abUd9XG!_T&CKDx+^oB8Rf)jT(O zuoL|R!`&{;aO%zElI3VQAV=%AG74tzV9wiWP=i~rI*+mm^B zCCf6jymx6@H!o>?uW4I^I-hynQmTYr_VN#*Hct;B%RJu=jZ}f~B#Uvy8#`jrH(xRH zk5uAUt8)niuRO7j)OG5nClM_JB;_k?`6u02HlG{qPU5KW+ST6IkLR|pjn@YBkK6u~ zRA}F6iHY$3_@r@u8|zg6LRPv|>tyuYcs3AX!soz1?{wX9h0SsT^WqiTlTqV83%hb9 zydUFySSQ#oMEVekHuyL_#ZSar^uMAua zc%rQ25e_aMC;PJzPflqj8N>SVy*RC}dE#z=A75SGw=#CS>pkE8%#Yd7cqZgf^Wb0C zY3nGBF>{;_@bBxRz_xElb9D$m3}bsPo%_*kbY5dxFJWtA&~bUcFii^m?k%GxUAqQF zw#b(DH15+~IyXN*`1@3E zveC8I9(|v5lB#K9u{v_g;kYZx5mQrXH!gLnR_D=@u#{0NWOth*b+F_j=QI5rN3!c= z$O0;x&O1}+c^?_V_c0SDz&_!2m8WmzVI(Fs*7&S)K%ft$;ro((?w@AM{SnpZ;DRrF z3HHRCsNntO{Cw*z+b2Ec7DOrB6PFPCZDK$)>)3tzWd(X;*#ElkDcrJQC2OdWwxfZY zV~e&rYGt2l$^Ofrg9yKt_&LEDXp(^rvZY$eMv0}?cUw#?nV2<_A=lOsq z)=iM0bql>+4!ml=2M7BX>t95Q9Lk&MG*C~nvaxP@b7WZ? z@6m$h(g(~7|A2X+6*J#=Pz0wd@%bHDM`%i;;flS3H%auxR3-ur(RoQ3XjOk1{urCi z=ppT!Y6aIh7WrS&Ca&?l53g%{-gj$nKMx7GhpeNG^NsPK<@%%u)@&^@gr6qRmZaSN zfEKe|DuG`L%V+kMVZ8QS*S%e<1PdrKITk;!Z;QXf<5g0Y4i7)IU3oA8`)w(;`ONUO zfz#9LPN!SKEBNwsykWA`ZD~t5^mQvYRkQ5rh^bKy1AK<7LF*RPn!w-7U6zmhA0ebH zR=f8@Gd>E-?RELjjIRmF^?xeWNY0I^vl(40-;n-LFhKEje`0PEg&6njx=Kr!xzZ74 zu7sJzD|bK^045;+9A2u9bo4Pwc?WaiGrN7Gt^3C&nRKK>Ww?A}E0hfY05 zSwLy7#D4_3EQM#hq;UvP-#$wyNeFbL)(UT7b%@TNw+)J@Wat;=I^I3v3@hUq@~k6o z@R?d3%Oj^)5nnAJ?jZT?CFp*m?tOCBP#`=(vJi|cT3oLT)cssy*56kpaU~YaVnkt+ z(9p%uZLKW1KJLVo`H8I}kv@5r2PeElGJlT5mJVf#3_l53wIHxUZ2lIEiWpIKQMid$ z;7M7?Ieh6@Cf>W?S(4L4Cf>C69RBn;0Tmt>>VjVE@fzKE;6ER_GuA$KRo<6z%zm!H zXX_#?P4$!lClYhi;O@WLZd7*gOBenOvo**^*l`wsO)~p&;rXmF%b6?@16p7Gy=r(< zg5Y(RMBxW4?TnQytWQqTeA!?uY?ZQY#~if_D)iP7uX8SWnH?DK*tHw>y*r^C?#ZGn zO&h?Wbm4$xxR&eK)pO9#dNO8%iTupoX7C#}rU#R`eaV5kY}h05a#K%t9%WgQ6ys6N z;O`s}C#xH|Pl$FRhbeZqiwu|1b35Hpz@NP z_g^@*!&^3%_n;QOr~0E<(ocp?lZNfiI`gbo*A`Z&IxrD-W4B%B9*;vCu8rQuS=Tk7 zTTZovSHD)#gV76>X=5hKg9rLgi1UGvKv1?mMOND5G$+!s+hrwr{BAIcqpUEJSE{gM z!;Gz{I_7By6UoikC{EG>i*yb>1b2>O58sHg^oKQO&qIG@a4TK6BnP~j!7ajS8#3B$a)1%e^bVMw{ZM}+rT}dh2h8*s@&GN+uaJ-`(Mhv?1sKi9GsH@_nXI( zkH?Q(*Hg=Rb)Yo%2Dix<-C@tW9qHdFHl`M*v0lda(CfaF)&3@Fn%(9BxHM6hy+-p4 z-gLp9v_Ak*VRcf+w~uhFaakfOcpmo!Q*^7Y8aNKQoZvY8(?M2lTBkw023db6o$hMI zjTuU=xUC|aNcHm9D_9hy4r%XoUJ5yH*Q~&P>siqaMjzHar?*{o>&LHkUH=D-J%3cI z_Yt6R5ef_6)q{3Pf2nt#I+m^C`c}`d^>97#&+j?6{3>l7Tgb4OGvuQg@u)~&c{vpe z>hf=09waBy zCV_60>L^JX#f_BSZDP#umGM53dPphLZLX8u9?`Q%`>kFzkt+zP^PR|=A2wlK=0XMa z%1Flxq$K{7dfA6Z&QB#v;(tvXxurxFVc+SwLG>J<#jHy{z9|yL#w*rB0rV8x7lh$0 z@0Nu(k?|bV4F}t-K(B7;oT~_`Rt}+R<%FuWzm>mBEO`SZFf9n)gKZ}l7=u*EpX~B$ ziqZ0s-LiA%hyNa-AAya1iYD*pq2gA}<0^q>)L*~7$MOha79e;$>u^v`c^m;RGbe1d zs#yP(-i+AxueFRg78U6x!QJG3A)75*I9r`6u2mDs@LcRg{M*y%0~VK58e^A0;#Hdi zT=}{D6H~a`e73(pOEy1&z-34WT*C!6Vn%ji7qD=+T&Jr3+|f*uZLLV_JiS8QfkaLJ z6lBIqn*9i0(cuHBl(Ft) zj%vA|t1F!E$meyB2d0h;%sh>HI8fmjND=$gJ*xvJ=7AXk(v6tBCSW@{$V?|*-9+C4UqOcMD)g&FbeWbLcSR#fy4&2TVVFrq{a2Euip#GeUw z?1+8ZQkQe$2~1^r`e}9sxwBkWQ#;4}TP^pme*)dR0&Apn?P!HuHaVD}CVi4l`Wd%> zeDv_v?NnyG@>c;TGrwB^-8?tkB!EsYka?EKHfFT!7T`6c_os@2`X~kJq2I!@n-^kKkVH6aVT-4V&tYqRSTut=QXquNFeasGKX* zSZv-vQP9rd%>3IfRq$Kqg&4c0VC-GT@0EB<+_L_Y%V!L~IpH$;)v7(0;_iDJ@FbCY7l=}#3w}Hf1?<_% zzO7*DSE(Kwme9@vm$5VeM)_Ycm+S;}Yir&kYl?K&?(c~GyW5t3Dra@D`YXabsx%oO za=d<1RjlkH=2+L1=A>xx??#AAR$gfhht-ftaHK9hvc`w^OTGx3Pf)U{ih*ZB_E=i0 zm*@2&l@BZ&p+d$Q&s;tqOjhEVqD!=njGn7~0~ZDOON9)`vJ>+ufb8%5)7#Rt3!JCL zwLGme_iA{`e<~Urx=CtQu|96aV(8zyRj(!E@`c7=EY%Ow?Sii|E>}_RdmEa7_u@U} zd55lAXNHH4-gMKYJ-E?V+#*}VCjh!~d;_@CX5{uIuo5s{Va##PdG{?+kQ1DVDhh3Y zKhCN_h(Adft;^I`ccw79~g^u}CO>PV#uc57fHCf@ktl0>-?EHZHoi>2a|WGq+|)c*n7 zdW#T86_r~sa@2mP?pI8=3svMas`B08^3ZzG4?li9QA32^6iu5<>hL`+tWeAEnKw1= z%KiNCprjw|QnMzrr%HXW#*k4uK$N#sK39M%R)$cSBT(uAR1>f=E-`G2;a&o&zUjV{zz;a&n3@QSE zIIKks5TNR4ZB>$|p)KUolmY(ZUY8=en*$H}zQW%zk20TN-2Iw3va0v~|QAlO^P7ReAz&SkSN57N`|hg^ZO_$)skQ5;&| znWx9I3wG~i!;0vKjY@a8utU3%amhwb~#T`9YXMT3^JJy*Ge7vfqiWHnjHKPHCADxOZGZ`A#kV1GH8p*9aP+F|XoU z&hiKdD{IW8ImF<-zkD2|{*WSt=IEL_g6i0BKuHcBT3!E0g3w_40&XTbeVsnC4KN z(XE{(iIdx>hhG&36W=mC$_8^2bdortXGmObvG4bd)eoLI#*c)>L`sT#4HXXKv5dEwEG#L`b$us4qP8alu=G?(z`Cn&-|K**h~e3HQW+TDaC zkDR&L-pM1&fpnsS=kJzgVH^_lNzJj_2YkY73s%w-#>+3YrPK6YR|mARe#gBSNa1S8*k-qDw@!X zto+Pw5{i^!ohuNcRP?!PGotHs!PS-+9gEp{Tzm>27O=(ah$n)%pLC2}Kb$G_1s|c7 z5PXQi4+z8X&eE@LZrl)z!^T_10IE(uXXRD2pH%dDm)zfTt>3OVRr#ubwU{BG@rEF! zqj&4Oa&P#%(#A#{@VA)i-hU$#CHmMv9=3?+3H|*rjlsj5G#!2ixAo?e)qhunY>Ecq zig;kA4uKKRxLC+e&o9wttZLG1Q=#?*sgL}`7lec;&?%Z6-(_DRGI(5eKOYHlW4!FA zD)FW#eKr_tuob%Jp>ln@QXJD@6-Kz>2rkI+$(1-52P^QuJb-VCx8=M zEqN_l6r<`JGXA@PK{c^B0VDEk6l9j73jQecfy{(x3>8-W<4i}aCbms>Hx@`*n`4CA zzHGBI}N+{WI+Zdwhv&-yy~Z>4Yb zC}LzhH}hF#gRt!*fNsRMZ{q*FJDoX4(s1=s>w7s zAZMYxKzV@2Zti8mZI@22J=5NA+C|Z$v4h?$P7rqX-mJcaQQA)7 zUGA~C0S$-Mm6QA7)!}PWK$tggm335q+Ub*FQ*?GTI0xQ=*5djbT~Qi?hs65K6KS$m zFyiOs7VvwA3sJ%cE_3I=kc;o-Vt4Tv`ShoE?Ty>RfG5g7>0pbB`V551;0n|4$Ui|h zr7ihY^vP^=S(VEoy$$BT zD$(qH(zzbnl=5Q$A&Zw_9u0)s%{;CI{(dt(Li4Am^z7tnASF37TNb(V;FaU^t%`TD zuz|PyI&-UjNHsC<2pQiv=iTjLzUd7hxaIf*sZnAT7inhkZ}I zofPhEsf3~_EM&XPQt^?(p1u-ne{yo**0N__K@)pwu=A}~lA7h2;zBWN zN3z`_GG23T)Ihbg+)NJra#lHNKnWj6%$|y9xkxMN`g2u1;1cbjn$AJsRjSHE^ZE~@ z(?T(J&_CuT$r$$}j_8WhwU^^nA3a!uK_}S<_$frzRA;77hUeNN(=^{m2bx{dAuN(r z$sWnLuy#0YpdM!cq7CW6-NI5s#f)o3G#tvSue{-K*tPqPU7Y5K zW*f6Mxbcx+&>rd2O>Ge=JeGXOQER=b|JEM}kWKN^Rg?2T@iM1tJ~8Il`LRc?J?`kZ zxk_6QWj9^>43!ff>U9p-2GwkewLLD2@-3^ni_Dpyqwk$$pAIyjzuwMi<^+79d4rh5P z3FVYW0O_Wgd^&Xu?8RxY*kMDjYo1{Y)(>JmHEzkeaaa?EtK+xq6bbFo|C$DAzhe2e zAG!`oP5ue|Xf5hz{;7rSVl#cP@D{vFiQ)A7s{YNChe~=c7@FV1NF2oOHZ9LycXnF% zaM@gv_wy-J{zj~w8Y3aN7X%eczWbz;Hh zD;HBQ?Qy&Gq^cFqi;TpG!PnKgcl(iZ0Fi186h;xw%>$kV*8Yzh?}-5@q~mlx7MZ3r z!?hnw4)e1KV8M$Wo-Y%rFu+oO@!RXI_q-^poFx&mIWVmkL^6OUvrvLPj+v;$cbKxw z{%pvi5qBY(WPQrj$CgLaUU%I5k}W2;tmZk@NKnz80{yms zbj0k$M6$CF19)Qr7U3ea#2z&uA>^ZC%s5TLGJV!d-^;^N=IA%+t5+VXEyjBq1)$3Nv_4 zN|z2y`7wV89-A=vRFb{;q~))jyfg;9gx}Z)B*>?XTJL`;uILaM1oWBN%h_7G^&0KZ zD{THEKpHFo;?=IO9YFDyg-TwKZs=Z6tcDrt8EUM1`ycX{TT&Njc2yq3@4fND8-;yeMhT~sIE_gVv* zp6~o3Yr(=7>h?Ez0d$ZfBd9KZ8!=7Bm7yB2TdKF2YX`hHR53F52Go>YZZTbSQ2$Zv z(e53mW3D7^mKP&k1yh9l0G+l|{?>K%Wn{`kUT;~;WnR7`np+V>Qx zIy&;N@273s9C|fBjjX1j)d|Dx6|^4{?DCYaPA8MFcb))dmO!pNBKG;s^uEarl%^|R zhvq~qv#<@KL{F(Twv3kv=Z}p|76<~5J^O96rtE;ycz1{Q>EV&{*X zd-z}4(LM$7vr(=Z^+Sc8l`UZ391qS#H| zLa%o^=#Fn7n5U@Qr&kL`6EDzQRABhw=VW%L6~#Nuth&Q3?9}-VBV6*991eAqiU*Rt zcR@U}oaO8UBX-fLo#8vyJ54EIz3nL^BqaK|ZQl3L1l}SMfR;<(zM`a?wc#Njwli+- z5nG-Px1YKKGr%QX9&4uM6Z|nCVa6|N;skZ&VUbIxKgq56m7BDxUPr!@;*hQ;^=_K! zcs$m<6!k&DDJ-U{0Wpwvp4Rq4M=2@oMZJOO@^XG?iRVW^8fl$`JR!79w>Zl?N#u1z9E+#wm{1M>?O8$U8Sz%uMZU7!C2H3sO&@l{Tm zc*87BR1F6+y(ybD{{gl>*DX!=Q=Iqgi=x|if)}E8cTz1Z_3~A6CM)(5e&({=I@qZ^ zl4I*Wb&@PPhnJ!K0cuSbd1viynCO#m5W>J|`r%;H(AQ$*CNbXw2(I6SJD@K+0=nvP z!O~+oVPlef`b`d>K%j(pzjd=sA70$sXt8YH)f)XQ^{V!I1 zLfxg%4-)v3sARG57FX(txw*vVlnLz@^8XAT#i|SC{xOuep`FBM`n4p^eQk>4r7&gG z%z0xM@&-FFdG$Va!z_*WSx+xx{qZB1ksFYVR;j1umsuo3-L0w%nbw`SiqSQ5LHjP( zd&^(_7$q6H0kt`oCYBNwz@q2yZ4#JQH+D}(r9M9+be0Qbz-=s%e9<%HEv16IR#1?c zp#F<0t0QHdXyuz~>JX~V!)qrjHBe)ayDTvPb^wv3&j`1{YNQ*F@q3v-U8a>v)5CTp z44w3L486F!e?K=-pP8Y2@1;B2NSBW!p?81WEz&&kUoWx075SU$`c11F>ME^k2agoe z0!q3r3o;gbs{TbC%mG~TfUYx_ELp)8o$5FOK7C##q{3)zuogf3*Yd4{V zghz#IcB$LTTlKM%I14SD)L4Nf5bL1wU=t0MG`&yYR%#qK=6L$8OvP5%C=>BH=Pu0S zapL6EndA#BBJVo=V&daDzmu+ zShfMv%)U&q6;^uY{Q*PR^*BiXq(?yS`zRB0qpfnRS82hL;M5<*c8;m(E6cS{WSg=4 zA#*|sJNqkYTMZX9cEJ_Ba*>bB{^jsz;OESkLYoFw6G+h>F0R1Dp-`aBz>Q!< zlR55*KsUNHCEwF=gqU$1xGaFiSMFT$oY@Ov_9)?BuN3p>Aa)dCC65r0#PUVz`b&G` zFaBnyJ4Lpv|1moMQlKP}t}jK?*Xn;+0LeUfJL&DMOVGJVG!(1oSh?m$cklVBI;6(@ z(Ms%EqD`N@=5&L=_Z?(q3h|M^o|5q2sI6(%e5&OI#Id$mwH<4046^3KrRh+|!Av}- zSl5|G0SsmHzkd(a1$*UkSdYq^7Cq3yoWq2-ocO)fXe+9YoPgOoI}%eq9-&KW$;%k^ zi2+31NsaCIb%c;Of_^6Rtl(=1dSSz!v;NO5(xl90Rc_K)DRW+LY^Na7h2P@$st;bE;JJy z&I95#^Om@&9Ybm3VUqGqd}i@Dy8o7D(ydW~$QM6ZmihB^2y={dS=OSJjT0r}Cnk-G zgJ@Wd+9}FX432edbiOsA4-J{)kFsW%4Rbv&6bLOy2vGS}F-OVPf9cX|0tpk1QfogY zrcEI5#MvZ!bOC!8G-)Bo=%1x3*eX~*<;&RW2>CXWIh(WZp+US!aRuPC$e#%{ssv^d zWJVo~C}BFv)U$po-eo;>aNJJC8!bkMlEDn+u=H}&XXYEqfH@<^y z>@X)|@n=JDoMTiGwS6N|2HvG6Q;pi)m9k}1SQh0U4hI1F482jDxv!)+vdbWDZz^;- zKq$^tn6Ejo*!62)Nz8&gC6?KvE%p~;r#$u@=zBPjhCe)z*4)H*(&kq|Uwf~#Ky7nr zCqmArleDBjjE&1<^bOOOR6;l=yff{o+VeXFs|y9Vff&3s@nnPGP7O>Zta`Fr+D{Nc zCh9o&%#N7-`ZID95dvgIVlcjRP?|7n{3_1;f!o8I1UtK*1J^v7inLqWP;M@SW`c5C z7WaU?=A4_$oMYp14)dsApU0$9%kqzv2| zY$50rM_SjLkf$uwjkfd(#{-W)Jx>&!^<}s&uV`n#bs>T8Qy~R1)f#KwC@?(oQ>ei* znQgs64;Wc*oEceLR0;ZN3*=|=fbSO`EZ@)~kg?W03uQ^NDDL^7^$QmL0!M(88%??U zIXw3eiW`UR0w<*vwjSSTX`Ve-zzo*fmc;FXyjXSA`Ip4m!gZ3D_vr#8pWk%< zM$RmKhTRa&&f)kE#%BIFyN$&qkJCUvpJ+}$JEnpHr}419a@Nr$mcp-7%0smpYgG2q zEt41HAUXcwhka;aI>x@I=8R}x%AX=)u+?wmt5goDh~-Aafz?)nAHLxQ?^%MGCiyBw zfToKFr@Ger46{wmPK-D!&JD0?BR8D~Fv!IR$JR2m5F=(eFF)WVvF-Ty_bdOi6J0>M z3YXdDp#=JtW@2m2M->kN~ zb{=fBUj>xMX+IuW6L3N~FW^PqO+0#e>C9$x4P+kuXrAvQX_3QPe=9E{T46RT4g$Y< z4){T`{DG=@mY%P{BgX1thIE)Rvu@jb?awf881bRUobaa@mY*|67Us7ica_GHhI}ve z*Lp4mDn#4Sr4gibT%d6d&{iQ-Ljy3u|DgWzu=p6BnfRkpiR22Ga~t!LZ<%p_x#{b{ zvb!5d|*TqYat+2Y;XrRjiQ1S3-=uOnWviBB{`LT#XEaMecYU!J#2KxC zHwl6oHW&;KW7JUxE{dd_@%u2^ILN#wj5wRJn?X6%fpMr5=&|p&4LCChX9sGtq{d%S zn^3?7bWMkfm2&z?056{>=pxA8y#_=Cg%XJLqzG+#Qjy88Hb|jc?zsg_Z5;?{#y3)I|B-gwpi7F6T2CQr&=J-JN!O$7s4uVAq z6)&!d_}xT6XL<;C018q&4VJ;51u#GJj(zx_wd?(_Hq)r`PmoxA#!e-E;;5+WAlhUi z6g-3!h%*_Mc8rZ*qhk*7lkuJgVmTxZvf1W_I@KA`!eys;=gy)Rk2AP3ZzK+y|hQk|(h**lQ) z=EnUFAUz%AJ{_cD(Mm*c@DMq3%Zt?BmA-Fj#~>Z@4q6hYO@_9s+*0M`Mu;cmAkV;< zk}?)NUq$KxMu?(z)@M-QtFU_}MgAg@`FGG0>!U=y%T)e7)wS9M^YK;i%KSdYUqH z)7QiK*9Dt%I$z)R$g`sTS9HtA?Qi|ge3SCvDIG0g;#H=qwtv={e*rcO_KKZxjsOC* zG2|sScn0qP!XMnG?l(+YtqUSU*O^d8*{*D+;YTFIE9Y6g`kOufPD!S{3px*hmM2iC zs1pyQg_?&UGSDnBa#N#pUR8rH9*Gu8R~ME@Oo#)ezO~zbmVE68>^U6^oam>5T6~bF zPCcWGugRa=IZd*aixMq(QTd}pnasLf(vk-Nj#_@2IE((CvPor98HGM)?DjW1b4RGe z^173GCV9ZC%NObgXpRSN<&lco)>>3zZjz^_Snl0wY&1WXB|TWJ##6r?BHU)|#G>S@ zg|E0XPcPNh>P`+!!sl}zlN@mdh!Xv+IKe2UlLKFQ_vu!XkE}H44F(Y`ATjE1S-%yq zqwI1B9=7YT)Yo}fTv_myq%|u*K~`rPC|zB%9ap4^Oh1AA0WSBb9|L*b2Nx4hninUU zex|EghP*h7<>dtN2!xB&8Mt-{e#OMZmT7yS>zO@}B@aOOf@FcTwWh8n?QAfHki=*C zf}4~|kP7X?tjYY^IfR3y@v$9xK0ZQ}D6>k15+B~Otn;!unCSR^zODAH51`4Xzl{P! zrqKH?B@4S@{&+xalYPGaFSdjM$O^bUm`cjZsL=7L45T1Vz@HjG4Yo>AqVlWFWtXzJ z8iw6~K*jGj*n*w#HF!UiMRFclKrz9DV~OuK}8B9|v1?f`m9>q2>fA|nco68x(O zCQeR(yM7AWbU#$il*~BU;p>*pU*8gxieisY3D}xe4X6^X*K|r%5(*}gi{5L|w~f}q z9ReRH!4E0rBItKv%XHcf-;7>NemS3yYw>N1!MQ~p-R^pz z)@40|009Kszi+hI=-vT}8#H{#m|7l`BcKNu>miQJNOwgmUplw00=x zN;jXJlX)d5#t8LC`FMQG5CumgaJXjq1R0ance*$FI!mn@WUj3nts;41ws$ywe?GOvR+`GZJPP#zpO9d zsQ2O3urGH=Q6F7-^PNBG9%s1>31#X5a22UTj*)wKNq`mnIsZ(`D0mQZOD$+jYh>bw z*2n=dbhLro!t&6}@ld3g@>m%Ke}x~*ey^0;1?f!7lK~;1#w3QjM(gE0Nhr2CO?9ix&hna zP0Rx{%SW=id7!E6IpaVo)~+A;aJwE4zC9qid3E*@e=(Dfp-Fy!86PblxGu`h#e+6H z1lNc4V=H?pAABT4tIsf`9{Taw$qD7YNbft$HN#-isxzAGq5XefWFQml<0(;l-kfbb zoP~JeYW`HX`~jh%>aZur9~~CX;y*r2hYs|J0K7QfM3E)Q349{JgBTcgAhYx5{Wm+qz|{NW=4 zhZBH7&b>?wsj z%`ST)EscllSBNC{*ve0ilcr*4tf~G2n-Z`VC$SA=;vXS}Xd-0s&9>dA&3n%#ZPklv z-fBx_h;M!WLZkjIo+dBWG`{1=I2bf-zT)IUla!EjR09^=?x0IbbJfd&G){6MA_v?n! z0;6KHSs#2n>u8b9IvAZUG3GFZ)Rr4E$rE%c`lu@HNSZ9gKppC3Swwa{J6b~ck3_(| zZ>mnTB3;^{ixK_Na~5DSXPkA!^kVgsK7qJ@`WEbor!T&a8iJcuoTRieh-jT^1yZ&rzVb%`6`3wmhSa(72u(k*=`*p#>a; z8uQratQ28%MD+q5nH;=_hou)>M9iMqvi6Xn6;S?Z&+@3S{ECn2Qw|(Ka5(aDBbKT| z>px5=2}&t7;-zKb5rvth8z``i)Ga*3zqZ-RQ4mS`1xt_!f&{oI0VOJtJHSfay18V++9Gk3a z*hW{DliP(B`$xPW2FQRAVTDJ-XZ-*~*?RYMRePv{Vq;Vz>7IXQzGmm9s;M!~&wq+K zv?R`n6rf0PXGwWZeHx@&3Df-|3o3xhkeK77S;6pyM8<#LT1_2vHEJ?n*Hh213nvlt z;Q<`TAD}+pCP6ZkMNUwN%xSQ-dEFh+EixULQHsVC!XrDY$I^hCp1`}R28bG55n4Ep za^L)me4-WX!Y0Bx1?ILKGz51wI5nXJkuFC;|3INA#HQtOEO=r=v=d@kcv{ox&et0q z`x$u7j_#Gg!2@r|^}K2MQ2woQAH$I?v_-pJ2Y;H)+DZyUv4kX`x7s%`N-^Gr*_=%v z^yA3i`4z*UG%9PUZ6}HAOMsaHe-s2~9C%Gl?vQ3z`T@Ui@wcusRBuk6UNPS1Nnj+J znKCh29TbpbHXWeYAPTFb-bJ{^=G~!q+%8@+uE)@2JvH6hP$y-XNlrZ#EC%n4TC4N$ zG@hScU)0;1@p9H`+H6)e9wjJD2+i39;UK0tYhXdtJZ*9j=vDd86Vi+}H<%`AYc?BD z=T~AWt&9xOQ@ZpDPWKimR({&)vSLQ_3+GoxM?+8$c#J5K)Ep(@v(R3Xufel z(AV1jX${5_kTNU5Jl$a*^6y!33P}QJNg+p~dtp1pf>)RP>_W65g!>y#qwzoJi$Tyg zPBGjMznC(}f%ew;ZBje_}gzp|1bVg=tl89_OX`)@Vp1!x$$4H@*r7y&6g$5lOJoF(8g!W zst7)wFeV#UcQ+@W7EJHhwQAcLT*!WOn;Z>Ov3}&QGe08!zCbXP>Cte`( zu6?S+@|J7^k8hIy`hU4|@`;~6f6m3M_$?tGg06m+@RE=JKJYOim803Ne5JXFb}V<$ z&oyTeA%z`xQ4^IgS@jD(^iz14VVxOLF^;>1#O@-;2 zVqB!<<5VE?q?Mc9j_bwOhn|AS4!X&=)_80t9=W0S@IM(5*zF2nw-d%zMWT?d$pVm5 zZ?*%tkcKV6e)V*?ltB~Bt$fuj#J#QBX=71uy@FEV*lYIP57+N5A#0BvYnvM>+Zl&0 zd}{nGH~0DOkD=_CILHj;f&;(f7bJr_QZD{Wc*YjWW@frWW{M`S_4h34mz6BPGo1kN zQ)&>nkf@lxGa57+NC#jf&Qtgkt@J)tC|#YlH1Dbx2SW2s+wL`K2PDHZ0xQ=mMHaDF zK2sacav;SBBb$x%<(6ZemJ?)y5g#`?kOESpx;qKsGO|;1R$ZIs5?bEc5n*5V zLlXxdUjkE_?@HeP4#FCN54~s&A>N{>t77w z%xkZq9)0u+9_iOf6rS~bbVBCe;3QqpKMi^MXi*)aPJD=hl&nm12=>6dFXq(7cpNow zGR=Ehm4TTv@yCCm`GHmhUSKjO)|~M9K%L%~j5u`a!Qveb06rs)=zF>vO#iq*C%?e> zF)NE<{Gh=1`Vk^;4Z$fAUt3yao=93vkjYfgJ8>6j2oI4h+eRfTI&D2>GFtp;1y-im zF9P^}FkGNwzf%8KQ6FUc0(HV_X5o#0>2i_eX7EGhESb2IIgl{F^*rYyi^4J&u&)RJ zFX?SQG**rhTaDbfxN%s?;Ihg$Opf#OHf&7xc-##8A+x%41Ja(3o%<{2P}&vy%mZ?pih-S1~VzHxn1Ja%j&2%ON# zm}4qolOd2$02c5+aJ~8D4R}=v0my>Q`~bvf;1mPCc@rh_G)J!yMQTkxmooRMdBBF4OJU7&0{Vr{gzbHZN5r{EG;q202Ec z?0gSZ1^I1&s3+`D2Vy28L(Igu=N2|!lp*vB-Bqz{^{ZG(7QH{e5Pc>FRBKIwPCRbI zHA2l!^$l`Uf9`$o%Z!?#ED!7_x#3gcq{j~&$!S!uvrMxO$lFz*wp_Uhk_zv@MJp-> z0|FsiOI$xUrG4kMsl;#}KPW6ek4de-BFgZ5Qy(05H{j!-Qb9VIP^@wZgypNmZ zN3Rvp6W+RHL7V7zRt9JY$RNB~E>6}?lTA?SiS#{wJNnSw0#cpF?XG`BqbqX+Clrht z9jaqFHurWIJoFR#eX8rD?|^BDC+HWW0&C8-U<^H~oHlinmE;IW0oa^fCrthqyz_~W zfEph4uI6ka3Vvwz6#`cHmM>ljWoX92K5`=7T0682Fn(kW<%iWpm6lEqafeoac`1wj z6XIh>HO29FxJS|8;I{|lHD|daPJBP&C`<-(ho8#*R}1tGj;ip#B&qUFP*lr1Kk`fy zb|yO!@!{q){`5=KX6@^lEneu>r=h}+ipr!;WHLE_2Q(-CY#bg^V=(3*gk79el9v6? zmN)JzjG*2E_=V+grI6rGC!AUe!hcKgu|SRh7Fy(i$n*MEJu5WhBpfJiHh5ow8!#HW zF4U(IV1Vg~Q?>fl%qJ3h1St;P|UPb#3xlpZXfUA0acsz z@dkkx2Y>&ca|8B9A|Y~pu^P|QQ;3e%>v7bfY8wbdTMIiB@JYMLDb{avZ4|wx5nK+D z>e@y6$VG`Cn&WAvG-H3JK$;vQzt&E66c*p2vIYvIbNELp{~kk2<=G^N%Ll_Bt^Q9X zW=Fe_iJ$isp4*t&j^P-Vvy!>_tUO%P$(C)%+(fmewj$)jg6-bmFEj@mA5qgm`#1jO z6v)6&;Q-C4H(rw=Qs7?w$NPfs-%Thf;ZdI`|95Cw1c;p%UN0BJK&UYSeND<)9jQ|M zy9XswhoG2ZDN;Dq)=&BS;kf4cAgk*=r5s8@_=)C_G`5Bv7H*nNxbEm}`#A36Q@>nwLIc$~v?hy?e z3Oi44!}l)=ZGb2cg>t~Au{dw)1Yh{1mP)V`5z;Rgs=Z%iVV9LK(w7fFnmre5R^DPe zbsy7fKbGoC!<`#A-pZWLzXL>fUeF^w)^jw}lO~b7;x*dz9iL12{TR2ug~Eu-O-&?F zfh_!jm3F-%P8AY(Cy;E_92T=nK)TtN2&uhMo(9_V7fQ1!2uN!6|A7rQ$Kh-=&^Cc} z`Yq<89EoB)5?R1dKF>O|qjE^jod%uD8rshvAv*}REc=Z#7Aic|JdBcm& zAR;6RV)8ncKT)@AOJcpMp#W76UVd{~c?rBU>hV8ybIUH_r31UspMAIqzxgxyLN%VW z=ggYe!RJ<)+^idPuU^p<;rg!Q@b9&gB`+qw^lJl}7@{0J(Cb!cuyHu#I)?VZCdRIH zg)nzMsN-;y>n*|#R3ZNs^G+52hE>K{fQnTWqfJ(Jl>6ev9J7| z0)czJI0eT~Yg5p==Moql`P{)}AyobgHd9k2oQ}(z%Xy8C!)K559Id2f=0rZKrFs5n z$8n{3H736Qqat{rK-8w@W7cjRGJhz8a%WaK^!5Y=ldZlj4{l(rkMrI`Z-@PC*}q@6 zCf~++lb-7v*5a;Slj;77bq14Wl7A7BKL5wlRYyhrJ?*7C6eOfU36WMnY6&Tk5+$W2 zB&C~O8fgWjB?T0a?pjJ(y1Tm@mfiQW`2D@-@P`LHXYbxScjkGXnLERn0ZbNvzSjr> zNa0bLi=&tm|CXf#33i7p@A#3%`Q-a_{JMT zC67=`sHPF*Rh~)wZNjj_e`*W7Gy(ch?1)5(lHgz*1Mpwo5@UF`x|*f%Vm}}WFyVuO z|C}Xh5->$9g0RNVT^aNYI&K_$c$FhFbpP&4pP}BDH6scHrpN>U2S-AQbZuX_E1=qsuK3-~ESm4D|547+@{7%tTXif#ZJ=ht8K)a!Jo!wcbqvlYlk+rxJ% zSQ(kkvm1hxi4a?_9vi9<-!tA^bN-l;5G@R;8(p$3ez;(Yy_$|&@qip9tT0;4LF6VoA#VZhl@~(` zM=pnE6U&S%^5w`V&3M=K`5K1oT@!cD%qY~8E}NvO|C%~rrq29p{?)poj5v)38CWEY z2jp=k?SqZ=a~A;RscQGXj@7VFsL4|6x3%+b<50u0Yfmr?8hz8&fdD%=H@y8rP7p#9!| z*kPf11hHh=QgqC;Y`VZ%CoqY%&Rk9E(PuH6mzi*-KRGCet>Z+<-n$_{!gRBAlH5K8 z+5X6!twfc6Kc(5XTa(+7IW82oU%weGHDw4osSM~dsOCHAy!EzqL8D~F!Zw0%)0Ppq6 zq36X#ZpZ3EZm0dY2Zxm1Fm&j~A0VOc2q=@?0FC9@STOzn@s+u#mpAw!_fg*(=!m0| zE}k%VcDc2yYB2X*__}Fg{@zR9MDE@b{@~CNl|bi=q>a5yr{2K?BI-O~1QDz$RwKVW zR8Kq4R^&ZeOy0*yZFlVukrM&5-5pS3*Rsn>=1?9YQS;yB;1&B9X4**F;;WV8mLI78kXlH6ojj=9M6vjKXC^;dWa~rc@PN>Tto^wU{f>k8F+b~i;AR{6s*|#; z7@61HHGkrSWb)dJV?|qM)IiO-K>cizO3q>2eUugEZ_gdwb55kAp{vfa2FzKLPa^cB zGn(?awSb+cP~c_q-*d5>_4tX(wBw9)LEb{n0xO@Uxq*ev6tvgb;wQg)o)owZoh%GA z9kC%_c$wb3KVL(ho4cM2ApBU-dW`<{5yfT(rh;@JgR#pbtz^(YgAqaNPyWLU-#`d9 z3A#+- z9Ac1e9&dO^vH&zLOGh$$jif>hAeR9eQ%LyYfjM#k+|>H?Km7=U3}`Mtb0s5Q!u1A> z>a5bfAK0&a!&`mVG;-4q)_i#|QI=k<2*tpFtE#P$&}|QPlkBkcH@r>Nn{MGLt! z$71ZqsEHf@b{z@>Mf;$G!(rdWyR2;ry#jO6Ae4wo(wr33}Il%BeGqaDD9Z|(MH0S?hpu<(q9j8 z;K_T6pa2xHJ@Cyd*C(G4Q}z`%BMgmSZi~S;@>4tZ+iG+CQ9XC%MNPPy0#KhXzkkdB zZ@vTI{2%*q&I9QI9_P2&y7(7W%ql59v>r?E;wZ;CUWM%C z7!3&n~oYFMRF{r#^VI5(M_<_Ubu@r@QtdIMQ!f19+yAKthND9`oXcYwUvm zdOK4=f%;Bi(CLdOEa3hAq2J5;sJ`I(3UN&6%%lK~%#C%W0##wOi;+Q99@ed_0JCgT z)*6EM1_gsSE37pcrYCpK828T@qZkbHB7fJ})>beuv7s{teEc>MAASw!f=J)3BRH)2 z$zIE1^zLgYa&5)1&o@T^?H8j49ct76>p1lcdm7yK!}v=f@GI>X=*WOHJZJzK&;BI@ zTO^mB9l1I5*^Dl*t4($23|W4$zVz+gSmUNxsz_c&*l*Am)(KFUe^~yIHJq(B`A@qg zyy>Fxz{7r&hD;rH@uPOz%R@CXj5+cl(M1zm>F3WRae-CrVNV`zNs(n6kV%IsoDq?a zrT^Z3o3`G+kh)WSKIv54IIy4MdCye5eM4q0H^Fbk&Q(Q44d@9@{UB8K zIEU8gyHj8l7j-5^%s?n9DZ0`_KS4;p-mtdSp|m6}uAiU$;yYhusQtATCcV~Mo$(hU zdND1Szf1BQ^$OKVp2f?I^U!pHbP1TZE0e3wFuw1_RXxlz_F|2pK8|YUg43Mq7=0Qh z7^uyo_ncKG7dub?CGZ%bw{p~y3`#I4pI82<3?=8U3_^W0oxG$q$eDII7z4=O8+VCV ze_HMO@)tYC4Yf8HI&NyY)ucXhT76@Id~(p7fR`$(pU#%TJf>7QAeClsYTv@DbNI8^ zXDkP1a~lC)Hj{}p0i|{dxOe+P&-U><*{vEny*XfPx%QGhq6m*KGh(uo$aBFdcK{=Uv0NB0%`R2n?U?{`Pq16AOA;qaB*r z@BctpN`-oQ(vnQ?_BNr`@%5H=qIlI2 zDfm;Y%luV!rpB)Dx{E05EQ7ai(Ksd}W7fYhxAVg{HgSHy#z-^DEG`QK z&m|aYTsc8cWx}y2{mN}AersYkR_H6sr8j1{rY^qtmi6B1?7JTw zjUx=c=rNC56#dK{TkR35zQz{XhxTF~V}{!UCephZGPUtT=V(YLP$6CkGUGcYBkSEN z{8X4T(m~Gm=hnS}I>#5YBIZA;LC%D_FDTHZGw?9E4^`3O{WMP~u|Isl>Pg!lQX$aV z)}uSl`ANKXEBWGkR@VKiu@o;Z@zW_p#T*%JS>UnBLba`*>Wh!CR^qId9M#Fn5%DY7 z%JTy_WolV8Fah)yQPiA1$F3>ZMd6kAR?J@2Ml1KChhVswB3uZ zzg}$vTOx^jdLNDa^~UvcwBIMH=#$UUY?xltGg!fmSoX~J&;FSI=IE$-Lp^hLt#TIn zVC_&oebW?dHo8M?Cfzl{HrCy6_^TNLIdnj#AZxKgdc`D_!ydTqDxFOLhK`sRD0KBY zbA{sfJ-Yj-3ZTptZBXUe%!(2jXs@Nz)}R8{XeJ|$1z6;CD6HUi2JN@USg77w@k91s zYHCwizald|m!EJw+Pf4VF2wjP8k^Aqx^U`i%!AhE9hm-C|}uIQ_s0 z>=4_%n#%~Y{knF&$4y+!Ki3Jr(k?&stP2_}hs zd&tT{M6;D3)yXgMf%vs+SA!1i5}wsW9zDrH5y-A-*iG)>V=9ZjfWwYOe)% zAGDmun0LO?g(-s#wC(@1;1wWFKba-K5nT!-%gDil24#K?2G$||axsgNq~6+4d|74x zq(DJ^scZSGPtKlydH!Jq-wa(boyUym?O_P5&S7j73$ah(WNp8#_bJ0{AP?d*4u`X} zw`zDvPBil?(bFM@k6$Fr20adgWcJ@6AHnt;P07RY(e5ruIPN7LG@Gj~#v|q4=1H-g zE&U#}CM7*Roi65Wd@isKB`Uv(2KS_!?Hwg+^iwkOO8gd2{8rD-H>(8vdNur%JsJzC zv{D}zdB;P$pcPICa9-ZJ5%6%fs zK^88~URMReslWQjpk;vyzAU%(kl)AzSlds@HZ)r_50_Efw3X#qvb6ahQvSwl-(49$Son zL662j4@dn*t)km!Lo&%?+(*n=s6+AlLwcCLHztux6f5-LdH$-+( z$UtaYv(nwgxD@-PM$^3g{qf&(^4Kpv*;gOP-5y0ru)FO9+-|)Dt!Y-z!5u`a>evpv z+Lc4Fkjr0sS6D$=ALnrs^X?ZNn@D!#Ja_br9&rB^D{{eJ@tEkn2CH=w;B`} ze8yHQ3KCjLe5NKBYuhMYU>9wFytp&EM(o&Ir&K)*5;X>y#a(aAtI?XT($jm#DMEE} zt_Z0YOCCxNwL%3SZLQ9Bq(n^1<6XH(T@1*DC>cF8G zV<4)8?MiX;HT`P5R*O#`BDozi|>eiM<8y0-$qy&(YM*Bs??Sy_v;EHhKl;8Czg!^o}+QsYg(g^wkrDE8B;iv0Rmg$5P}*%Gc#-03&Vz>zru#ow^uNkC za2npTwC&dGS!s{4kqO~1SYRh%uy%W02fo}*vqQFY%k}@@`OoMwHgMlwy&6Ahh(iHi zV6{)tG1Z`r!(hBmkr3I8G)zgRph(#yuFkiazUG{Nl(5vmiMxGF(zxcn zLHmpxspD@`-khS7b-8fbbustWeYcsm6lzx6wGy6=AsH&w{`!a<#+O9@ax$C(J7Rha zX}WA&gr)QNp%hx zD!OYwMv^H;3=CNpU{F^nt=h|AD3X4%OE6k*M3a_^$$l*)Ma}Lpsoj)Mlr)!b&*8*a zSzPhw5iF#V6&j@W&$Sc!B_&b&=6vfO+oVHn8r^x&7kPPkrU_lF+(41wI8Nd8$v;&3AO@F@j4Ry1(dcDJp-aQf+5UFdk5If-aFUBrDRlJ|s%wR^#oe%s2^+?@9C3(m}ng)2WgKzy&oNbZxRlNQ3KWWODK^;_|w; zo5Q{X$KU)5QaXPo?iQ9Zxu_kAaGTtbw*!~9%Qd!82Rm7e09VAwcL_gzAFSLO{W zu*2@lNQS3eETGvhTWcYSq^a@H?tZ<<1T`VBM)#(+Mkf^d2GPyW3|)zmIGE(iDGUxnrxS5O2T& z+)o1rzvatoJV`$8uK?gF!M*1m2|&hat;iZV;5l*WAAh3f%x*o(bCd5zDV|JvoCrUP zf2>HOcC4>l7iH9GchP(W0bVUu0>sqMP;>YMI%qh3E>9@yofJ92bu%R?{Ohrd-suPz zdvvjW{KC0j(<;~WkG=OoIN*^*wC=T9^LN-Da~Iy;vKg#szglyMf$jN*i(*np;tE#K z^+6&#ioXTIzRE0`0MX5`u?a};=oO+RW(j_n)uB4aZ!be{X8&vh`e>^tI?Oy`(5*5J z@YbCJ_{uxTkN%TP-l))!<|(PJtFMlW?l$WHlzfF4OrW@N$YLBh!e8uRBgiUzTJ(rD z`7rGVg%1_=^$8aaLrVkJ^woFk2mCtUYLWG~$smTBYdayAONGp)z<+m?5!2HTz=@uI z*R6bKn6OqVMHyg6WrIP!#D~?s_ZfZegF0xc)j;M%UAF0CXaoKc#|9&C)-uK9O0%x& zh5LU&diz>8$cZzOI+pHu4hFfeZZTefBMTQF4N>dZaD720>mk5@sRZ_;s8}kTegvB1 zV^Hg2XFJPcU-N5iK}$bS&z@c=o8^BjhIg3BIZ^YOgNsm`NT?f7X|!i?H-T^}+63H( zX49;QyZfL7Fmbhwn+{OZ>2?h(h@hMqpZdZVBm6A8A0Qa2Wzm(7XEJ2ZtC~~bp~!w@ zE)K&50m3*_0*ni_tI|G|roVad=Y8~b&b;7+AA=a4(RIX5YKI-8;o~kj z`>WE*zl|(iGB&DT!aHhqjnNkd6hVOzu8YfZ$QGaPp$W&5@%<_v$CU<8;K*$6KN*)j?W>a12;rjhd5zh@OID# ziHBcDTXFQi`@-f*&wgmmY2QKIb$RfGyo_0YrDv|ubl7Jzx&D?D9f*Y;vUjmi64#j$ zNE|v-9$;mo7=}nU4;SULSbr44F&bj}wExTaqJQEl9V3wq?b5jK#x#)XCwb|pAnWrf7g4r390`va zSp^VC5~TQ2>aAOzsIYH-?st(p=`kG3Z)wTcH<0@q6A@e(0JJGG`DB?wHJrbI#bX45 z@QVmkPKt3)!8pRUiDm{!B2cC2(_mA(!pAyVxwnI5*SF8IzHlLgkR`*1EW@{`PVG;1}V946-q8` zQcww3`a-eT`vG})mIU|^8<}uK%S8EHliBQTrXkg*i}_N|(H|_Bch^ojqX-qui$3)v z{R5GJLW6>6h~=z%ZVg3s({wpl5CzU623!3p{~hk+zx5A9tF9K{Da#D;w)w6Cizm{F zbemCY_8pmcbxkC&L@qIe{mUQq=j7KWUfjoVgJKhBblNzK-Q0RmJI-@uF4r>2o)s zDc?IlH5Sw+r0sNtI=duvOWdN$lBH(XnN%cVq7814Ac1`oVZHA+uOJfb>{BoELib)Y zcREV&W`-lO3|bz6MBI5Lxfmi}@mGde*f}$f3k*#j2r2LX4RL%9XDyZIRrlx-NSEVjl2A5^eXTSn)gQ3ON zr!-IrQT91F{+NZ#!H#q8jfm)DHk3hZGNBNi2tdIdWaCYwFf?&ABgfT zM?YQbzk%;gSM{E-FJ+9yjtmEY0SB8=#KP=O*(B3z z3@e>Jks)&1S8_4daftT(!Z27!cSD&LBp~W~qj_;~(XMri=I@@+^nucNDPu+76&)%e zcFrKQ`Qbi^(d7$J+CAQ4+{gyffu~abvlSeiWJzjFjyj@F(ijY}bAr8tX>`J*4NEaw z>I~$fYtG%iRid(Otx#ZtH4b}{Ssv0A8JeX65{ZReNqq7QD4QIr#4xctl5vn7)kk~fAOo0&h zJuxd|d~(}eU@AdPI@Tbai}3=;3FAWvoLyyD_TY@j+U z*EEOe!^)q372Xuk_|?|FPzH@gej`W4>mJxn&+<1jouG+>? zkHNi_uH_Bf<1>vsmGkS$UK8O{Y>)9RJclQ3tUJWMVxM#bwEV>W7^zyW>8#$W(-s^% zj=iS{zbuRunFmi%u?1tRdNiCJJf@PA8?w0q^Hj%#GeZGHn~f{9|DFsKX*#Y>(0~Pla11>J(aGxkMQyGP zZYpHEq<#oc8Q;)pJ*PO$V6PjFyp5yWDk(PPz*iEj7%EDcYcBSIHE;94UoBji|6qd@ zrz>j5yonI>36eO7^DVE1KE2PCNeaOwebz{|Ce9Z~@m!o{oF3Zzm6m`c`1_#{=7}L) zz*7Oj&Q6-lZoI(!_XwfWwij=t6DVI&exdfyX2-pi%A1wl(36lTHReUszelDTQXOtr z?hhJ^lPlPuP#YES#F9Y*D94cywQ=!&w_P5QASY5c%@es&s1DGFK~_w)&c@R?!$ zAVY@KSm?o0Rt|LnkIbgD5##-)`(RWez+%CD!10~Yogd*uh2aOMBBs_&tS+q32Eiz( zA%>(X=oxX!(>oWv{~XAS@LVfGW6OGC+)hUPt$#{Z&MsUntQ($L7`Bpct7s;%kBTd> z525K`>#0~Ty_{=c!?ibWbK=aY&T@}ZHR~7Ji*~C%gn{75f0OSvL2PhBXa%(QWgI zAygL9UMuW)eQ;mbZ7=Z?L(R6`EiKSaO%bq@O;b!b8K|4hn1QYS<(m;qNqZ9KCA_6{ z(BKWfm)Co8ec;QY$uGV~IzjE5eMdd+TPf4ahUBrJ_)uB`iZ z_xC|iCn7+FiWYw_KPX()ih;mpAy&L;fZ*-m8N|_NAg(0L?K~;uN38^W?a1kZHDK5o zM6pibU`+eVtUdC(G>M3euOFUI%Pn7LU@L?^2>iChLQ(p@cUE>d&9EwR?p`(Tv-G$< z3#(D%6mlRxaoF=*mnsGt3K%pmDeh%8=yaLIov~!=-B;i^B#sHbV*-5nf+UO?MVMi*wt%I@^i1J?!%jKuq^VqGvgmje-3c>JBDD8 z=?(rZK(dDgak?MyoR+r}mofeoHw}a8h3=*}b+HsXn}V-fRa{PS0xb2DS)p0T>*a&f z0j}^M$ag~u_KWz+o1l`#fsj9?<4KI;nC=S}`=gxbJMBtVfd4zCM?+FTvB6uO=_e)w zKnFT%;^zjI#~$&38DEy5_h3}qdXBNq=IlMzM;S>U16EZ`Fx;*; z)J~%>eI`{oOOkVCWFpx-pEaggoETrJEl#n@Vt17$5!vI^zzKHd0D-zcu~!bomj>Tq z{^{&Yxvkl;`mV$=$$a&yqJ}u>J4pL|r$#oQePvVwNe>`F_zlQ6IFy#{+46JARm;GH zo>a9IPnL=UfN9~1M76t|A+39Yhde746IVjIx%#BSSrz=O!Qo@uocABXHw)}j3CB_l zkQBpQ5)a-8h{+`TlHqI2z&z~1t#G&wBmqJp3*J9pxd+j>#JTBXxH2*~IrWzfLsMdX z5OV(w->bdi>>S*gD$yNTe2DadcWX0a5<;L z2(<6wONyW;W{4@8@VzrZ{XXV_DWAHhH@jwt7oETsvbYRr1U*Gm>IQTGO(nK683cOT(HK; zLy!=Pt^e<3miej7+thHOso-7OD)F_|(O_Df&%MXZO<2#2|HQ=WuVS zA(8}Kzq!ER8X-Nw`53aR2v?EJdbdB%(E#z=RU{66mq&dlXXIG6ZK07M@t8)%V~FPT zN-IM)8nOhs#f18ztA$3~$w+?V_i7GL{~_0vn_YaWFnO?;8hNFS7R^!VOm$s)u@^gJ z7rgDk2`5=uWJ-|xgCq*SF}r0v`V8&D(zDE>b{)GAu)A%UlH{^eR#HJ%-uO(R4f1&jG8b zVDR%#2TiIf^;Uyx#3+~tEes*}PVe8evdBjnHIyq^4L&SHk=TrI+zf^GJHFKf4ExBm z4wg2UJ&FwNc-l-?N>tYeK5stS51F-@DnNLLXwkO{To`bWZ}R@7{m?Gdixub9Z@F=E zFW|@#N2p3) z2NW7aFE1bsGik_IOwU`;$oW?yR!x47GBjS!tHo&X;c8xDh!?N8w0)2^VhYDEk$bar zgcvg0-z;UZ8>d8Gra=&)U}sWJ&O?l7*U;#{H9^nuyS&0kX9XN46czXg%g99(Md{=e zOZ#a{V1JzVCk2-z+{bi_@JNk^3<1b;4MID?1cA%084G@-`J?Fh-veV7WBo>RM&DfU8Wy(K)#m=fd=Sga7obAV8!ph z>n@OY;$RPE$sen;yuPnS{kQGg)`#Q63O}LFv|DPVJ2=c&t)Y&m?kufpa$xSQu(@hi zJhhZ|-+(_R)_9n9MekHlKu!09Abc>9h&&h^obb{@sX}jng!u)m2KFA(#-&g_)KML zj^K|T6$$op%f3zLerj+%np0z?v$i>>xA}$Ijl^Ld({E^ZUqSqfFL54bvIs5}*o4QD zo-`d3$s!$Cnhq~yn<2B!Z;8BU60!7nbw=?G&7w}QS@>hiQk{zS`Iv0eUncuXv=iq_ zKc({5&LO|Gc2lY8EjHL8R<%|(UVaSZnHm*6}=D*LuZCqTj-}B;eVS&Up{6Fzc|6!dM`_>(~njSi*_6|V5u^!R?_ zrv!bc>X}CShHuH&cUwv)18c_qlo|ais^i;=38v@a^E}~uib|-mvd2&V;oZ8=pmEF^ z#96joMgEf_fqT9qXv!WHOUZHEMf7GFodDY1VIYpa#d$%la~psyfh*(Iad1{{RJv#p z_f(=U;N6z0#O@-lqv2^ZVf|Ko@7&OXY{ZyPZ|ecPH_Rhl=1}7sUr>Xg*v zzsemz7y{f6Y*-eBx?FcVJ3BXSH9)$xc>_`5s9c`W7ULm5QWr3K-fb1TWBl$c!Z@)( zmI3Lgiic%2KwVSvLG9H0ApvRz!!}?N)T4uYp1Jj-eY78>u7J(vmQ>w58{6v(g)}Ts z-pXrU%foNyeBU-aW=L{)rF|%4=aJnR=O2b_vr!gMX*>OVG*32LC!4j^hcG`uqSSet4S*fx&1M z|DjFnc0B{P1SjeCGgBA6viG?3g+8!A0hVJ($ncAQ$PoinY91@H8~lW z`5v^&mGWoyzz3jv@?ads)GXAJ(EQRw-CUW%q@ST&&_k($=W|vQd-zvz3%Uf4tx<;r z#E1ue6PG})+4kE?#HZuu}9FBdT zhhB%A0$NL}>)ZRA*Uvp0$fQ0*l=>Jh4ggo!0-k*HyU*&0PjZDh0yK8O^+Hk(?%`5r{J?Yy=Dg#3sX)|oIkJFp=igEi| z$N))PGLJMdB}LS|6_3rirx7lQdcmEH`CGAk_+8Dg)V$jw4ESzumswC!rE~@xZt4yM zl}|Hu-EV(3|3B6GUy;Tu}=MUJ(< z9Xx*!j!25{tZQSVrSYAKp170>uf<_Il*y$~j?Az=ki1!!_NCY^e$YhcbEWSC{zhBx zDr^S}3Hs8>tj4@4YeHX^Yg13B#w>|>Id>0vxL`=dKeoVW2}>=hIw7$f{T6dc{pmC`wT05Pwe zX>=>pe0Fvx9VE*cxw^XATph0|&-9iEpkxt&nyOV76BCo%$2k0V5*w~x6$=!ou?+%J zaG7aZDuyof^&YV^r3iJm3d@$}!pU%18YLn8sdE`3W@I6>xf~pjg=}}vgM2IA>wU|w z^z9Ih#S_m*B0WD=QRjm+nOIfMn_N}r_^Y1j%?;u-16zfeT>9YHF3)%x2O0112bW<* zQSBO{mwAM7dzC<3Wk9rgRv*A#%2MI|7jzfdK!1Re4Lui@8$p)Azr}pEDz;m7C#s-6 z?ztiBRlxRf{SdN?V}L(yJ}Sn2zr@K-u0Ct~CuXd^XtHX|w&^DG(*}d;8RfKjydFXW z+ULP;ZoFCyJkgc*4N(b;zGTpsc;j^DThsgAJcv=RZ`zU(mkq5;gDacKqS&-i(!7B@ zn)7I+G*_9>!)!0q&|_3hFCkoHzD$@&8(|OqjIMZSGx0^(XHbaUEYwd>s1Wbd)R-@yJTYR=15u92zreQVIr1nvG7{)mYOB`!<<9II@2cp1 zR$N&2-$JlDLOibhzE>5<8dezx%+##=!G(}5TF+Nr|7Et@r-I}`Izo}kNQb6F!+QoZ z2@9D6=(<`JoV^{CUp3iIgYYMNOY_CXl<4=fS$hf zmH%^vvIiT-r(ZDq&#T?iEmoJV$(GZ>VGDcTs%#gmz<7rtTC+>UQ9F-cQc$AG?<;}< z=`3UOC`*??z6dMMMIU8D+=+DstLdP`9lMvZ|LQvZJnuG z?kE@yKuY_@#R_)@l}iec1Bk~_sNUx%<$rCvv@$wv=Xa}$yhi)o>9IIAKs~dEzZNO? z+72$&4;hX{4QDLcbVL(}Mte@4BnIO~h|jUJ$TqJD`0UL5d3u;AXK6pfDm~z8*|ad; zuf{<|%vCR)Ump=S%gO zBWCEbt@%}%+M()I7V_|@w=E5!%RWdUQX)^|Wq_OO7BN&+Hh7M`W$rR8u>eG{2?)=QkU6HrX$;Ln<#V%$vczI3Iy%| zFWEr3QM50lJqj39Pg$m!Q9kh=OfXR^l`u9o_Cc9o`xk=$;;#TY`_$hvpbBOTjAvwc zPn+EQa>``Dn-4pgkz=XpmJi&JR0jucWj4$@rpilz600TTWI%*LjpJ86Zg&jU|JC6c7Mt zBpY!r>yaVwo&H{lHGCUeh*b5uRJEcF!Pl)kl*!vnnky@4#AGgjzVh(r>33u zaBJJAhXq@c;W%NgGk-Zv$YWBqwKEbw(5gJjAWEO*sCHn_wiRLzk?KhV3e)V~n8@^z zrik6Vx;n(o&f|NuRlZu#{(PNdnonpaLCjK{>d>kPPfc1U6*&1bW>hn046Hi%B**60 zd>Yh(Y1k<{OOTh{ICb7vjvMLdlR7r6KmWU!oapQ@V6$BSVTxzIYRJ}o6Hmya%&-OW zz+h(M;FMBq-q7}G)yu+Mvel=@KR?VAMidoFMpH65f06gzj~g1@*3rrHAPyiudOC0k zNFXj@=$tk=vWc=pK%*_nV!R)xR9rD)(Te-Myw6P^0(0dIuepwoE>Mx*=UA}X4N@fJ zsZ+cRi1MW9e{C0<^z8u&0fGw{b#nkeSVSZY52}BgkjxJh-J^o2Cuz-QNAIj5e7k!e zJ`$z(2@A5rGa6t3V~*&cc4lYk-_w@FmKwJy!B@Ijg+{h%AGV7}kKqsow=TV- z)}3G2a`qz;Tz-kK6ZTQ(jTlA7+tmz(rFQ#Dlb4Zyki%@Z0`_XTv7U|A8#(p6$u4#S z63XZ~lc=I367%`nwuy?B3!|85x-q-;O@<=apj|C;(52 z?h^^)901SEogOVX=J9Ygj~?rhf={_BJG2Is!dilGQaz0PJ`&wG9Q+`b0#qKWroEky z7bH{iFFovx>0*0AXV3iH#I!WRFE-t5(kA9vwCv(i==VaC)ge>UcUI51jVqX&W8TeZ z+FuZ07yukkr2XJ@?Ac?$A4}p2Z$OaX6^H!u(l^T7n<5dCSJhvMabj<-NntnqfM537 z8Tt0@{|$iW#m%#eu8sL611GqGY}nJ*LG?4e7#_kR0|Q}f7JD;JBZ_Z15uvVhG!;E2 zW`bur6ZbNt;$x~5yNG*sTI-kQK0+oq z`eJyWwl*d%6`}CC`N+DMCg78mF#R^tA@pRR>1#p&RG%WClLy30$q^T3D$2?axRQr% zZ2nzAN!-y$5Pnrcs?V>R9pt&@MR2TKKpNMwI~tTwbh?TGdlb#kHIK?IlBVHS*)U@^ zU}2Z!rl@eo`x|CR@bu((XFJYq<8&z58(5U!d0AZIGaQqj6GSw0rM8yaH2Tj+BiCA= z`ixlU%oC*4H_tpEy=o4w3WvA0c6AMp_$XUy&t z2HJ{Ict1GuBzgB8E!ZLiTVixD2|Keyq}Bn4YT1Iry~^5z`u@N(>qjbvKNmEEWzxsx zx0@9@w<(W+2%qBA!?|gSkU|g=*@xLchK2R7>sz+Eoa>U-P7;KzV$WHRJ zbog4a-cBhShfcp7v3$6O2?zSpD zR85)^El{4Fw3nCahz}OIES0HiAKKbG1Zo0B;RR_Rsr__x;nDh0a-DxBAQA+tp51%FFeB0Rl!>{8J2RT>z<8FKHOqwTCDleuNr_OCAzgm*J1+BLoDnbV? ze!sMTitB)3;7Vd}?Dt55gH5)2O~8eoQtjHj;q{M?(hH{q@{2R2LqeMiw)9R1%_abE z(z@WD_ABxRs{Wv`-QC@&m1yuhaS#JIr%KhE67>j_vPCd+7wmnUqn2`U&_8-yhs|4h z=SVvOVVs7(RX5l2^V{6Q+`sWi{{)M6OqOPHsCd<_kUCH7eUnivZSf~XG z{4Rl%8X_Rpa1wWykl zS|C76HgFr38wBR`wct^r_E#kXqlVbh&r|h@)t*w!a&gDW?(pi8n>1uVzmlYh!%aiJ zv6+1}1&6$z-iyJDZmKp`>5L(dO@0n65kuz;Nt=XXE~Vt=My#s8)yp zozzUrS{eFq@Tb!Mk@em2RQ~V($8oG=@9dHz5hWw*kdUmbkc^UK?>!C)*_FK&MP|0F zqY@!|&m(&t>u`+YoZo$V*ZbY~_xY#4dfe{wy07uPp4aobUgSb-5G`9=_Y1+_P#7~h z%rz3KvwVRFeV72F= z%&(l~>+At?a3%Ws4y8+C=`FXP{HM-BA9;G^bvs!O?iUlm&<4diuV)&qrc7NIO#!tL zBtnY!;{xrr$n`y%>o6y~RA1Q5B#wL2Tpt0-J;vKg)=bYw7gBFKT*!-G`5~6L_WD-< zectj&>7QBgfDOqhpZ2+B(7W?Jv0_a|ALCqW{FJ-aEV3CV3z7%FAPjFXeKRV3P4-b53Vd0j&9$*cpMbP;n=Urd~&NH2r$NakZU3>P?ghAQFU`myFb-qGKu(wo^D#u zoevTxay+g?Is^0BKHpXjsS20A<$fvL1Dh;}oukCv-F`x$*Sq#|3ufD84FmDVeaQ+@ z8kqf*uJ}Bg^0C8NBub^^BD4Ibar;Y^rwQUW9ePR*kNp5r2#H5;`pPI=m{m6bAe{O<}xVkNQuev!4?vK(?NV6U_1!_`O&S}#O3Tw$3w)-QqQ?drtgiP?+@1& z2(kGwOpUZ9Z4JAC9dE}U4*v+DFgYXdWLUf8Qoh3)pCCQllz=e`IDQu`-zA*p)DJ6I z{Q2tY`hg?WHES;b;&hc7FZ1&cra$xWOMDB&JmTj;cnXj_McoCrz-vZ#0)tc}4nHI{ z8=u7)k=j78?bNnM{%3K+Y>sDk8hqCGuby3<_Z{u z*@&N#EUL|UIc5X%A0EjvvH|XjdIV*nXdOZ0?%3k{gv6wa`!b3AMO#_|cS~**KJ4@1 zEP6FRn`_Hi_R}v!Nggb(0s^Yx6H5eYM*kzf0wS-Qf@p?s%foE7wyP?0Ir-v)vEDC8 z>P~@YnoGo;XZET@;>LNDU^!!S$u=(~Rw^_y4)+6X16rvj%_o@FDw1GL2U$>vXkUV*)kbFVs8)Km+dfp)AM^Jisw)VpM(q8N>qs zS7-}~2vDPAJ4~kRv|nh0-Nk4|5P1?3kCk1E1|5Lh$=sQAJ`OvV#&1PNBp+~wr@!{< z3d^(>S$0TT&~0>ZV;kw82j(zxgL9+vg(awW#rvspFxV1RjTg|D!mA zDa}2T8jj+fysU-Rr>)XSU{0|ZnWckgwrjneRmR(rM%YOT(rs}|eHGz&QN!aLCqW%8 zxlZ;sXtgsY+vw>RWe<`m`qjjjhbVW#{7FQ&9494E@+&N)vhIhsQCb9UC5kw>qoc#Y zsBg+i>g1Cld&bf8g7@crWaw6=B_ljzAAJni;SRV{PTG3J(Fo7%SSB#PG z8GS!oaaem(oULbi%%^$6Zu6CFUKIYlxRDMX8m5sDJ5KHLi1-`+Zc;~DCZI~mZWz?$ z93YOPdMIK=$mqZokzUEjrHboEY6_hj4wJh8g+WU=L)woXb>Cp_I7^YYd(dqE-Iv*N zC&rx3dFTH*OLb82KNUb6_WtAuM4%yktLRH3S5N7k6&lI!C#)vSm74F2NEP0Z9kx9Y z8Ia&w7@~;O#Jz#1)lQ0>2D{e!D2;4C;WU~TbY(ux$$$i{c}a4*Z=LSRpxr=GZ@hU$ zXUXj+Yc@jzP7WS2V!hQ?gW{Y&4gxbqcn(+=>vw_ec5XNp`$j1|Ya^R6@mB)?5Hp=4 z!g9=(;m{?hw~4}~6c%OD<2m-9dpkgPJN@K5+f>&i0!-ZQ-`ICcL;mco`ZBvabCWa; zO_O%4JsGOSOnV=JR_z?4tSeXvlXFJ80K)KN}TOPC<(P) zFdZw5B+VRtB^7l#z(@5dMY|Di&SkwHOX1bQ`~Ln-`Q(cJO0n47YY+ z2IQl-h)PzCk2O+@I#2raIjgPKNM_yb*VeH=zjSO0ak-+t3$Dl=ujHnYZsD%#{+dQ;Y2n%K-0Ss3 zVpqxQC|u-kCJxG0sT_ADdA_Zf*-5moz@6 zy-{Xq*TBb`ZYtHV#t*~Ky;8l?-(CgrixeyYbASa}+| z>7p3~@RuJ10qH_Z5Rdcr?C0zh{iFU?F}Zgt2KKcCldXMO8f^*e%u^C`!lUzHnL7>} z6TjjofE^gmJL5iC*Hvc+9A`2t1}B0vaqQ(7+-fxR@KgL0N68&n!(v zHJnHUif6IhM8`v^LS?1B!(pS}AFq5}I#F^^Q=$Qh&W1Ht9o)*+d1E^%5D;?Bv$DrV z+Z;Vzj41RRx#~mO9W6jQCvaftwGeWKsjmRKqp_SMJddK04``4Pl}J>kCkR}SbcY?< zfdH5-HI-W5bR4Y7Cck&3S)ITFsw<2Fu^~jxc*(Hz!73nagg*#x(*NhEEg~*#SGbvN zl;Y!S>m-juiHr}4=}ivrzbNb|(JDLiz6vO*&3GuuUVA+uUd*}O4Knh($#|N)rjt8z ztt){w#9_Ve_LGzKpFfE$&zH2n=goWz-09uT(e?$w7d;3v&L`nIUod>9aiMK`14<7}!Fsh+0(oUwUNs5zeSw(%&p# zSfa!*9F{HtXPw*`mtX304gwR$er^-IYhskZuN-bbFH%2g?%581^Fou4iQ zgI!c8_ye#_A=vS}sEkZQfW3V*0$90XJRqT0#1G_zbOJ6S| z8~$_)j(<@Oq>q2BGv^A#%w;C^p=OX|#`XKjfencRl$`7GZ4cQxJoCnjj_yuPsvfZm z9G1Wqf~0KhR~Xw>wcXNVNN7q9p`Pf60Vc+7sZZ{?--6ncb)LPGnFwr53>UeYD&M_Q z)E$9bLQ*@g8hCw@J84t@{0%spJ{Izg$=WRdSBWZyi)G8W&F2$OzLg^^PL%`CJlE7F z%@X?LzdlmphI^HE+NSbLc1U2S>uKw@v6WLXc+BJ!+l6VwLM7?rw{;&C+bB6~HhS+{ zdF?k9_k2MfgL^rfg`M0gB(8=7jI*Rby9y$2-?#esNBp(*^a|h8k)d3%yIsqJER9`p zP_elteB+pi>r`m#JYUPSqpNMb0C5L!Fe`N6<|pHImhIG7NDw>BxKrMA?9v1~q#o~( zBRRiOTOdneZ?;PDteHpV6g@aSG&IC;&-nM4CBUT9NiDOOEo9Xl0|kaQ>xa?2i%sbB z$u&`#)`_`I>)9-CX281@%|FzG&t@5gzb{|wx>zk(9ksz$R#5i%lW2QJ3HSHD_tDan zenon~_a9QHvmEbL#YTydOJ5HbIeu3>R(#%8FvmyGyvg#5>A{gW3fRAN`;CqXIr?lc zH*Pyz2H>Hk96nuO*_F*4M;T|S%K_wo?}+AEqmD&++Mqr zhaX0p@18B8J5C94Y}`@7N`&VZywf1N<{(EPfaT;t{Ec#Io!*TUvt+Qt&w46`|5`y9 zUEQpe^`~__S{UWQ=}jNRa)s}kllSmr0|wRdxX51S6Pt%N(GDCh9Lk^iSPn3nIB-NG z69xfS`_YusApS~oWY@zxMjJF+=St6W_0a$%6Q{9;%xkE~+lC{end+lCvdZ_KMO-P0@|3CZJh{~~wZcBsIgVtu4Hk4|1-EP1 z|D-XPIfV*~S%1mv&(V07N_y4!yJ=R9H406bv#2bp7PSxy0)_#qh=TL81CIe9j%o!5 zNret_(g|E}y5#L(N{9)j;QClm*-K|uZSpfE7OY25g z>@g=K&fBL2aYURRIFM0u+=hZ!-)>)jlK<3;kPp0ev~qVI^C-g(-Ms)E?qs9S9*rKE z?LV9*pgdzHYCOMf7f3(*HnHoB>Gs@X+v18e5%JD_!83=&WUlg@7Dq!mBTxK2D>cu2 zTKq67^iD)~9m<`~B=LDr@{;LC%{x9y*Tq#DROW=%E`(l#&vSE@!xmm1_0R}oAN4NW zpz18amzQ2{CE4{c0k;CbCyX&Zm^_zE)&I~dKp3g zSlj@o8T;Mn#^a-JQNz64TdL_Yj3u(H1N1SwRC2{TeM*|&S-E#T?MJ-U;sWwY+TP3A zoGTM{;OlzcA;x1v|H3w+ZYYn_##X_nUTbar`dZeEoeKhr=Z@HsIv$ za)TKd7--6j%E6to>`?`qWxeH9($5qYhnp`vT&N;~cz3I7XM8eo{IqzNI56+e<|rVs z^~hT$n&4Aw8zi&z8~H&|qJF`J?i+p%!M!r4`oPw}1hzX!Mqd8M(VAzB3)Rz~2n4(u zP@OQl-Gj4b#H|eO_AQSUj*ke}#tLn5E|jfy@!NQNWhY!6@XWf-Cm=XKI+I$>IvW2aYDxJwWm>;HQ#z=n)U<&sD>e1AaVic1y4K*uQ~yAM zu<8GtaWW#vNyiW8ooCdwyv%{wcK^YSTqX}L(ei4u zt179aXW&{8$k*abEpk3BU3?wrCTV2M=9n$gyw$?q%zbh(^V8St7$y7$^j+h_J7hUy z!p^Cc1Lp%>s-7m}is)X=8Zoic?4IW=G7qhFEX*@qWiQ__`zER1+~D%#^fQweFs9yC z_*6{@=*!B`9`?rtqI-MgPlO`j_EMRHa_)~^w`ET+v1}4F9xLa^#BYwr2SLvcb%gYk z08M*G0MKJbwsWuiL$}d_H81>K7_s*tGRGjJ5G_=cw7AbDZFTL=lq*+#~WysI_!_ zd6O$2e8x>dQgan%@E9&=o@1&y@osD+xx1s2N;`4#6qqYFuk7JuO~2ms2sqxSP_X2* z`=H|%4FgD78^pt?t+typ;Y-kF`9k~?Kg!-Xvl>RlzLe#=_90upJkjW%Ecsla3z*kL zu{oYD2iDrtw@7~@DSXtmb(n7U_1+3Q(eUkll9`$q-$9|%;P;`>Ox^HJ&%U>5Y%UY@ zQL$2=be9rxg}9Z44sBS~@lsTGpK!z!zmT>0G+A#lk|As3tP5e4?o9A+u<+LBeaAKe zIovk5&j9j%$^hO}X~8$Hv@mGPUY$Rk8&darUYXA~F;&UHW?t=&kCYp?-%cSuGlYNGU@xlk0-ViJ|1%Ob_go=W$6n#{ zF+@8Tyzi_0ft~&B7qWR{+atb<$5(cJ2A5ngfj~o**iw(_Az@8tjt>N2i4nLTV!h9a zGcqYRyUAW#O%jUK$sGHRS4|o3{Kx07W2U{h&B}v~B^>^|xO7;{(Q@OM=@u~X5Vy*w zaR2Z^$laB_U4zuun~E-NH>q3?UfsJd34H@=d&bh4wr6CYc>H*W;)W+XVoWJhSNgs0 znyhB)dU;(tG44nBlDN%U!+TfD%n$3&s?^B@Io%Wmie4XU4dZ(V>j^svs_vaCbqBz7 z({5P+5D6dT(b?!z|Mi0QPJ#rR=95jr2-2oPxevE2TX8sg;gVgp`+%Awuyq_+P5O`2 z0(f(GFi@p#0}Gusz0ACoEk0k2qCD9_!CrrVd@o%&ttm%mB%)F2T-()0d=S_NJ!(NC%=lD>@kxRfL^q*8eI%gm#R4|o%7 zFR)MT*s+O|heXAJw~r5uJRYeHthef7KAD8?=E*LqrAPBsdJ=egPu}r*ZnL%7h{kuo zP!>KdW;`3a0L4^sX>t7_1B9YMGt}EnMKg<6?%$Y8JhcLrd21ZKK;+k1gbL3O)&m2{ zm70~Fy2mvME)E$8er&427bVf>V}GlFr7wR zHpvav7O~jaYL$c?^C{adD5lc5DZnqY`%iENPA)tjF}iaGR1>cbys(5}`H0CWU}%x)(rq3f5(bbrZhxVa%m5<7 zU1~`|xodxXNiC*zw^xJPn8)i5iE6A%(o# zV*rm<=Q7`B>vif=`1-!&OPh5%LcFHiCVA*{ek}gEto8603W;mi<|G^@-1UNKBK{bI z``KVhKx+|zVL)sG?Hk;&1?4rf7KM_=>5lT*JoBncc3uynNzyq@65MA+;;lbkhn$=~ zoj(u1D)SHi&6x?MpCj)%-6EU2ZtA{zSR|OVbSCHiQb>*FfJsekgZe37 z%L3zw(Fi|qvKPqxSJlmZ18r?1^JUhVYUaarSJ74tuV@DV4c<4yZEDEtu0nFg%(Dlr zYSzO`SdGbzlG>T$uZ3L0zxx3=$jFw66P;7lW>#k+GCzc&;Ayh!?Qwej zBbSqwZPEtboiQcx)!B)V|jf%=C^V3z6>2+<^4(^U6l46bW7^-z{SzFbSuDtH&x#lBp?Y|nn zDo$m!l8{g^4tE-p=Wd*%!)av4gBrg&b-N}rK6B;C8M|#+^a0_nZ5j5_VfV(n*WH)4 zgsh9tbf-wzd{VY68J6Ln4lgsyR|^`kNZ6-WoSj7C4zwu)@#fdrKHj2b%XnxD&Vk1! zHpMTPly#W8!vrjRkfh2`GT25I)Gv&R*T6O#kFp*cc&{^%PY$2nVSf(5fGQ)cfYD#kM z5?4xIDq_OR?nMw!O!yK+55DAqickG+Za?N-q+p)Fq3~F9+@iVTrET6{GH`-nl=22; z6U+K9%1pD{HFD;>dThl0C5%Nu_u!SpoaFF3n!_bhHcQ1YiTyrDpUNIqA&+zJW5)G( zr!91HUjJA<)ocAAMdMUX_j8Dz8V|DgD$`4%ccQad$NA%w1S>bC^&E_-2z6NG@O{>g z4;LPP)Ti~v9W6WkFvGX&F;zVU2U(x!20!6x`#{*vsd2C{8}a`u6Z(@Zo8Xs^C?Ps(F_=|ePKNW028ljBJ- z0wxk$VLAJQfh+;aV6$RU{^%PP0CZ^S7Lqp!zm{GBY5H8SVHTVq)PZ-KR=FAvzPY>o zu>Fb1Go67Mgaq@v@x;v28Ftd4mRX~X_Kac|&Q!%|N1Mrm;f}8)(|J{WByD$;1%j3j z`z6v1LQ-r$Or^MoHgzL7XW@t^nUipfx0iPqZ;_up1IF#cds9d8KlQ)GN{7m7BNM1Q zX<0n7fM{IyH9d>(fUm+og?zinspn{v2&V_9QXK!S+0a$~l`%&A4>D2jy297Pc$&8R zUn=uVcIzIOS(yVmnv=AEM&Hplj8TECt^K*092?ISP=cBn4(AplOT^rb>7IeZ6w+lL z*TCjW$OX|D`wKp)g166aLb>)tJlaO?Zazv`i*9F)o&>*BujA=; zzV}2owm;`FQ*M<;o8vLbqSk)k+gkffXYRuvoR0QjyDS?9usVA%_vwl%Ty9-54yV*ymu!K1o6-dfMG}(DuYMh{ z;5EZ__YS5@1lE0u&NrDp_SM-s7`a zrG{UBG`VEc-Q_JXZggEx&$d}{^sL^`EKZvjXTAybYB+Y&OX+F{3At zUq$Mf+N*0ul+CF$I>>`b>AaCAGnj8c7uK~c-K9NT*0V}+kb+2LZLD3|-_DMfu*jar zf>U2xB=za!be6`;@Pl4BZtv5283I>My>xN(4=g_SOEIvHKh*U4?D9^W$a$wC^rDDs z0x$XF&54!EF_w#)kxbY;Vnv?s0vLxA0T^nxeJVvKNps{Z-|Crj_ef`I#8@(UI8;KN z+Q_Qs-w~ZKC>28InjL299lit{rZr4|F8|QntrI~3+%_O8AyE?uaI(c}x{-R))33A= zwS%;t2qLQq@Lky5cd(s-tiQt~Ez91mcFMKu4KOuszoA(l`EM!C8l0TD_sFX^5wU(n zgP$m;Tbiy)4@te6UOpi8vev57&_*iHlHUT{e&t;2icZPR4o{UVK{NoYHpk4vQZZ+h zmOqcF5ltk#su0Nq5}cOwNn-@Cn)?utX7??JtF3yF2Sc;G=VSn$psp)!aBPIneh;le znxtxCl1%_+@;7M32R=d>fja`IvERRc$MyyuRF(~IzxlUDl~bH87Q6S!1hyjqR4oH( zAnd){6R1{QM2!Qb(f7%Ui(1P%mn^%8UlPT1CM0|?W^lK-oO(;Is>J24EiTSOIg59! zr|D$KjVx6U@AH*JV8W6tXfwfBuL+*(DLM%{H)1{mow!@lzfT}?V z>vKPZd060p0qm2v>AA#jPQ_y(Voa5yRvkhCi%PQS?y?MxNP=f&ODlv8W zN+l_~usHDtul*A%2!`#TWYL=?2gff-B97{Fz|_7Olq z)W^=Rkx;#hlCas0K)q2wl))@Qr*Ux~n)tTjJA zOF%Y4fieoOAuoCT`gMfEq=Yc(7`$Eo_h!~#ae)S3b!CB3FF)RMzcFy#^AB{gTVTqpkuKICQWZ;t!l!@tR+Jo_O(t9~iPGWKESLpy3MQlr!o zLtR5#%&!;B4JlU;Jjko4bdV+TaeZ{Pg@7TBMVPnq9shj4KVj{;0xuYjZHHs)%&~Fe zq_)&3W#Dci1;^Sdhm%&!Z_^Y zV0Ul2q|=q6tFl5iG9@}e99B2WwF%W_Hdo5Vf}*EXMBUDFu%>oP#erC_tXL&rYwR`x ze*)L<-U#3d1!Td55>yh9e}0%#vvlf8`#N%=M&(0$llvb?NBm|}&B`Y$h{=7j#-Vc5 z)N5Lks`VvdMdiQ0j$j??97KpUJjSW{Xi14HEb`oiSL5}N#_55YO$MYA0k$Y@r;|Hq zSD>FSIJth&mtra5jLCC;2L4H zagmVX5UKU|uOabkue;s9M{~$drZj$zl{mU4Eh{VQzS{xC@1@V6-+TFS{>!!e>+(SR zfNSo1LMigY`ywMQ$5SNj?A@Q{O#QfZh0g^J&a|@~B(~PG8)rEe-Za7S zxKBl8&Az>WkSFk(l#>2$tuatK|8@#AI9O(@ajy_qE;quQSA+W4Sfcsz$^=jasKZar z5K^CEc&;eh%nq<~wPP<9KJgx#^6J$q%O0uuXefX^M)75#GZ%lYdi(F!-?ZqsK)8u0 zX3M)>#&N9NlI#q81L&FHp7LK#W85|sJSO_WV^3Hs97k{6C-pTfx?_^9?k1Nu(F2!n zOby#o+ISj+|8+S^2

vR&Q@l5A!givNCL)Zon+BI0aai0|hP}Dk0-PxC9DYHihfX z?5n2x=Ug@{<&a*^aKkME@n9c+(^BVuEE`0-?S=Ph+;ng{SqEm+-;TBSG~jdWD`^-R zNQ7`|O}Dkdpyz=zXov!gJF|0YAigWhd)DXLYnsjFEI&t-CHKh~HT;oNf%~QZwE(tY zLI8II=41+ZjZ|N1PZp~RnRfP3O^pE?if1`0(3e2Kokold(oEVQ@A0c$$s*j+JFN`( zpD|AU^LPmXQ zvcWe@SPI~c)~MzaluV-ou-B9d^)d0+h~IyXPYd2uXenbjNCxhz6)s|HL{=qP{Oo

BCkR)vK1ipm{+!{GLI$B-1^FPVZ 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 literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000000000000000000000000000000000000..af052c93fcbf25e1ca271f2898e166f48c8f2a71 GIT binary patch literal 519 zcmeAS@N?&q;$mQ6;Pv!y2?EjrAk4uAB;`N?T zfNTy1#`a7G7LXDkmI7i12Id8f49q~95hS*N2`($JfEmFCDKrT!`~*~1Gl8r|M#m-SkHYV=foqAH}MYNMBUtuC3_?Zs0DnsQBV`paWG_9aaw5pxq1gr z0XODr3eGbYsJ&b;gX3wWZ1pG-RoG^u%|It?|L)+{(s45jHY*g zeVcwTaz?9S#6-zhPHm3{)>x4v|G&*{Ogwb9p67exEZNowiKI{ilfzpRB|h+G6kq;Y z&$GV%PhtU6R$s`mwUQ}ZZH(!0|I;hJ%C3-nks}|e*7mdfpOMYaZ~cz5`#Tj`E=$i~ zi|8;m{PW}dsRY$iCk(zHi*I`z|KBL$gRybN>7;T_9fALcZH}^qJXbq=WW&36_H9q~ z>x}3zop+gI+Le|fnvea)z4*}Q$iB}6L!V! literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..dbf5175fc20b2a74ecac1da1141829e1b38e6a1a GIT binary patch literal 14141 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 JT1Cr`{|mTI?N$H) literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 0000000000000000000000000000000000000000..3ff33109f15d141aee69c8c91d77f7fbf805a735 GIT binary patch literal 1065 zcmV+^1lIeBP)C26ySs~28)?9R-4^ZU(vZ)Uc@hWzIUC~o+sX&$7p4$=r|fK(?H z!hW)^NqwwB67=$&^d0G4(tC=cWRFvqgAj0lw4d~E%LAG)=m2T&BBN4(i^V*o7hB|P z4I1RI_uDDuZzU{D^J zNiP(3%faD)Q3SZ!2dUuhq{A-2n<(cT_B;jW0BP?kNPu%bvS{GuTpUa!CG^}yD`)T! z+C`cd@RN$M}@H3uF6y zu9)Z?jbSxO7Z8~(teM~%ytY?IeW)OK&cuK0K|z47s;MKGgKroH#)n3+^nN;L@?tt< z0ta jUr|3y$YDeNX#{=)#1Zk{;&VW800000NkvXXu0mjf#Q5A@ literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/src/serious_python/example/searxng_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000000000000000000000000000000000000..401e9891552a6e0d579c65e9af640eeda8badcc1 GIT binary patch literal 36405 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

^CjD`( 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 + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/serious_python/example/searxng_example/macos/Runner/Configs/AppInfo.xcconfig b/src/serious_python/example/searxng_example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 00000000..18cfae2f --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = searxng_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.flaskExample + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2023 com.example. All rights reserved. diff --git a/src/serious_python/example/searxng_example/macos/Runner/Configs/Debug.xcconfig b/src/serious_python/example/searxng_example/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 00000000..36b0fd94 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/src/serious_python/example/searxng_example/macos/Runner/Configs/Release.xcconfig b/src/serious_python/example/searxng_example/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 00000000..dff4f495 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/src/serious_python/example/searxng_example/macos/Runner/Configs/Warnings.xcconfig b/src/serious_python/example/searxng_example/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 00000000..42bcbf47 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/src/serious_python/example/searxng_example/macos/Runner/DebugProfile.entitlements b/src/serious_python/example/searxng_example/macos/Runner/DebugProfile.entitlements new file mode 100644 index 00000000..9f56413f --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/src/serious_python/example/searxng_example/macos/Runner/Info.plist b/src/serious_python/example/searxng_example/macos/Runner/Info.plist new file mode 100644 index 00000000..4789daa6 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/src/serious_python/example/searxng_example/macos/Runner/MainFlutterWindow.swift b/src/serious_python/example/searxng_example/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 00000000..3cc05eb2 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/src/serious_python/example/searxng_example/macos/Runner/Release.entitlements b/src/serious_python/example/searxng_example/macos/Runner/Release.entitlements new file mode 100644 index 00000000..e89b7f32 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/src/serious_python/example/searxng_example/macos/RunnerTests/RunnerTests.swift b/src/serious_python/example/searxng_example/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 00000000..5418c9f5 --- /dev/null +++ b/src/serious_python/example/searxng_example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/src/serious_python/example/searxng_example/pubspec.yaml b/src/serious_python/example/searxng_example/pubspec.yaml new file mode 100644 index 00000000..5225ce83 --- /dev/null +++ b/src/serious_python/example/searxng_example/pubspec.yaml @@ -0,0 +1,65 @@ +name: searxng_example +description: SearxNG project. +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: '>=3.7.0 < 4.0.0' + flutter: '>=3.27.0' + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + serious_python: + path: ../../ + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.8 + http: ^1.1.2 + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + assets: + - app/app.zip \ No newline at end of file diff --git a/src/serious_python/example/searxng_example/requirements.txt b/src/serious_python/example/searxng_example/requirements.txt new file mode 100644 index 00000000..f7140ff4 --- /dev/null +++ b/src/serious_python/example/searxng_example/requirements.txt @@ -0,0 +1,67 @@ +aiohappyeyeballs==2.6.1 +aiohttp==3.13.2 +aiosignal==1.4.0 +annotated-types==0.7.0 +anyio==4.11.0 +async-timeout==5.0.1 +attrs==25.4.0 +babel==2.17.0 +beautifulsoup4==4.14.2 +blinker==1.9.0 +certifi==2025.11.12 +click==8.3.0 +colorama==0.4.6 +fasttext-predict==0.9.2.4 +Flask[async]==3.1.2 +flask-babel==4.0.0 +frozenlist==1.8.0 +h11==0.16.0 +h2==4.3.0 +hpack==4.1.0 +httpcore==1.0.9 +httptools==0.7.1 +httpx[http2]==0.28.1 +httpx-socks[asyncio]==0.10.1 +hyperframe==6.1.0 +idna==3.11 +isodate==0.7.2 +itsdangerous==2.2.0 +Jinja2==3.1.6 +lxml==6.0.2 +markdown-it-py==4.0.0 +MarkupSafe==3.0.3 +mcp-utils==1.0.0 +mdurl==0.1.2 +msgspec==0.20.0 +multidict==6.7.0 +platformdirs==4.5.0 +propcache==0.4.1 +pydantic==2.12.4 +pydantic_core==2.41.5 +Pygments==2.19.2 +python-dateutil==2.9.0.post0 +python-dotenv==1.2.1 +python-socks==2.7.2 +pytz==2025.2 +PyYAML==6.0.3 +queuelib==1.8.0 +requests==2.32.5 +rich==14.2.0 +searxng @ file:pypackages/searxng-2025.11.27+c3799ba9e-py3-none-any.whl +shellingham==1.5.4 +six==1.17.0 +sniffio==1.3.1 +soupsieve==2.8 +strif==3.0.1 +typer==0.20.0 +typer-slim==0.20.0 +typing-inspection==0.4.2 +typing_extensions==4.15.0 +uvicorn==0.38.0 +valkey==6.1.1 +waitress==3.0.2 +watchfiles==1.1.1 +websockets==15.0.1 +Werkzeug==3.1.3 +whitenoise==6.11.0 +yarl==1.22.0 diff --git a/src/serious_python/example/searxng_example/test/widget_test.dart b/src/serious_python/example/searxng_example/test/widget_test.dart new file mode 100644 index 00000000..7bdf3633 --- /dev/null +++ b/src/serious_python/example/searxng_example/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:searxng_example/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/src/serious_python/example/searxng_example/windows/.gitignore b/src/serious_python/example/searxng_example/windows/.gitignore new file mode 100644 index 00000000..d492d0d9 --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/src/serious_python/example/searxng_example/windows/CMakeLists.txt b/src/serious_python/example/searxng_example/windows/CMakeLists.txt new file mode 100644 index 00000000..97f0b3fc --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/CMakeLists.txt @@ -0,0 +1,102 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(searxng_example LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "searxng_example") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/src/serious_python/example/searxng_example/windows/flutter/CMakeLists.txt b/src/serious_python/example/searxng_example/windows/flutter/CMakeLists.txt new file mode 100644 index 00000000..903f4899 --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/src/serious_python/example/searxng_example/windows/flutter/generated_plugin_registrant.cc b/src/serious_python/example/searxng_example/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 00000000..e985e51a --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,14 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + SeriousPythonWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SeriousPythonWindowsPluginCApi")); +} diff --git a/src/serious_python/example/searxng_example/windows/flutter/generated_plugin_registrant.h b/src/serious_python/example/searxng_example/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 00000000..dc139d85 --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/src/serious_python/example/searxng_example/windows/flutter/generated_plugins.cmake b/src/serious_python/example/searxng_example/windows/flutter/generated_plugins.cmake new file mode 100644 index 00000000..159536d6 --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + serious_python_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/src/serious_python/example/searxng_example/windows/runner/CMakeLists.txt b/src/serious_python/example/searxng_example/windows/runner/CMakeLists.txt new file mode 100644 index 00000000..394917c0 --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/src/serious_python/example/searxng_example/windows/runner/Runner.rc b/src/serious_python/example/searxng_example/windows/runner/Runner.rc new file mode 100644 index 00000000..cb92a27e --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "searxng_example" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "searxng_example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2023 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "searxng_example.exe" "\0" + VALUE "ProductName", "searxng_example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/src/serious_python/example/searxng_example/windows/runner/flutter_window.cpp b/src/serious_python/example/searxng_example/windows/runner/flutter_window.cpp new file mode 100644 index 00000000..955ee303 --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/runner/flutter_window.cpp @@ -0,0 +1,71 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/src/serious_python/example/searxng_example/windows/runner/flutter_window.h b/src/serious_python/example/searxng_example/windows/runner/flutter_window.h new file mode 100644 index 00000000..6da0652f --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/src/serious_python/example/searxng_example/windows/runner/main.cpp b/src/serious_python/example/searxng_example/windows/runner/main.cpp new file mode 100644 index 00000000..dccd2d5d --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"searxng_example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/src/serious_python/example/searxng_example/windows/runner/resource.h b/src/serious_python/example/searxng_example/windows/runner/resource.h new file mode 100644 index 00000000..66a65d1e --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/serious_python/example/searxng_example/windows/runner/resources/app_icon.ico b/src/serious_python/example/searxng_example/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..6e7e4c4cfa59f12362650b30190f0c5480a39ff9 GIT binary patch literal 33771 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 literal 0 HcmV?d00001 diff --git a/src/serious_python/example/searxng_example/windows/runner/runner.exe.manifest b/src/serious_python/example/searxng_example/windows/runner/runner.exe.manifest new file mode 100644 index 00000000..a42ea768 --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/src/serious_python/example/searxng_example/windows/runner/utils.cpp b/src/serious_python/example/searxng_example/windows/runner/utils.cpp new file mode 100644 index 00000000..b2b08734 --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/runner/utils.cpp @@ -0,0 +1,65 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length <= 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + input_length, utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/src/serious_python/example/searxng_example/windows/runner/utils.h b/src/serious_python/example/searxng_example/windows/runner/utils.h new file mode 100644 index 00000000..3879d547 --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/src/serious_python/example/searxng_example/windows/runner/win32_window.cpp b/src/serious_python/example/searxng_example/windows/runner/win32_window.cpp new file mode 100644 index 00000000..60608d0f --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/runner/win32_window.cpp @@ -0,0 +1,288 @@ +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/src/serious_python/example/searxng_example/windows/runner/win32_window.h b/src/serious_python/example/searxng_example/windows/runner/win32_window.h new file mode 100644 index 00000000..e901dde6 --- /dev/null +++ b/src/serious_python/example/searxng_example/windows/runner/win32_window.h @@ -0,0 +1,102 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ From 7f21120a96c3866ee5f4683e3ccefb00d1619db7 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Thu, 26 Feb 2026 06:54:19 -0500 Subject: [PATCH 18/24] Fixing MCO REPL --- .../example/searxng_example/lib/main.dart | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/serious_python/example/searxng_example/lib/main.dart b/src/serious_python/example/searxng_example/lib/main.dart index 33a0dafa..78f7100a 100644 --- a/src/serious_python/example/searxng_example/lib/main.dart +++ b/src/serious_python/example/searxng_example/lib/main.dart @@ -10,7 +10,7 @@ void main() { } void startPython() async { - SeriousPython.run("app/app.zip", environmentVariables: {"a": "1", "b": "2"}); + SeriousPython.run("app/app.zip"); } class MyApp extends StatefulWidget { @@ -40,7 +40,7 @@ class _MyAppState extends State { Future getServiceResult() async { while (true) { try { - var response = await http.get(Uri.parse("http://127.0.0.1:55001")); + var response = await http.get(Uri.parse("http://127.0.0.1:11881/mcp")); setState(() { _result = response.body; }); @@ -64,7 +64,7 @@ class _MyAppState extends State { theme: ThemeData(useMaterial3: true), home: Scaffold( appBar: AppBar( - title: const Text('Python REPL'), + title: const Text('MCP REPL'), ), body: SafeArea( child: Column(children: [ @@ -82,7 +82,7 @@ class _MyAppState extends State { controller: _controller, decoration: const InputDecoration( border: OutlineInputBorder(), - hintText: 'Enter Python code', + hintText: 'MCP Request', ), smartQuotesType: SmartQuotesType.disabled, smartDashesType: SmartDashesType.disabled, @@ -103,12 +103,11 @@ class _MyAppState extends State { http .post( Uri.parse( - "http://127.0.0.1:55001/python"), + "http://127.0.0.1:11881/mcp"), headers: { 'Content-Type': 'application/json' }, - body: json.encode( - {"command": _controller.text})) + body: _controller.text) .then((resp) => setState(() { _controller.text = ""; _result = resp.body; From 8cb3c7ac687eddb79c4ef1601556106dfb67ac41 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Thu, 26 Feb 2026 07:00:05 -0500 Subject: [PATCH 19/24] FIx bad merge --- src/serious_python/pubspec.yaml | 2 ++ src/serious_python_android/pubspec.yaml | 6 +----- src/serious_python_linux/pubspec.yaml | 7 ++----- src/serious_python_platform_interface/pubspec.yaml | 8 +++----- src/serious_python_windows/pubspec.yaml | 7 ++----- 5 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/serious_python/pubspec.yaml b/src/serious_python/pubspec.yaml index 85c3d6f3..49ffc0a2 100644 --- a/src/serious_python/pubspec.yaml +++ b/src/serious_python/pubspec.yaml @@ -4,6 +4,8 @@ homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python version: 0.9.8+1 +resolution: workspace + platforms: ios: android: diff --git a/src/serious_python_android/pubspec.yaml b/src/serious_python_android/pubspec.yaml index 326b3214..fd0015d8 100644 --- a/src/serious_python_android/pubspec.yaml +++ b/src/serious_python_android/pubspec.yaml @@ -2,13 +2,9 @@ name: serious_python_android description: Android implementation of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -<<<<<<< HEAD -version: 0.9.5+1 +version: 0.9.8+1 resolution: workspace -======= -version: 0.9.8+1 ->>>>>>> 93d636cc64931cefc89dbcf73cbd57f27fb4d309 environment: sdk: '>=3.7.0 < 4.0.0' diff --git a/src/serious_python_linux/pubspec.yaml b/src/serious_python_linux/pubspec.yaml index 030eb8af..f9731e68 100644 --- a/src/serious_python_linux/pubspec.yaml +++ b/src/serious_python_linux/pubspec.yaml @@ -2,13 +2,10 @@ name: serious_python_linux description: Linux implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -<<<<<<< HEAD -version: 0.9.5+1 -resolution: workspace -======= version: 0.9.8+1 ->>>>>>> 93d636cc64931cefc89dbcf73cbd57f27fb4d309 + +resolution: workspace environment: sdk: '>=3.7.0 < 4.0.0' diff --git a/src/serious_python_platform_interface/pubspec.yaml b/src/serious_python_platform_interface/pubspec.yaml index 7dd616c9..95cefc03 100644 --- a/src/serious_python_platform_interface/pubspec.yaml +++ b/src/serious_python_platform_interface/pubspec.yaml @@ -2,13 +2,11 @@ name: serious_python_platform_interface description: A common platform interface for the serious_python plugin. homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -<<<<<<< HEAD -version: 0.9.5+1 -resolution: workspace -======= version: 0.9.8+1 ->>>>>>> 93d636cc64931cefc89dbcf73cbd57f27fb4d309 + +resolution: workspace + environment: sdk: '>=3.7.0 < 4.0.0' diff --git a/src/serious_python_windows/pubspec.yaml b/src/serious_python_windows/pubspec.yaml index b938212a..eb51edfe 100644 --- a/src/serious_python_windows/pubspec.yaml +++ b/src/serious_python_windows/pubspec.yaml @@ -2,13 +2,10 @@ name: serious_python_windows description: Windows implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -<<<<<<< HEAD -version: 0.9.5+1 -resolution: workspace -======= version: 0.9.8+1 ->>>>>>> 93d636cc64931cefc89dbcf73cbd57f27fb4d309 + +resolution: workspace environment: sdk: '>=3.7.0 < 4.0.0' From 5132afb001b7df4d86fa2da2b04efb4ad989fac2 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Thu, 26 Feb 2026 07:01:21 -0500 Subject: [PATCH 20/24] FIx bad merge --- src/serious_python_darwin/pubspec.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/serious_python_darwin/pubspec.yaml b/src/serious_python_darwin/pubspec.yaml index 73a9b58c..3c5f87a5 100644 --- a/src/serious_python_darwin/pubspec.yaml +++ b/src/serious_python_darwin/pubspec.yaml @@ -2,13 +2,9 @@ name: serious_python_darwin description: iOS and macOS implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -<<<<<<< HEAD -version: 0.9.5+1 +version: 0.9.8+1 resolution: workspace -======= -version: 0.9.8+1 ->>>>>>> 93d636cc64931cefc89dbcf73cbd57f27fb4d309 environment: sdk: '>=3.7.0 < 4.0.0' From 1baa167ac7ef2c635c12e4deaffe6a9297e093b6 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Thu, 26 Feb 2026 07:05:10 -0500 Subject: [PATCH 21/24] Updated untracked --- src/serious_python/example/searxng_example/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/serious_python/example/searxng_example/.gitignore b/src/serious_python/example/searxng_example/.gitignore index 3efbe6a0..8c9ab10f 100644 --- a/src/serious_python/example/searxng_example/.gitignore +++ b/src/serious_python/example/searxng_example/.gitignore @@ -28,6 +28,8 @@ migrate_working_dir/ .flutter-plugins .flutter-plugins-dependencies .packages +pubspec.lock +.metadata .pub-cache/ .pub/ /build/ From 28be69c5842647ff3089c9985814dfca7bf198d2 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Thu, 26 Feb 2026 07:05:19 -0500 Subject: [PATCH 22/24] Updated deps --- src/serious_python/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serious_python/pubspec.yaml b/src/serious_python/pubspec.yaml index 49ffc0a2..09eab641 100644 --- a/src/serious_python/pubspec.yaml +++ b/src/serious_python/pubspec.yaml @@ -49,7 +49,7 @@ dependencies: archive: ^4.0.7 path: ^1.9.1 args: ^2.7.0 - toml: ^0.17.0 + toml: ^0.18.0 http: ^1.5.0 shelf: ^1.4.2 crypto: ^3.0.6 From 4ed379c6db754dd0c72bd61902298415a0286494 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Thu, 26 Feb 2026 07:10:45 -0500 Subject: [PATCH 23/24] Fix wrong port --- src/serious_python/example/searxng_example/lib/main.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/serious_python/example/searxng_example/lib/main.dart b/src/serious_python/example/searxng_example/lib/main.dart index 78f7100a..80b3bfbb 100644 --- a/src/serious_python/example/searxng_example/lib/main.dart +++ b/src/serious_python/example/searxng_example/lib/main.dart @@ -40,7 +40,7 @@ class _MyAppState extends State { Future getServiceResult() async { while (true) { try { - var response = await http.get(Uri.parse("http://127.0.0.1:11881/mcp")); + var response = await http.get(Uri.parse("http://127.0.0.1:11888/mcp")); setState(() { _result = response.body; }); @@ -103,7 +103,7 @@ class _MyAppState extends State { http .post( Uri.parse( - "http://127.0.0.1:11881/mcp"), + "http://127.0.0.1:11888/mcp"), headers: { 'Content-Type': 'application/json' }, From 5d860055ae4582eaa158a5d6901e4c368c5e82f5 Mon Sep 17 00:00:00 2001 From: Sheldon Robinson Date: Thu, 26 Feb 2026 07:22:38 -0500 Subject: [PATCH 24/24] Fix bad package --- .../example/{flask_example => searxng_example}/MainActivity.kt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/serious_python/example/searxng_example/android/app/src/main/kotlin/com/example/{flask_example => searxng_example}/MainActivity.kt (100%) diff --git a/src/serious_python/example/searxng_example/android/app/src/main/kotlin/com/example/flask_example/MainActivity.kt b/src/serious_python/example/searxng_example/android/app/src/main/kotlin/com/example/searxng_example/MainActivity.kt similarity index 100% rename from src/serious_python/example/searxng_example/android/app/src/main/kotlin/com/example/flask_example/MainActivity.kt rename to src/serious_python/example/searxng_example/android/app/src/main/kotlin/com/example/searxng_example/MainActivity.kt