Skip to content

Commit 292f5da

Browse files
Merge remote-tracking branch 'origin/main' into 2-handle-serialized-magnets
2 parents 09c062f + 2ac3ded commit 292f5da

36 files changed

+14950
-15042
lines changed

examples/ESRF_tune_example/esrf_tune_example.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
from pyaml.pyaml import pyaml,PyAML
2-
from pyaml.instrument import Instrument
3-
from pyaml.configuration.factory import Factory
1+
from pyaml.accelerator import Accelerator
42
import numpy as np
53
import os
64

@@ -14,8 +12,7 @@
1412
# Normalize the path (resolves '..')
1513
absolute_path = os.path.abspath(relative_path)
1614

17-
ml:PyAML = pyaml(absolute_path)
18-
sr:Instrument = ml.get('sr')
15+
sr:Accelerator = Accelerator.load(absolute_path)
1916
sr.design.get_lattice().disable_6d()
2017

2118
quadForTuneDesign = sr.design.get_magnets("QForTune")
@@ -52,6 +49,3 @@
5249
strs = quadForTuneLive.strengths.get()
5350
strs += np.matmul(correctionmat,[0.1,0.05]) # Ask for correction [dqx,dqy]
5451
quadForTuneLive.strengths.set(strs)
55-
56-
57-
Factory.clear()
Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
from .lattice.simulator import Simulator
88
from .arrays.array import ArrayConfig
99
from pydantic import BaseModel,ConfigDict
10+
from .configuration import load_accelerator
1011

1112
# Define the main class name for this module
12-
PYAMLCLASS = "Instrument"
13+
PYAMLCLASS = "Accelerator"
1314

1415
class ConfigModel(BaseModel):
1516

@@ -31,7 +32,7 @@ class ConfigModel(BaseModel):
3132
"""Element list"""
3233

3334

34-
class Instrument(object):
35+
class Accelerator(object):
3536
"""PyAML top level class"""
3637

3738
def __init__(self, cfg: ConfigModel):
@@ -85,3 +86,18 @@ def live(self) -> ControlSystem:
8586
@property
8687
def design(self) -> Simulator:
8788
return self.__design
89+
90+
@staticmethod
91+
def load(filename:str, use_fast_loader:bool = False) -> "Accelerator":
92+
"""
93+
Load an accelerator from a config file.
94+
95+
Parameters
96+
----------
97+
filename : str
98+
Configuration file name, yaml or json.
99+
use_fast_loader : bool
100+
Use fast yaml loader. When specified, no line number are reported in case of error,
101+
only the element name that triggered the error will be reported in the exception)
102+
"""
103+
return load_accelerator(filename,use_fast_loader)

pyaml/configuration/__init__.py

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,5 @@
22
PyAML configuration module
33
"""
44

5-
from pathlib import Path
6-
from typing import Union
7-
8-
ROOT = {"path": Path.cwd().resolve()}
9-
10-
11-
def set_root_folder(path: Union[str, Path]):
12-
"""
13-
Set the root path for configuration files.
14-
"""
15-
ROOT["path"] = Path(path)
16-
17-
18-
def get_root_folder() -> Path:
19-
"""
20-
Get the root path for configuration files.
21-
"""
22-
return ROOT["path"]
23-
24-
from .fileloader import load
5+
from .fileloader import load_accelerator, set_root_folder, get_root_folder
256
from .factory import Factory

pyaml/configuration/factory.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def handle_validation_error(self, e, type_str:str, location_str:str, field_locat
5353
else:
5454
field = err['loc'][0]
5555
message = f"'{field}': {msg}"
56-
if field in field_locations:
56+
if field_locations and field in field_locations:
5757
file, line, col = field_locations[field]
5858
loc = f"{file} at line {line}, colum {col}"
5959
message += f" {loc}"

pyaml/configuration/fileloader.py

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,45 @@
11
# PyAML config file loader
22
import logging
33
import json
4-
from typing import Union
4+
from typing import Union, TYPE_CHECKING
55
from pathlib import Path
66
import io
7+
import os
78

89
import yaml
910
from yaml.loader import SafeLoader
11+
from yaml import CLoader
1012
from yaml.constructor import ConstructorError
1113
import collections.abc
1214

13-
from . import get_root_folder
1415
from .. import PyAMLException
16+
from pyaml.configuration.factory import Factory
17+
18+
if TYPE_CHECKING:
19+
from pyaml.accelerator import Accelerator
20+
1521

1622
logger = logging.getLogger(__name__)
1723

1824
accepted_suffixes = [".yaml", ".yml", ".json"]
1925

26+
27+
ROOT = {"path": Path.cwd().resolve()}
28+
29+
30+
def set_root_folder(path: Union[str, Path]):
31+
"""
32+
Set the root path for configuration files.
33+
"""
34+
ROOT["path"] = Path(path)
35+
36+
37+
def get_root_folder() -> Path:
38+
"""
39+
Get the root path for configuration files.
40+
"""
41+
return ROOT["path"]
42+
2043
class PyAMLConfigCyclingException(PyAMLException):
2144

2245
def __init__(self, error_filename:str, path_stack:list[Path]):
@@ -25,12 +48,26 @@ def __init__(self, error_filename:str, path_stack:list[Path]):
2548
super().__init__(f"Circular file inclusion of {error_filename}. File list before reaching it: {parent_file_stack}")
2649
pass
2750

28-
def load(filename:str, paths_stack:list=None) -> Union[dict,list]:
51+
def load_accelerator(filename:str, use_fast_loader:bool = False) -> "Accelerator":
52+
""" Load an accelerator from file."""
53+
54+
# Asume that all files are referenced from folder where main AML file is stored
55+
if not os.path.exists(filename):
56+
raise PyAMLException(f"{filename} file not found")
57+
rootfolder = os.path.abspath(os.path.dirname(filename))
58+
set_root_folder(rootfolder)
59+
config_dict = load(os.path.basename(filename),None,use_fast_loader)
60+
aml = Factory.depth_first_build(config_dict)
61+
62+
Factory.clear()
63+
return aml
64+
65+
def load(filename:str, paths_stack:list=None, use_fast_loader:bool = False) -> Union[dict,list]:
2966
"""Load recursively a configuration setup"""
3067
if filename.endswith(".yaml") or filename.endswith(".yml"):
31-
l = YAMLLoader(filename, paths_stack)
68+
l = YAMLLoader(filename, paths_stack, use_fast_loader)
3269
elif filename.endswith(".json"):
33-
l = JSONLoader(filename, paths_stack)
70+
l = JSONLoader(filename, paths_stack, use_fast_loader)
3471
else:
3572
raise PyAMLException(f"{filename} File format not supported (only .yaml .yml or .json)")
3673
return l.load()
@@ -58,7 +95,7 @@ def expand_dict(self,d:dict):
5895
for key, value in d.items():
5996
try:
6097
if hasToExpand(value):
61-
d[key] = load(value, self.files_stack)
98+
d[key] = load(value, self.files_stack, self.use_fast_loader)
6299
else:
63100
self.expand(value)
64101
except PyAMLConfigCyclingException as pyaml_ex:
@@ -119,21 +156,24 @@ def construct_mapping(self, node, deep=False):
119156

120157
# YAML loader
121158
class YAMLLoader(Loader):
122-
def __init__(self, filename: str, parent_paths_stack:list):
159+
def __init__(self, filename: str, parent_paths_stack:list,use_fast_loader:bool):
123160
super().__init__(filename, parent_paths_stack)
161+
self._loader = SafeLineLoader if not use_fast_loader else CLoader
162+
self.use_fast_loader = use_fast_loader
124163

125164
def load(self) -> Union[dict,list]:
126165
logger.log(logging.DEBUG, f"Loading YAML file '{self.path}'")
127166
with open(self.path) as file:
128167
try:
129-
return self.expand(yaml.load(file,Loader=SafeLineLoader))
168+
return self.expand(yaml.load(file,Loader=self._loader))
130169
except yaml.YAMLError as e:
131170
raise PyAMLException(str(self.path) + ": " + str(e)) from e
132171

133172
# JSON loader
134173
class JSONLoader(Loader):
135-
def __init__(self, filename: str, parent_paths_stack:list):
174+
def __init__(self, filename: str, parent_paths_stack:list,use_fast_loader:bool):
136175
super().__init__(filename, parent_paths_stack)
176+
self.use_fast_loader = False
137177

138178
def load(self) -> Union[dict,list]:
139179
logger.log(logging.DEBUG, f"Loading JSON file '{self.path}'")

pyaml/pyaml.py

Lines changed: 0 additions & 47 deletions
This file was deleted.

0 commit comments

Comments
 (0)