forked from retoor/devplacepy
Code Farm: per-plot auto-replant pause and crop-lock check; community sync and node work
Continuous Delivery could never be turned off once a crop was planted. Add a one-shot per-plot "stop after harvest" flag (POST /game/plot/stop, Devii tool game_plot_stop, game_plots.stop_after_harvest), cleared by the next plant, autoreplant claim or Refactor. Autoreplant now also respects crop locks through the shared _crop_lock predicate. Plan and measurements in happyplanting.md. Also includes the pending community sync, node network and related work in the tree; the full suite passed (4999) with all of it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,15 +4,29 @@ import json
|
||||
from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit
|
||||
|
||||
|
||||
class FakeBinary:
|
||||
def __init__(self, data: bytes, content_type: str = "image/png"):
|
||||
self.data = data
|
||||
self.content_type = content_type
|
||||
|
||||
|
||||
class FakeResponse:
|
||||
def __init__(self, status: int, body):
|
||||
self.status = status
|
||||
self.body = body if isinstance(body, str) else json.dumps(body)
|
||||
self.raw = b""
|
||||
self.headers = {}
|
||||
if isinstance(body, FakeBinary):
|
||||
self.raw, self.body = body.data, ""
|
||||
self.headers = {"content-type": body.content_type}
|
||||
else:
|
||||
self.body = body if isinstance(body, str) else json.dumps(body)
|
||||
|
||||
async def text(self):
|
||||
return self.body
|
||||
|
||||
async def read(self):
|
||||
return self.raw or self.body.encode()
|
||||
|
||||
async def json(self):
|
||||
return json.loads(self.body)
|
||||
|
||||
@@ -23,6 +37,8 @@ class FakeFetcher:
|
||||
self.requests: list[str] = []
|
||||
self.session = None
|
||||
self.posts: list[tuple] = []
|
||||
self.last_headers = None
|
||||
self.get_headers: list = []
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
@@ -40,6 +56,7 @@ class FakeFetcher:
|
||||
async def get(self, url, params=None, timeout=None, **kwargs):
|
||||
key = self.key(url, params)
|
||||
self.requests.append(key)
|
||||
self.get_headers.append(kwargs.get("headers"))
|
||||
route = self.routes.get(key)
|
||||
if route is None:
|
||||
return FakeResponse(404, "not found")
|
||||
@@ -49,10 +66,12 @@ class FakeFetcher:
|
||||
return FakeResponse(status, body)
|
||||
|
||||
async def post(self, url, data=None, timeout=None, **kwargs):
|
||||
self.posts.append((url, dict(data or {})))
|
||||
body = dict(data or kwargs.get("json") or {})
|
||||
self.posts.append((url, body))
|
||||
self.last_headers = kwargs.get("headers")
|
||||
route = self.routes.get("post:" + url)
|
||||
if callable(route):
|
||||
route = route(dict(data or {}))
|
||||
route = route(body)
|
||||
status, body = route if isinstance(route, tuple) else (200, route or "")
|
||||
return FakeResponse(status, body)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user