greenpick 0.5.1__tar.gz → 0.5.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {greenpick-0.5.1/src/greenpick.egg-info → greenpick-0.5.2}/PKG-INFO +1 -1
- {greenpick-0.5.1 → greenpick-0.5.2}/pyproject.toml +1 -1
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/__init__.py +1 -1
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/models.py +1 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/locality_service.py +8 -1
- {greenpick-0.5.1 → greenpick-0.5.2/src/greenpick.egg-info}/PKG-INFO +1 -1
- {greenpick-0.5.1 → greenpick-0.5.2}/tests/test_services.py +14 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/LICENSE +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/README.md +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/setup.cfg +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/__main__.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/config.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/__init__.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/_net.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/annual.json +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/auto_repository.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/canada_repository.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/eia_repository.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/electricitymaps_repository.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/emission_factors.json +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/entsoe_repository.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/gpu_power.json +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/inference_energy.json +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/instance_families.json +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/mock_repository.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/network.json +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/power.json +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/pricing.json +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/regions.json +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/repository.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/static_data.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/typical.json +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/data/typical_repository.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/server.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/__init__.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/carbon_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/cost_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/data_hint.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/forecast_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/inference_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/instance_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/latency_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/metric_scaffold_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/offhours_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/recommender.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/residency_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/rightsizing_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/scheduling_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/serving_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/training_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick/services/typical_ranking_service.py +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick.egg-info/SOURCES.txt +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick.egg-info/dependency_links.txt +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick.egg-info/entry_points.txt +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick.egg-info/requires.txt +0 -0
- {greenpick-0.5.1 → greenpick-0.5.2}/src/greenpick.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: greenpick
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: Design-time sustainability co-pilot (MCP server): greener, cheaper cloud infrastructure decisions with carbon + cost + latency tradeoffs.
|
|
5
5
|
Author-email: "Data Science Advisers, LLC" <info@datascienceadvisers.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "greenpick"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.2"
|
|
4
4
|
description = "Design-time sustainability co-pilot (MCP server): greener, cheaper cloud infrastructure decisions with carbon + cost + latency tradeoffs."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -4,7 +4,7 @@ Greener cloud-region choices with honest carbon + cost + latency tradeoffs,
|
|
|
4
4
|
delivered inside the vibe-coding loop. Directional guidance, not audited accounting.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
__version__ = "0.5.
|
|
7
|
+
__version__ = "0.5.2"
|
|
8
8
|
|
|
9
9
|
# httpx logs every request URL at INFO, and our live sources pass their API key / token as a URL
|
|
10
10
|
# query parameter — so at the default log level the secret would land in the MCP client's logs.
|
|
@@ -303,6 +303,7 @@ class DataLocalityWarning(BaseModel):
|
|
|
303
303
|
|
|
304
304
|
The core 'does the greener-region move backfire?' check. Primary signal is egress COST;
|
|
305
305
|
transfer carbon is a secondary, deliberately-coarse figure."""
|
|
306
|
+
summary: str = "" # one line, FIRST key: the answer or what is missing
|
|
306
307
|
compute_location: str # "provider/region"
|
|
307
308
|
data_location: str # "provider/region"
|
|
308
309
|
monthly_cross_boundary_gb: float
|
|
@@ -78,6 +78,7 @@ async def data_locality_check(
|
|
|
78
78
|
egress_rate_usd_per_gb_low=0.0, egress_rate_usd_per_gb_high=0.0,
|
|
79
79
|
est_monthly_egress_usd_low=0.0, est_monthly_egress_usd_high=0.0,
|
|
80
80
|
est_monthly_transfer_kg_co2=0.0,
|
|
81
|
+
summary="No cross-boundary egress: compute and data are in the same region.",
|
|
81
82
|
warning="Compute and data are co-located — no cross-boundary egress for this flow.",
|
|
82
83
|
recommendation="No locality penalty. Choose the region on carbon/latency/cost as usual.",
|
|
83
84
|
limitations=LIMITATIONS,
|
|
@@ -137,6 +138,12 @@ async def data_locality_check(
|
|
|
137
138
|
"whether the move backfires on carbon. Ask the user for it, or compute it as the difference "
|
|
138
139
|
"between estimate_workload_carbon in the two regions, and call again. " + warning)
|
|
139
140
|
|
|
141
|
+
if verdict is None:
|
|
142
|
+
summary = ("NO NET VERDICT: carbon_saving_kg_co2_from_move was not provided, so this does not say "
|
|
143
|
+
f"whether the move backfires. Estimated {cost_txt.replace('roughly ', '')}; "
|
|
144
|
+
f"transfer ~{transfer_kg:.1f} kg CO2/mo. Supply the saving and call again.")
|
|
145
|
+
else:
|
|
146
|
+
summary = f"{verdict} Estimated {cost_txt.replace('roughly ', '')}."
|
|
140
147
|
if severity == "high":
|
|
141
148
|
rec = ("High exposure. Co-locate compute with the data, or move the data to the greener "
|
|
142
149
|
"region too. If you can't, confirm the carbon/cost saving beats this egress penalty "
|
|
@@ -163,6 +170,6 @@ async def data_locality_check(
|
|
|
163
170
|
est_monthly_transfer_kg_co2=transfer_kg,
|
|
164
171
|
transfer_carbon_source=reading.source, transfer_carbon_quality=reading.quality,
|
|
165
172
|
carbon_saving_kg_co2_from_move=carbon_saving_kg_co2_from_move,
|
|
166
|
-
net_carbon_verdict=verdict, verdict_status=verdict_status, residency_note=residency_note,
|
|
173
|
+
summary=summary, net_carbon_verdict=verdict, verdict_status=verdict_status, residency_note=residency_note,
|
|
167
174
|
warning=warning, recommendation=rec, limitations=LIMITATIONS,
|
|
168
175
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: greenpick
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: Design-time sustainability co-pilot (MCP server): greener, cheaper cloud infrastructure decisions with carbon + cost + latency tradeoffs.
|
|
5
5
|
Author-email: "Data Science Advisers, LLC" <info@datascienceadvisers.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -1895,3 +1895,17 @@ async def test_locality_without_saving_says_no_verdict():
|
|
|
1895
1895
|
assert no.warning.startswith("NO NET VERDICT") and "carbon_saving_kg_co2_from_move" in no.warning
|
|
1896
1896
|
yes = await ls.data_locality_check(MockCarbonRepository(), carbon_saving_kg_co2_from_move=40.0, **base)
|
|
1897
1897
|
assert yes.verdict_status == "evaluated" and not yes.warning.startswith("NO NET VERDICT")
|
|
1898
|
+
|
|
1899
|
+
|
|
1900
|
+
# --- 0.5.2: the one-line summary is the FIRST key, so partial printouts still show it ---
|
|
1901
|
+
@pytest.mark.asyncio
|
|
1902
|
+
async def test_locality_summary_is_first_key_and_flags_missing_verdict():
|
|
1903
|
+
from greenpick.services import locality_service as ls
|
|
1904
|
+
base = dict(compute_provider="aws", compute_region="eu-north-1",
|
|
1905
|
+
data_provider="aws", data_region="us-east-1", monthly_cross_boundary_gb=100)
|
|
1906
|
+
no = (await ls.data_locality_check(MockCarbonRepository(), **base)).model_dump()
|
|
1907
|
+
assert next(iter(no)) == "summary" and no["summary"].startswith("NO NET VERDICT")
|
|
1908
|
+
yes = (await ls.data_locality_check(MockCarbonRepository(), carbon_saving_kg_co2_from_move=40.0, **base)).model_dump()
|
|
1909
|
+
assert "net win" in yes["summary"].lower() and not yes["summary"].startswith("NO NET VERDICT")
|
|
1910
|
+
same = (await ls.data_locality_check(MockCarbonRepository(), "aws", "us-east-1", "aws", "us-east-1", 100)).model_dump()
|
|
1911
|
+
assert next(iter(same)) == "summary" and same["summary"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|