Skip to content

Commit

Permalink
Merge pull request #224 from tangkong/perf_lazy_page
Browse files Browse the repository at this point in the history
PERF/REF: Lazy Page loading
  • Loading branch information
tangkong authored Nov 18, 2023
2 parents ce4f64a + 9a149c5 commit 27163da
Show file tree
Hide file tree
Showing 30 changed files with 1,570 additions and 1,248 deletions.
11 changes: 9 additions & 2 deletions atef/bin/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ def build_arg_parser(argparser=None):
https://doc.qt.io/qt-5/qapplication.html#QApplication
https://doc.qt.io/qt-5/qguiapplication.html#supported-command-line-options
"""
argparser.add_argument(
"--cache-size",
metavar="cache_size",
type=int,
default=5,
help="Page widget cache size",
)

argparser.add_argument(
"filenames",
Expand All @@ -70,9 +77,9 @@ def build_arg_parser(argparser=None):
return argparser


def main(filenames: Optional[List[AnyPath]] = None, **kwargs):
def main(cache_size: int, filenames: Optional[List[AnyPath]] = None, **kwargs):
app = QApplication(sys.argv)
main_window = Window(show_welcome=not filenames)
main_window = Window(cache_size=cache_size, show_welcome=not filenames)
main_window.show()
exception.install()

Expand Down
30 changes: 30 additions & 0 deletions atef/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,32 @@ async def prepare(self, cache: Optional[DataCache] = None) -> None:
await comp.prepare(cache)
self.is_prepared = True

def children(self) -> List[Comparison]:
"""Return children of this group, as a tree view might expect"""
return self.comparisons

def replace_comparison(
self,
old_comp: Comparison,
new_comp: Comparison,
) -> None:
"""
Replace ``old_comp`` with ``new_comp`` in this dataclass.
A common method for all dataclasses that hold comparisons.
Parameters
----------
old_comp : Comparison
Comparsion to replace
new_comp : Comparison
Comparison to replace ``old_comp`` with
"""
util.replace_in_list(
old=old_comp,
new=new_comp,
item_list=self.comparisons,
)


@dataclass
class Greater(BasicDynamic):
Expand Down Expand Up @@ -843,3 +869,7 @@ async def prepare(self, cache: Optional[DataCache] = None) -> None:
await self.warn_high_dynamic.prepare(cache)
self.warn_high = self.warn_high_dynamic.get()
self.is_prepared = True


ALL_COMPARISONS = [Equals, NotEquals, Greater, GreaterOrEqual, Less, LessOrEqual,
Range, ValueSet, AnyValue, AnyComparison]
154 changes: 150 additions & 4 deletions atef/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,53 @@ class Configuration:
#: Tags tied to this configuration.
tags: Optional[List[str]] = None

def children(self) -> List[Any]:
"""Return children of this group, as a tree view might expect"""
return []

def replace_comparison(
self,
old_comp: Comparison,
new_comp: Comparison,
comp_attrs: Optional[List[str]] = None
) -> None:
"""
Replace ``old_comp`` with ``new_comp`` in this dataclass, wherever it is.
Looks through ``shared``, then any of the attributes in ``comp_attrs``
Parameters
----------
old_comp : Comparison
Comparison to be replaced
new_comp : Comparison
Comparison to replace ``old_comp`` with
comp_attrs : Optional[List[str]], optional
Attribute names in the dataclass to check, by default None
"""
comp_attrs = comp_attrs or []
if not any(hasattr(self, attr) for attr in comp_attrs + ["shared"]):
return

try:
util.replace_in_list(
old=old_comp,
new=new_comp,
item_list=self.shared,
)
except ValueError:
for attr in comp_attrs:
for comp_list in getattr(self, attr, {}).values():
try:
util.replace_in_list(
old=old_comp,
new=new_comp,
item_list=comp_list,
)
except ValueError:
continue
else:
break


@dataclass
class ConfigurationGroup(Configuration):
Expand All @@ -75,6 +122,10 @@ def walk_configs(self) -> Generator[AnyConfiguration, None, None]:
if isinstance(config, ConfigurationGroup):
yield from config.walk_configs()

def children(self) -> List[Configuration]:
"""Return children of this group, as a tree view might expect"""
return self.configs


@dataclass
class DeviceConfiguration(Configuration):
Expand All @@ -95,6 +146,35 @@ class DeviceConfiguration(Configuration):
#: Comparisons to be run on *all* identifiers in the `by_attr` dictionary.
shared: List[Comparison] = field(default_factory=list)

def children(self) -> List[Comparison]:
"""Return children of this group, as a tree view might expect"""
return ([comp for comp_list in self.by_attr.values() for comp in comp_list]
+ self.shared)

def replace_comparison(
self,
old_comp: Comparison,
new_comp: Comparison,
comp_attrs: Optional[List[str]] = None
) -> None:
"""
Replace ``old_comp`` with ``new_comp`` in this dataclass, wherever it is.
Looks through ``shared``, then any of the attributes in ``comp_attrs``
Parameters
----------
old_comp : Comparison
Comparison to be replaced
new_comp : Comparison
Comparison to replace ``old_comp`` with
comp_attrs : Optional[List[str]], optional
Attribute names in the dataclass to check, by default ['by_attr'] if
no value is provided
"""
if comp_attrs is None:
comp_attrs = ['by_attr']
super().replace_comparison(old_comp, new_comp, comp_attrs)


@dataclass
class PVConfiguration(Configuration):
Expand All @@ -106,6 +186,35 @@ class PVConfiguration(Configuration):
#: Comparisons to be run on *all* PVs in the `by_pv` dictionary.
shared: List[Comparison] = field(default_factory=list)

def children(self) -> List[Comparison]:
"""Return children of this group, as a tree view might expect"""
return ([comp for comp_list in self.by_pv.values() for comp in comp_list]
+ self.shared)

def replace_comparison(
self,
old_comp: Comparison,
new_comp: Comparison,
comp_attrs: Optional[List[str]] = None
) -> None:
"""
Replace ``old_comp`` with ``new_comp`` in this dataclass, wherever it is.
Looks through ``shared``, then any of the attributes in ``comp_attrs``
Parameters
----------
old_comp : Comparison
Comparison to be replaced
new_comp : Comparison
Comparison to replace ``old_comp`` with
comp_attrs : Optional[List[str]], optional
Attribute names in the dataclass to check, by default ['by_pv'] if
no value is provided
"""
if comp_attrs is None:
comp_attrs = ['by_pv']
super().replace_comparison(old_comp, new_comp, comp_attrs)


@dataclass
class ToolConfiguration(Configuration):
Expand All @@ -123,6 +232,35 @@ class ToolConfiguration(Configuration):
#: Comparisons to be run on *all* identifiers in the `by_attr` dictionary.
shared: List[Comparison] = field(default_factory=list)

def children(self) -> List[Comparison]:
"""Return children of this group, as a tree view might expect"""
return ([comp for comp_list in self.by_attr.values() for comp in comp_list]
+ self.shared)

def replace_comparison(
self,
old_comp: Comparison,
new_comp: Comparison,
comp_attrs: Optional[List[str]] = None
) -> None:
"""
Replace ``old_comp`` with ``new_comp`` in this dataclass, wherever it is.
Looks through ``shared``, then any of the attributes in ``comp_attrs``
Parameters
----------
old_comp : Comparison
Comparison to be replaced
new_comp : Comparison
Comparison to replace ``old_comp`` with
comp_attrs : Optional[List[str]], optional
Attribute names in the dataclass to check, by default ['by_attr'] if
no value is provided
"""
if comp_attrs is None:
comp_attrs = ['by_attr']
super().replace_comparison(old_comp, new_comp, comp_attrs)


AnyConfiguration = Union[
PVConfiguration,
Expand Down Expand Up @@ -154,6 +292,10 @@ def walk_configs(self) -> Generator[AnyConfiguration, None, None]:
yield self.root
yield from self.root.walk_configs()

def children(self) -> List[ConfigurationGroup]:
"""Return children of this group, as a tree view might expect"""
return [self.root]

def get_by_device(self, name: str) -> Generator[DeviceConfiguration, None, None]:
"""Get all configurations that match the device name."""
for config in self.walk_configs():
Expand Down Expand Up @@ -182,7 +324,7 @@ def get_by_tag(self, *tags: str) -> Generator[Configuration, None, None]:

@classmethod
def from_filename(cls, filename: AnyPath) -> ConfigurationFile:
""" Load a configuration file from a file. Dispatches based on file type """
"""Load a configuration file from a file. Dispatches based on file type"""
path = pathlib.Path(filename)
if path.suffix.lower() == '.json':
config = ConfigurationFile.from_json(path)
Expand Down Expand Up @@ -312,6 +454,10 @@ def walk_groups(
yield self.root
yield from self.root.walk_groups()

def children(self) -> List[PreparedGroup]:
"""Return children of this group, as a tree view might expect"""
return [self.root]

async def compare(self) -> Result:
"""Run all comparisons and return a combined result."""
return await self.root.compare()
Expand Down Expand Up @@ -468,7 +614,7 @@ async def compare(self) -> Result:

@property
def result(self) -> Result:
""" Re-compute the combined result and return it """
"""Re-compute the combined result and return it"""
# read results without running steps
results = []
for config in self.comparisons:
Expand Down Expand Up @@ -636,7 +782,7 @@ async def compare(self) -> Result:

@property
def result(self) -> Result:
""" Re-compute the combined result and return it """
"""Re-compute the combined result and return it"""
# read results without running steps
results = []
for config in self.configs:
Expand Down Expand Up @@ -1505,7 +1651,7 @@ def get_result_from_comparison(
async def run_passive_step(
config: Union[PreparedComparison, PreparedConfiguration, PreparedFile]
):
""" Runs a given check and returns the result. """
"""Runs a given check and returns the result."""
# Warn if will run all subcomparisons?
cache_fill_tasks = []
try:
Expand Down
Loading

0 comments on commit 27163da

Please sign in to comment.