Title
ESOAPI.__init__ fails for environment='production_lasilla' because it unconditionally requires a Phase 1 (p1api) connection that doesn't support that environment
Summary
tom_eso.eso_api.ESOAPI.__init__ always constructs two API connections — a Phase 1 connection (p1api.ApiConnection) followed by a Phase 2 connection (p2api.ApiConnection) — even for callers who only need Phase 2 functionality (e.g. getOB, getOBExecutions, getNightExecutions, getRuns). This makes it impossible to construct an ESOAPI instance for La Silla (environment='production_lasilla') at all, because the p1api (Phase 1 / Proposal Preparation) client doesn't support that environment string, even though the underlying Phase 2 API does.
Versions
tom-eso 0.2.4
p2api (PyPI p2api) 1.0.10
p1api (PyPI phase1api) 0.0.2
Steps to reproduce
from tom_eso.eso_api import ESOAPI
eso = ESOAPI('production_lasilla', username, password)
Expected behavior
Given real, working ESO P2 credentials with La Silla access (confirmed via the ESO P2 web portal, https://www.eso.org/p2ls/home), this should succeed and allow calling Phase-2-only methods (getOB, getOBExecutions, getNightExecutions, getRuns, etc.) against La Silla.
Actual behavior
Raises immediately, before the Phase 2 connection is ever attempted:
ESOAPI.__init__: Error creating API connections: (500, 'POST', 'production_lasilla', 'environment not supported')
p1api.p1api.P1Error: (500, 'POST', 'production_lasilla', 'environment not supported')
Root cause
In tom_eso/eso_api.py, ESOAPI.__init__ does:
self.api1 = p1api.ApiConnection(self.environment, self.username, self.password)
self.api2 = p2api.ApiConnection(self.environment, self.username, self.password)
self.api1 (Phase 1) is constructed first, and unconditionally, regardless of whether the caller ever uses any Phase 1 functionality.
p1api.p1api.API_URL only defines two environments:
API_URL = {
'production' : 'https://www.eso.org/cop1/api',
'demo' : 'https://www.eso.org/cop1demo/api'
}
There is no production_lasilla entry, so p1api.ApiConnection.__init__ raises P1Error(500, 'POST', 'production_lasilla', 'environment not supported') — before self.api2 (the Phase 2 connection actually needed for OB status/execution data) is ever constructed.
By contrast, p2api.p2api.API_URL does define a La Silla entry:
API_URL = {
'production' : 'https://www.eso.org/cop/api/v1',
'production_lasilla': 'https://www.eso.org/copls/api/v1',
...
}
So the Phase 2 API itself supports La Silla — ESOAPI just never gets the chance to reach it.
Confirmed workaround
Bypassing ESOAPI entirely and constructing a p2api.ApiConnection directly against production_lasilla connects successfully and returns real data:
import p2api
p2api.ApiConnection('production_lasilla', username, password).getRuns()
This confirms the account has working La Silla P2 (Phase 2) access, and that the failure above is purely an artifact of ESOAPI's unconditional Phase 1 connection, not a genuine API/account limitation.
Suggested fix
One of:
- Make the Phase 1 connection lazy — only construct
self.api1 when a Phase 1 method is actually called (or via a property/lazy-init), so Phase-2-only usage (which is most of what ESOAPI exposes today — getOB, getOBExecutions, getNightExecutions, getRuns, etc.) doesn't require it at all.
- Make the Phase 1 connection optional — e.g. a constructor flag or try/except around
self.api1 construction that logs a warning and leaves self.api1 = None on environments Phase 1 doesn't support, rather than failing the whole ESOAPI construction.
- At minimum, if Phase 1 genuinely doesn't support La Silla, that's worth calling out explicitly in
ESOAPI's docstring/README, since the current failure mode (a P1Error about production_lasilla "not supported") reads as "La Silla isn't supported at all," which isn't true for Phase 2.
Happy to submit this as a PR if a maintainer can confirm which direction (1 vs 2) is preferred.
Title
ESOAPI.__init__fails forenvironment='production_lasilla'because it unconditionally requires a Phase 1 (p1api) connection that doesn't support that environmentSummary
tom_eso.eso_api.ESOAPI.__init__always constructs two API connections — a Phase 1 connection (p1api.ApiConnection) followed by a Phase 2 connection (p2api.ApiConnection) — even for callers who only need Phase 2 functionality (e.g.getOB,getOBExecutions,getNightExecutions,getRuns). This makes it impossible to construct anESOAPIinstance for La Silla (environment='production_lasilla') at all, because thep1api(Phase 1 / Proposal Preparation) client doesn't support that environment string, even though the underlying Phase 2 API does.Versions
tom-eso0.2.4p2api(PyPIp2api) 1.0.10p1api(PyPIphase1api) 0.0.2Steps to reproduce
Expected behavior
Given real, working ESO P2 credentials with La Silla access (confirmed via the ESO P2 web portal,
https://www.eso.org/p2ls/home), this should succeed and allow calling Phase-2-only methods (getOB,getOBExecutions,getNightExecutions,getRuns, etc.) against La Silla.Actual behavior
Raises immediately, before the Phase 2 connection is ever attempted:
Root cause
In
tom_eso/eso_api.py,ESOAPI.__init__does:self.api1(Phase 1) is constructed first, and unconditionally, regardless of whether the caller ever uses any Phase 1 functionality.p1api.p1api.API_URLonly defines two environments:There is no
production_lasillaentry, sop1api.ApiConnection.__init__raisesP1Error(500, 'POST', 'production_lasilla', 'environment not supported')— beforeself.api2(the Phase 2 connection actually needed for OB status/execution data) is ever constructed.By contrast,
p2api.p2api.API_URLdoes define a La Silla entry:So the Phase 2 API itself supports La Silla —
ESOAPIjust never gets the chance to reach it.Confirmed workaround
Bypassing
ESOAPIentirely and constructing ap2api.ApiConnectiondirectly againstproduction_lasillaconnects successfully and returns real data:This confirms the account has working La Silla P2 (Phase 2) access, and that the failure above is purely an artifact of
ESOAPI's unconditional Phase 1 connection, not a genuine API/account limitation.Suggested fix
One of:
self.api1when a Phase 1 method is actually called (or via a property/lazy-init), so Phase-2-only usage (which is most of whatESOAPIexposes today —getOB,getOBExecutions,getNightExecutions,getRuns, etc.) doesn't require it at all.self.api1construction that logs a warning and leavesself.api1 = Noneon environments Phase 1 doesn't support, rather than failing the wholeESOAPIconstruction.ESOAPI's docstring/README, since the current failure mode (aP1Erroraboutproduction_lasilla"not supported") reads as "La Silla isn't supported at all," which isn't true for Phase 2.Happy to submit this as a PR if a maintainer can confirm which direction (1 vs 2) is preferred.