jupyterlite-simple-cors-proxy 0.1.8__py3-none-any.whl → 0.1.10__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  # File: jupyterlite_simple_cors_proxy/__init__.py
2
- from .proxy import cors_proxy_get, robust_get_request, xurl, furl
2
+ from .cacheproxy import cors_proxy_get, robust_get_request, xurl, furl
3
3
 
4
4
  # from .fastf1_proxy import enable_cors_proxy as fastf1_cors_proxy
5
5
 
6
- __version__ = "0.1.8"
6
+ __version__ = "0.1.10"
7
7
  __all__ = ["cors_proxy_get", "robust_get_request", "xurl", "furl"]
@@ -0,0 +1,83 @@
1
+ # File: simple_cors_proxy/proxy.py
2
+ from urllib.parse import urlencode, quote
3
+ import requests
4
+ import requests_cache
5
+ import io
6
+ import platform
7
+ from typing import Optional, Union
8
+
9
+ PLATFORM = platform.system().lower()
10
+
11
+ class CorsProxy:
12
+ """CORS Proxy with optional caching support."""
13
+
14
+ def __init__(self, use_cache: bool = False, **cache_kwargs):
15
+ """
16
+ Initialize the CORS proxy.
17
+
18
+ Args:
19
+ use_cache: Whether to enable request caching
20
+ **cache_kwargs: Arguments passed to requests_cache.CachedSession
21
+ (e.g., cache_name, backend, expire_after)
22
+ """
23
+ if use_cache:
24
+ # Set some sensible defaults if not provided
25
+ if 'cache_name' not in cache_kwargs:
26
+ cache_kwargs['cache_name'] = 'cors_proxy_cache'
27
+ if 'expire_after' not in cache_kwargs:
28
+ cache_kwargs['expire_after'] = 3600 # 1 hour default
29
+ self.session = requests_cache.CachedSession(**cache_kwargs)
30
+ else:
31
+ self.session = requests
32
+
33
+ def xurl(self, url: str, params: Optional[dict] = None, force: bool = False) -> str:
34
+ """Generate a proxied URL."""
35
+ if PLATFORM == "emscripten" or force:
36
+ if params:
37
+ url = f"{url}?{urlencode(params)}"
38
+ url = f"https://corsproxy.io/{quote(url)}"
39
+ return url
40
+
41
+ def furl(self, url: str, params: Optional[dict] = None, force: bool = False) -> io.BytesIO:
42
+ """Return file like object after calling the proxied URL."""
43
+ r = self.cors_proxy_get(url, params, force)
44
+ return io.BytesIO(r.content)
45
+
46
+ def cors_proxy_get(self, url: str, params: Optional[dict] = None, force: bool = False) -> requests.Response:
47
+ """
48
+ CORS proxy for GET resources with requests-like response.
49
+
50
+ Args:
51
+ url: The URL to fetch
52
+ params: Query parameters to include
53
+ force: Force using the proxy even on non-emscripten platforms
54
+
55
+ Returns:
56
+ A requests response object.
57
+ """
58
+ proxy_url = self.xurl(url, params, force)
59
+ return self.session.get(proxy_url)
60
+
61
+ def robust_get_request(self, url: str, params: Optional[dict] = None) -> requests.Response:
62
+ """
63
+ Try to make a simple request else fall back to a proxy.
64
+ """
65
+ try:
66
+ r = self.session.get(url, params=params)
67
+ except:
68
+ r = self.cors_proxy_get(url, params=params)
69
+ return r
70
+
71
+ # Create default instance
72
+ _default_proxy = CorsProxy()
73
+
74
+ # Legacy function-based interface
75
+ xurl = _default_proxy.xurl
76
+ furl = _default_proxy.furl
77
+ cors_proxy_get = _default_proxy.cors_proxy_get
78
+ robust_get_request = _default_proxy.robust_get_request
79
+
80
+ # Convenience function to create a cached proxy
81
+ def create_cached_proxy(**cache_kwargs):
82
+ """Create a new CorsProxy instance with caching enabled."""
83
+ return CorsProxy(use_cache=True, **cache_kwargs)
@@ -4,17 +4,20 @@ import requests
4
4
  import io
5
5
 
6
6
  import platform
7
+
7
8
  PLATFORM = platform.system().lower()
8
9
 
10
+
9
11
  def xurl(url, params=None, force=False):
10
12
  """Generate a proxied URL."""
11
- if PLATFORM=="emscripten" or force:
13
+ if PLATFORM == "emscripten" or force:
12
14
  if params:
13
15
  url = f"{url}?{urlencode(params)}"
14
16
  url = f"https://corsproxy.io/{quote(url)}"
15
17
 
16
18
  return url
17
19
 
20
+
18
21
  def furl(url, params=None, force=False):
19
22
  """Return file like object after calling the proxied URL."""
20
23
  r = cors_proxy_get(url, params, force)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: jupyterlite-simple-cors-proxy
3
- Version: 0.1.8
3
+ Version: 0.1.10
4
4
  Summary: A simple CORS proxy utility with requests-like response
5
5
  Home-page: https://github.com/innovationOUtside/jupyterlite-simple-cors-proxy
6
6
  Author: Tony Hirst
@@ -65,3 +65,51 @@ The `robust_get_request()` will first try a simple request, then a proxied reque
65
65
  - Simple CORS proxy wrapper
66
66
  - Requests response object
67
67
  - Support for URL parameters
68
+
69
+ ## `fastf1` cors proxy
70
+
71
+ A monkey patch for `fastf1` is provided as:
72
+
73
+ ```python
74
+ import fast f1
75
+ from jupyterlite_simple_cors_proxy.fastf1_proxy import enable_cors_proxy
76
+
77
+ enable_cors_proxy(
78
+ # domains=["api.formula1.com", "livetiming.formula1.com"],
79
+ # debug=True,
80
+ # proxy_url="https://corsproxy.io/",
81
+ )
82
+ ```
83
+
84
+ ## `CorsProxy` with cache facility
85
+
86
+ Via `claude.ai`, the package is now further enriched.
87
+
88
+ *Note that `pyodide` sqlite can't write to `/drive` so the cache path dir needs to be something like `/tmp` or a dir created on `/`.*
89
+
90
+ *I'm not convinced the following works in `pyodide` and `xeus-python` yet - `requests-cache` dependency issues etc.*
91
+
92
+ ```python
93
+ from simple_cors_proxy.proxy import CorsProxy
94
+
95
+ # Create a cached proxy instance
96
+ proxy = CorsProxy(use_cache=True, expire_after=3600) # Cache for 1 hour
97
+
98
+ # Use furl directly from your proxy instance
99
+ file_like = proxy.furl('https://example.com/somefile.csv')
100
+
101
+ #----
102
+ import pandas as pd
103
+ from simple_cors_proxy.cacheproxy import CorsProxy
104
+
105
+ proxy = CorsProxy(use_cache=True)
106
+ file_like = proxy.furl('https://example.com/data.csv')
107
+ df = pd.read_csv(file_like)
108
+
109
+ #----
110
+
111
+ from simple_cors_proxy.proxy import create_cached_proxy
112
+
113
+ proxy = create_cached_proxy(cache_name='my_cache', expire_after=86400) # Cache for 1 day
114
+ file_like = proxy.furl('https://example.com/somefile.csv')
115
+ ```
@@ -0,0 +1,9 @@
1
+ jupyterlite_simple_cors_proxy/__init__.py,sha256=QNqJ64TlAKsoaOKeVcRqeaibDiO3SpOyEakvenkuiuU,280
2
+ jupyterlite_simple_cors_proxy/cacheproxy.py,sha256=SzKQrflMbIJdHoDZ2dtRenGCAGMZEBSl_fs7sjIkiHk,2989
3
+ jupyterlite_simple_cors_proxy/fastf1_proxy.py,sha256=FglRogTIlSJvHOu6lFS3S-EHDb37M93aYjQpoKc1QYs,7614
4
+ jupyterlite_simple_cors_proxy/proxy.py,sha256=uFpevhGlkbcNqVb1d43uBrqVdvAbOQ2m1PLqxsML6BE,1346
5
+ jupyterlite_simple_cors_proxy-0.1.10.dist-info/LICENSE,sha256=Ogw7GUmeZIxmDNiKWsu_N07svNoGnPB7lWyiXHX_rMY,1074
6
+ jupyterlite_simple_cors_proxy-0.1.10.dist-info/METADATA,sha256=g2KklCts9AuEwEUEQ7EpaMh9JBAE8Nmb050_yZNqZbs,3059
7
+ jupyterlite_simple_cors_proxy-0.1.10.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
8
+ jupyterlite_simple_cors_proxy-0.1.10.dist-info/top_level.txt,sha256=Oh0oQrSmRnBq5u675coiKMbkb2ASg8AGF8ZiZTzUS5Q,30
9
+ jupyterlite_simple_cors_proxy-0.1.10.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- jupyterlite_simple_cors_proxy/__init__.py,sha256=fFGdcTl9-jFFAQJVrb1KXt8dh8NH-JcS79FvAtFT3T4,274
2
- jupyterlite_simple_cors_proxy/fastf1_proxy.py,sha256=FglRogTIlSJvHOu6lFS3S-EHDb37M93aYjQpoKc1QYs,7614
3
- jupyterlite_simple_cors_proxy/proxy.py,sha256=hF7SeLx7whBkE8m8bDUaelx2tKfLrSHA_Lp_auFtqeY,1341
4
- jupyterlite_simple_cors_proxy-0.1.8.dist-info/LICENSE,sha256=Ogw7GUmeZIxmDNiKWsu_N07svNoGnPB7lWyiXHX_rMY,1074
5
- jupyterlite_simple_cors_proxy-0.1.8.dist-info/METADATA,sha256=VCrtXTTVM4n0BsH-f2siz3s9SeWTDwGcVNJjvvfdz7k,1718
6
- jupyterlite_simple_cors_proxy-0.1.8.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
7
- jupyterlite_simple_cors_proxy-0.1.8.dist-info/top_level.txt,sha256=Oh0oQrSmRnBq5u675coiKMbkb2ASg8AGF8ZiZTzUS5Q,30
8
- jupyterlite_simple_cors_proxy-0.1.8.dist-info/RECORD,,