1313from reframe .core .modules import ModulesSystem
1414
1515
16- class ProcessorType (jsonext .JSONSerializable ):
16+ class _ReadOnlyInfo :
17+ __slots__ = ('_info' ,)
18+ _known_attrs = ()
19+
20+ def __init__ (self , info ):
21+ self ._info = info
22+
23+ def __deepcopy__ (self , memo ):
24+ # This is a read-only object; simply return ourself
25+ return self
26+
27+ def __getattr__ (self , name ):
28+ if name in self ._known_attrs :
29+ return self ._info .get (name , None )
30+ else :
31+ raise AttributeError (
32+ f'{ type (self ).__qualname__ !r} object has no attribute { name !r} '
33+ )
34+
35+ def __setattr__ (self , name , value ):
36+ if name in self ._known_attrs :
37+ raise AttributeError (f'attribute { name !r} is not writeable' )
38+ else :
39+ super ().__setattr__ (name , value )
40+
41+
42+ class ProcessorInfo (_ReadOnlyInfo , jsonext .JSONSerializable ):
1743 '''A representation of a processor inside ReFrame.
1844
45+ You can access all the keys of the `processor configuration object
46+ <config_reference.html#processor-info>`__.
47+
1948 .. versionadded:: 3.5.0
2049
2150 .. warning::
22- Users may not create :class:`ProcessorType ` objects directly.
51+ Users may not create :class:`ProcessorInfo ` objects directly.
2352
2453 '''
2554
26- def __init__ (self , processor_info ):
27- self ._arch = None
28- self ._num_cpus = None
29- self ._num_cpus_per_core = None
30- self ._num_cpus_per_socket = None
31- self ._num_sockets = None
32- self ._topology = None
33- self ._info = processor_info
34-
35- if not processor_info :
36- return
37-
38- for key , val in processor_info .items ():
39- setattr (self , f'_{ key } ' , val )
55+ __slots__ = ()
56+ _known_attrs = (
57+ 'arch' , 'num_cpus' , 'num_cpus_per_core' ,
58+ 'num_cpus_per_socket' , 'num_sockets' , 'topology'
59+ )
4060
4161 @property
4262 def info (self ):
@@ -46,62 +66,14 @@ def info(self):
4666 '''
4767 return self ._info
4868
49- @property
50- def arch (self ):
51- '''The microarchitecture of the processor.
52-
53- :type: :class:`str` or :class:`None`
54- '''
55- return self ._arch
56-
57- @property
58- def num_cpus (self ):
59- '''Number of logical CPUs.
60-
61- :type: integral or :class:`None`
62- '''
63- return self ._num_cpus
64-
65- @property
66- def num_cpus_per_core (self ):
67- '''Number of logical CPUs per core.
68-
69- :type: integral or :class:`None`
70- '''
71- return self ._num_cpus_per_core
72-
73- @property
74- def num_cpus_per_socket (self ):
75- '''Number of logical CPUs per socket.
76-
77- :type: integral or :class:`None`
78- '''
79- return self ._num_cpus_per_socket
80-
81- @property
82- def num_sockets (self ):
83- '''Number of sockets.
84-
85- :type: integral or :class:`None`
86- '''
87- return self ._num_sockets
88-
89- @property
90- def topology (self ):
91- '''Processor topology.
92-
93- :type: :class:`Dict[str, obj]` or :class:`None`
94- '''
95- return self ._topology
96-
9769 @property
9870 def num_cores (self ):
9971 '''Total number of cores.
10072
10173 :type: integral or :class:`None`
10274 '''
103- if self ._num_cpus and self ._num_cpus_per_core :
104- return self ._num_cpus // self ._num_cpus_per_core
75+ if self .num_cpus and self .num_cpus_per_core :
76+ return self .num_cpus // self .num_cpus_per_core
10577 else :
10678 return None
10779
@@ -111,8 +83,8 @@ def num_cores_per_socket(self):
11183
11284 :type: integral or :class:`None`
11385 '''
114- if self .num_cores and self ._num_sockets :
115- return self .num_cores // self ._num_sockets
86+ if self .num_cores and self .num_sockets :
87+ return self .num_cores // self .num_sockets
11688 else :
11789 return None
11890
@@ -122,8 +94,8 @@ def num_numa_nodes(self):
12294
12395 :type: integral or :class:`None`
12496 '''
125- if self ._topology and 'numa_nodes' in self ._topology :
126- return len (self ._topology ['numa_nodes' ])
97+ if self .topology and 'numa_nodes' in self .topology :
98+ return len (self .topology ['numa_nodes' ])
12799 else :
128100 return None
129101
@@ -140,37 +112,21 @@ def num_cores_per_numa_node(self):
140112 return None
141113
142114
143- class DeviceType ( jsonext .JSONSerializable ):
115+ class DeviceInfo ( _ReadOnlyInfo , jsonext .JSONSerializable ):
144116 '''A representation of a device inside ReFrame.
145117
118+ You can access all the keys of the `device configuration object
119+ <config_reference.html#device-info>`__.
120+
146121 .. versionadded:: 3.5.0
147122
148123 .. warning::
149- Users may not create :class:`DeviceType ` objects directly.
124+ Users may not create :class:`DeviceInfo ` objects directly.
150125
151126 '''
152127
153- def __init__ (self , device_info ):
154- self ._type = None
155- self ._arch = None
156- self ._num_devices = 1
157- self ._info = device_info
158-
159- if not device_info :
160- return
161-
162- for key , val in device_info .items ():
163- setattr (self , f'_{ key } ' , val )
164-
165- @property
166- def num_devices (self ):
167- '''Number of devices of this type.
168-
169- It will return 1 if it wasn't set in the configuration.
170-
171- :type: integral
172- '''
173- return self ._num_devices
128+ __slots__ = ()
129+ _known_attrs = ('type' , 'arch' )
174130
175131 @property
176132 def info (self ):
@@ -181,20 +137,22 @@ def info(self):
181137 return self ._info
182138
183139 @property
184- def arch (self ):
185- '''The architecture of the device .
140+ def num_devices (self ):
141+ '''Number of devices of this type .
186142
187- :type: :class:`str` or :class:`None`
143+ It will return 1 if it wasn't set in the configuration.
144+
145+ :type: integral
188146 '''
189- return self ._arch
147+ return self ._info . get ( 'num_devices' , 1 )
190148
191149 @property
192150 def device_type (self ):
193151 '''The type of the device.
194152
195153 :type: :class:`str` or :class:`None`
196154 '''
197- return self ._type
155+ return self .type
198156
199157
200158class SystemPartition (jsonext .JSONSerializable ):
@@ -222,8 +180,8 @@ def __init__(self, parent, name, sched_type, launcher_type,
222180 self ._max_jobs = max_jobs
223181 self ._prepare_cmds = prepare_cmds
224182 self ._resources = {r ['name' ]: r ['options' ] for r in resources }
225- self ._processor = ProcessorType (processor )
226- self ._devices = [DeviceType (d ) for d in devices ]
183+ self ._processor = ProcessorInfo (processor )
184+ self ._devices = [DeviceInfo (d ) for d in devices ]
227185 self ._extras = extras
228186
229187 @property
@@ -390,7 +348,7 @@ def processor(self):
390348
391349 .. versionadded:: 3.5.0
392350
393- :type: :class:`reframe.core.systems.ProcessorType `
351+ :type: :class:`reframe.core.systems.ProcessorInfo `
394352 '''
395353 return self ._processor
396354
@@ -400,7 +358,7 @@ def devices(self):
400358
401359 .. versionadded:: 3.5.0
402360
403- :type: :class:`List[reframe.core.systems.DeviceType ]`
361+ :type: :class:`List[reframe.core.systems.DeviceInfo ]`
404362 '''
405363 return self ._devices
406364
0 commit comments