Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cherab/jet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
# under the Licence.

from .equilibrium import *
from .sal import sal
from .sal import JETSALClient, get_jet_sal
3 changes: 2 additions & 1 deletion cherab/jet/equilibrium/equilibrium.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from raysect.core import Point2D
from cherab.tools.equilibrium import EFITEquilibrium

from cherab.jet.sal import sal
from cherab.jet.sal import JETSALClient
from sal.core.exception import NodeNotFound


Expand All @@ -46,6 +46,7 @@ def __init__(self, pulse, user=None, dda=None, sequence=None):

DDA_PATH = '/pulse/{}/ppf/signal/{}/{}:{}'
DATA_PATH = '/pulse/{}/ppf/signal/{}/{}/{}:{}'
sal = JETSALClient()

# defaults
user = user or 'jetppf'
Expand Down
24 changes: 22 additions & 2 deletions cherab/jet/sal.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,25 @@
from sal.client import SALClient


sal_server = os.environ.get('JET_SAL_SERVER', 'https://sal.jetdata.eu')
sal = SALClient(host=sal_server)
SAL_SERVER = os.environ.get('JET_SAL_SERVER', 'https://sal.jetdata.eu')


class JETSALClient(SALClient):
"""SALClient with host `sal.jetdata.eu` by default, or env variable `JET_SAL_SERVER`."""
def __init__(self, host: str = SAL_SERVER, **kwargs):
super().__init__(host=host, **kwargs)


def get_jet_sal(host: str = SAL_SERVER, **kwargs) -> SALClient:
"""Creates a SALClient instance connected to `host` if provided.
By default uses env variable `JET_SAL_SERVER` if set, `https://sal.jetdata.eu` otherwise.
"""
return SALClient(host=host, **kwargs)


def __getattr__(name: str):
Comment on lines +15 to +22
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless Github's formatting is off, I think you're missing some indentation here: these functions should be class methods.

Copy link
Author

@skuba31 skuba31 Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the indentation is correct. I should have provided better explanation in the first description.

I wanted to create two ways for SAL creation, a function returning standard SAL class and a subclass that could potentially be expanded for other functionalities that jet.data.sal defines. I suppose one could be dropped in order to have one standardized way.

The custom getattr method should be on the module level to allow use of the current notation from cherab.jet.sal import sal introduced in #35 with the difference, that SAL server connection is checked only if this import is executed in code, not on package import itself.
This should ensure, that any scripts created with this notation remain working as long as SAL server is reachable.

The problem could be that custom getattr is available for python 3.7+. I am not sure what is the minimal python version cherab-jet aims to support.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. That's a bit un-intuitive but makes sense. Essentially what you want is a lazy import, right? This could be done using importlib's LazyLoader (https://docs.python.org/3/library/importlib.html#implementing-lazy-imports): the intention may be a bit clearer to those reading the code.

if name == "sal":
value = get_jet_sal()
globals()[name] = value # cache on the module
return value
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")