Spaces:
Running on Zero
Running on Zero
Download tools_basic.py from Atomicflee/unni: direct link, hf CLI and curl.
- Browser
- Download file 2.94 kB
-
https://huggingface.co/spaces/Atomicflee/unni/resolve/main/tools_basic.py
- Command line
-
hf download hf://spaces/Atomicflee/unni/tools_basic.py
-
curl -L -o tools_basic.py https://huggingface.co/spaces/Atomicflee/unni/resolve/main/tools_basic.py
2.94 kB
| """Offline/simple tools: exact calculator and weather.""" | |
| import ast | |
| import operator | |
| import requests | |
| _OPS = {ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, ast.Div: operator.truediv, | |
| ast.FloorDiv: operator.floordiv, ast.Mod: operator.mod, ast.Pow: operator.pow, | |
| ast.USub: operator.neg, ast.UAdd: operator.pos} | |
| def _eval(node): | |
| if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)): | |
| return node.value | |
| if isinstance(node, ast.BinOp) and type(node.op) in _OPS: | |
| if isinstance(node.op, ast.Pow) and abs(_eval(node.right)) > 1000: | |
| raise ValueError("exponent too large") | |
| return _OPS[type(node.op)](_eval(node.left), _eval(node.right)) | |
| if isinstance(node, ast.UnaryOp) and type(node.op) in _OPS: | |
| return _OPS[type(node.op)](_eval(node.operand)) | |
| raise ValueError("unsupported expression") | |
| def calculator(expression: str) -> str: | |
| """Evaluate an arithmetic expression exactly. Supports + - * / // % ** and parentheses. | |
| Args: | |
| expression: The arithmetic expression, for example '(1500 * 18) / 100'. | |
| """ | |
| try: | |
| expr = expression.replace("×", "*").replace("÷", "/").replace("^", "**").replace(",", "") | |
| r = _eval(ast.parse(expr, mode="eval").body) | |
| return str(round(r, 10) if isinstance(r, float) else r) | |
| except Exception as e: | |
| return f"Could not calculate: {e}" | |
| def weather(place: str) -> str: | |
| """Get the current weather and a 3-day forecast for a town or city. | |
| Args: | |
| place: Town or city name, for example 'Aluva' or 'Kochi'. | |
| """ | |
| try: | |
| g = requests.get("https://geocoding-api.open-meteo.com/v1/search", timeout=10, | |
| params={"name": place, "count": 1}).json().get("results") | |
| if not g: | |
| return f"Place not found: {place}" | |
| g = g[0] | |
| w = requests.get("https://api.open-meteo.com/v1/forecast", timeout=10, params={ | |
| "latitude": g["latitude"], "longitude": g["longitude"], "timezone": "auto", "forecast_days": 3, | |
| "current": "temperature_2m,relative_humidity_2m,precipitation,wind_speed_10m", | |
| "daily": "temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max"}).json() | |
| c, d = w["current"], w["daily"] | |
| lines = [f"{g['name']}, {g.get('admin1', '')}, {g.get('country', '')}", | |
| f"Now: {c['temperature_2m']}°C, humidity {c['relative_humidity_2m']}%, " | |
| f"rain {c['precipitation']} mm, wind {c['wind_speed_10m']} km/h"] | |
| for i, day in enumerate(d["time"]): | |
| lines.append(f"{day}: {d['temperature_2m_min'][i]}–{d['temperature_2m_max'][i]}°C, " | |
| f"rain {d['precipitation_sum'][i]} mm ({d['precipitation_probability_max'][i]}%)") | |
| return "\n".join(lines) | |
| except Exception as e: | |
| return f"Weather lookup failed: {e}" | |