forked from platypush/platypush
Refactored system schema dataclasses.
- `percent_field` should be declared on `platypush.schemas.dataclasses` level, since it's not specific to the `system` plugin. - Added a common `SystemBaseSchema` that takes care of calling `_asdict()` if the object is passed as a `psutil` object instead of a dict.
This commit is contained in:
parent
2d618188c8
commit
ebe79ac29a
12 changed files with 61 additions and 41 deletions
|
@ -151,7 +151,7 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
||||||
|
|
||||||
def _cpu_stats(self) -> CpuStats:
|
def _cpu_stats(self) -> CpuStats:
|
||||||
stats = psutil.cpu_stats()
|
stats = psutil.cpu_stats()
|
||||||
return CpuStatsSchema().load(stats._asdict()) # type: ignore
|
return CpuStatsSchema().load(stats) # type: ignore
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def cpu_stats(self) -> CpuStats:
|
def cpu_stats(self) -> CpuStats:
|
||||||
|
@ -164,11 +164,11 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
||||||
|
|
||||||
def _cpu_frequency_avg(self) -> CpuFrequency:
|
def _cpu_frequency_avg(self) -> CpuFrequency:
|
||||||
freq = psutil.cpu_freq(percpu=False)
|
freq = psutil.cpu_freq(percpu=False)
|
||||||
return CpuFrequencySchema().load(freq._asdict()) # type: ignore
|
return CpuFrequencySchema().load(freq) # type: ignore
|
||||||
|
|
||||||
def _cpu_frequency_per_cpu(self) -> List[CpuFrequency]:
|
def _cpu_frequency_per_cpu(self) -> List[CpuFrequency]:
|
||||||
freq = psutil.cpu_freq(percpu=True)
|
freq = psutil.cpu_freq(percpu=True)
|
||||||
return CpuFrequencySchema().load(freq._asdict(), many=True) # type: ignore
|
return CpuFrequencySchema().load(freq, many=True) # type: ignore
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def cpu_frequency(
|
def cpu_frequency(
|
||||||
|
@ -198,9 +198,7 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
||||||
return psutil.getloadavg()
|
return psutil.getloadavg()
|
||||||
|
|
||||||
def _mem_virtual(self) -> MemoryStats:
|
def _mem_virtual(self) -> MemoryStats:
|
||||||
return MemoryStatsSchema().load(
|
return MemoryStatsSchema().load(psutil.virtual_memory()) # type: ignore
|
||||||
psutil.virtual_memory()._asdict()
|
|
||||||
) # type: ignore
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def mem_virtual(self) -> dict:
|
def mem_virtual(self) -> dict:
|
||||||
|
@ -212,7 +210,7 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
||||||
return MemoryStatsSchema().dump(self._mem_virtual()) # type: ignore
|
return MemoryStatsSchema().dump(self._mem_virtual()) # type: ignore
|
||||||
|
|
||||||
def _mem_swap(self) -> SwapStats:
|
def _mem_swap(self) -> SwapStats:
|
||||||
return SwapStatsSchema().load(psutil.swap_memory()._asdict()) # type: ignore
|
return SwapStatsSchema().load(psutil.swap_memory()) # type: ignore
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def mem_swap(self) -> dict:
|
def mem_swap(self) -> dict:
|
||||||
|
@ -226,7 +224,6 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
||||||
def _disk_info(self) -> List[Disk]:
|
def _disk_info(self) -> List[Disk]:
|
||||||
parts = {part.device: part._asdict() for part in psutil.disk_partitions()}
|
parts = {part.device: part._asdict() for part in psutil.disk_partitions()}
|
||||||
basename_parts = {os.path.basename(part): part for part in parts}
|
basename_parts = {os.path.basename(part): part for part in parts}
|
||||||
|
|
||||||
io_stats = {
|
io_stats = {
|
||||||
basename_parts[disk]: stats._asdict()
|
basename_parts[disk]: stats._asdict()
|
||||||
for disk, stats in psutil.disk_io_counters(perdisk=True).items()
|
for disk, stats in psutil.disk_io_counters(perdisk=True).items()
|
||||||
|
@ -234,7 +231,7 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
||||||
}
|
}
|
||||||
|
|
||||||
usage = {
|
usage = {
|
||||||
disk: psutil.disk_usage(info['mountpoint'])._asdict()
|
disk: psutil.disk_usage(info['mountpoint'])._asdict() # type: ignore
|
||||||
for disk, info in parts.items()
|
for disk, info in parts.items()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from dataclasses import field
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
|
@ -6,11 +7,26 @@ from marshmallow import (
|
||||||
Schema,
|
Schema,
|
||||||
fields,
|
fields,
|
||||||
post_dump,
|
post_dump,
|
||||||
|
pre_load,
|
||||||
)
|
)
|
||||||
|
from marshmallow.validate import Range
|
||||||
|
|
||||||
from .. import Date, DateTime
|
from .. import Date, DateTime
|
||||||
|
|
||||||
|
|
||||||
|
def percent_field(**kwargs):
|
||||||
|
"""
|
||||||
|
Field used to model percentage float fields between 0 and 1.
|
||||||
|
"""
|
||||||
|
return field(
|
||||||
|
default_factory=float,
|
||||||
|
metadata={
|
||||||
|
'validate': Range(min=0, max=1),
|
||||||
|
**kwargs,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DataClassSchema(Schema):
|
class DataClassSchema(Schema):
|
||||||
"""
|
"""
|
||||||
Base schema class for data classes that support Marshmallow schemas.
|
Base schema class for data classes that support Marshmallow schemas.
|
||||||
|
@ -45,6 +61,10 @@ class DataClassSchema(Schema):
|
||||||
|
|
||||||
return matching_fields[0]
|
return matching_fields[0]
|
||||||
|
|
||||||
|
@pre_load
|
||||||
|
def pre_load(self, data, **__) -> dict:
|
||||||
|
return data
|
||||||
|
|
||||||
@post_dump
|
@post_dump
|
||||||
def post_dump(self, data: dict, **__) -> dict:
|
def post_dump(self, data: dict, **__) -> dict:
|
||||||
# Use data_key parameters only for load
|
# Use data_key parameters only for load
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
from dataclasses import field
|
from marshmallow import pre_load
|
||||||
|
|
||||||
from marshmallow.validate import Range
|
from platypush.schemas.dataclasses import DataClassSchema
|
||||||
|
|
||||||
|
|
||||||
def percent_field(**kwargs):
|
class SystemBaseSchema(DataClassSchema):
|
||||||
"""
|
"""
|
||||||
Field used to model percentage float fields between 0 and 1.
|
Base schema for system info.
|
||||||
"""
|
"""
|
||||||
return field(
|
|
||||||
default_factory=float,
|
@pre_load
|
||||||
metadata={
|
def pre_load(self, data, **_) -> dict:
|
||||||
'validate': Range(min=0, max=1),
|
if hasattr(data, '_asdict'):
|
||||||
**kwargs,
|
data = data._asdict()
|
||||||
},
|
return data
|
||||||
)
|
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
from marshmallow import pre_load
|
from marshmallow import pre_load
|
||||||
|
|
||||||
from platypush.schemas.dataclasses import DataClassSchema
|
from .._base import SystemBaseSchema
|
||||||
|
|
||||||
|
|
||||||
class ConnectionBaseSchema(DataClassSchema):
|
class ConnectionBaseSchema(SystemBaseSchema):
|
||||||
"""
|
"""
|
||||||
Base schema for connections.
|
Base schema for connections.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@pre_load
|
@pre_load
|
||||||
def pre_load(self, data, **_) -> dict:
|
def pre_load(self, data, **_) -> dict:
|
||||||
if hasattr(data, '_asdict'):
|
data = super().pre_load(data)
|
||||||
data = data._asdict()
|
|
||||||
|
|
||||||
addr_mapping = {
|
addr_mapping = {
|
||||||
'laddr': ('local_address', 'local_port'),
|
'laddr': ('local_address', 'local_port'),
|
||||||
'raddr': ('remote_address', 'remote_port'),
|
'raddr': ('remote_address', 'remote_port'),
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
from marshmallow import pre_load
|
from marshmallow import pre_load
|
||||||
|
|
||||||
from platypush.schemas.dataclasses import DataClassSchema
|
from .._base import SystemBaseSchema
|
||||||
|
|
||||||
|
|
||||||
class CpuInfoBaseSchema(DataClassSchema):
|
class CpuInfoBaseSchema(SystemBaseSchema):
|
||||||
"""
|
"""
|
||||||
Base schema for CPU info.
|
Base schema for CPU info.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@pre_load
|
@pre_load
|
||||||
def pre_load(self, data: dict, **_) -> dict:
|
def pre_load(self, data: dict, **_) -> dict:
|
||||||
|
data = super().pre_load(data)
|
||||||
if data.get('hz_advertised'):
|
if data.get('hz_advertised'):
|
||||||
data['frequency_advertised'] = data.pop('hz_advertised')[0]
|
data['frequency_advertised'] = data.pop('hz_advertised')[0]
|
||||||
if data.get('hz_actual'):
|
if data.get('hz_actual'):
|
||||||
|
@ -18,7 +19,7 @@ class CpuInfoBaseSchema(DataClassSchema):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
class CpuTimesBaseSchema(DataClassSchema):
|
class CpuTimesBaseSchema(SystemBaseSchema):
|
||||||
"""
|
"""
|
||||||
Base schema for CPU times.
|
Base schema for CPU times.
|
||||||
"""
|
"""
|
||||||
|
@ -29,6 +30,7 @@ class CpuTimesBaseSchema(DataClassSchema):
|
||||||
Convert the underlying object to dict and normalize all the percentage
|
Convert the underlying object to dict and normalize all the percentage
|
||||||
values from [0, 100] to [0, 1].
|
values from [0, 100] to [0, 1].
|
||||||
"""
|
"""
|
||||||
|
data = super().pre_load(data)
|
||||||
return {
|
return {
|
||||||
key: value / 100.0
|
key: value / 100.0
|
||||||
for key, value in (
|
for key, value in (
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import List, Optional, Tuple
|
from typing import List, Optional, Tuple
|
||||||
|
|
||||||
from .._base import percent_field
|
from platypush.schemas.dataclasses import percent_field
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
from marshmallow_dataclass import class_schema
|
from marshmallow_dataclass import class_schema
|
||||||
|
|
||||||
from platypush.schemas.dataclasses import DataClassSchema
|
from .._base import SystemBaseSchema
|
||||||
|
|
||||||
from ._base import CpuInfoBaseSchema, CpuTimesBaseSchema
|
from ._base import CpuInfoBaseSchema, CpuTimesBaseSchema
|
||||||
from ._model import CpuFrequency, CpuInfo, CpuStats, CpuTimes
|
from ._model import CpuFrequency, CpuInfo, CpuStats, CpuTimes
|
||||||
|
|
||||||
|
|
||||||
CpuFrequencySchema = class_schema(CpuFrequency, base_schema=DataClassSchema)
|
CpuFrequencySchema = class_schema(CpuFrequency, base_schema=SystemBaseSchema)
|
||||||
CpuInfoSchema = class_schema(CpuInfo, base_schema=CpuInfoBaseSchema)
|
CpuInfoSchema = class_schema(CpuInfo, base_schema=CpuInfoBaseSchema)
|
||||||
CpuTimesSchema = class_schema(CpuTimes, base_schema=CpuTimesBaseSchema)
|
CpuTimesSchema = class_schema(CpuTimes, base_schema=CpuTimesBaseSchema)
|
||||||
CpuStatsSchema = class_schema(CpuStats, base_schema=DataClassSchema)
|
CpuStatsSchema = class_schema(CpuStats, base_schema=SystemBaseSchema)
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
from marshmallow import pre_load
|
from marshmallow import pre_load
|
||||||
|
|
||||||
from platypush.schemas.dataclasses import DataClassSchema
|
from .._base import SystemBaseSchema
|
||||||
|
|
||||||
|
|
||||||
class DiskBaseSchema(DataClassSchema):
|
class DiskBaseSchema(SystemBaseSchema):
|
||||||
"""
|
"""
|
||||||
Base schema for disk stats.
|
Base schema for disk stats.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@pre_load
|
@pre_load
|
||||||
def pre_load(self, data: dict, **_) -> dict:
|
def pre_load(self, data: dict, **_) -> dict:
|
||||||
|
data = super().pre_load(data)
|
||||||
|
|
||||||
# Convert read/write/busy times from milliseconds to seconds
|
# Convert read/write/busy times from milliseconds to seconds
|
||||||
for attr in ['read_time', 'write_time', 'busy_time']:
|
for attr in ['read_time', 'write_time', 'busy_time']:
|
||||||
if data.get(attr) is not None:
|
if data.get(attr) is not None:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from .._base import percent_field
|
from platypush.schemas.dataclasses import percent_field
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
from marshmallow import pre_load
|
from marshmallow import pre_load
|
||||||
|
|
||||||
from platypush.schemas.dataclasses import DataClassSchema
|
from .._base import SystemBaseSchema
|
||||||
|
|
||||||
|
|
||||||
class MemoryStatsBaseSchema(DataClassSchema):
|
class MemoryStatsBaseSchema(SystemBaseSchema):
|
||||||
"""
|
"""
|
||||||
Base schema for memory stats.
|
Base schema for memory stats.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@pre_load
|
@pre_load
|
||||||
def pre_load(self, data: dict, **_) -> dict:
|
def pre_load(self, data: dict, **_) -> dict:
|
||||||
|
data = super().pre_load(data)
|
||||||
|
|
||||||
# Normalize the percentage between 0 and 1
|
# Normalize the percentage between 0 and 1
|
||||||
if data.get('percent') is not None:
|
if data.get('percent') is not None:
|
||||||
data['percent'] /= 100
|
data['percent'] /= 100
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
from .._base import percent_field
|
from platypush.schemas.dataclasses import percent_field
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
from marshmallow import pre_load
|
from marshmallow import pre_load
|
||||||
|
|
||||||
from platypush.schemas.dataclasses import DataClassSchema
|
from .._base import SystemBaseSchema
|
||||||
|
|
||||||
|
|
||||||
class NetworkInterfaceBaseSchema(DataClassSchema):
|
class NetworkInterfaceBaseSchema(SystemBaseSchema):
|
||||||
"""
|
"""
|
||||||
Base schema for network interface stats.
|
Base schema for network interface stats.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@pre_load
|
@pre_load
|
||||||
def pre_load(self, data: dict, **_) -> dict:
|
def pre_load(self, data: dict, **_) -> dict:
|
||||||
|
data = super().pre_load(data)
|
||||||
for in_attr, out_attr in {
|
for in_attr, out_attr in {
|
||||||
'errin': 'errors_in',
|
'errin': 'errors_in',
|
||||||
'errout': 'errors_out',
|
'errout': 'errors_out',
|
||||||
|
|
Loading…
Reference in a new issue