mirror of
				https://github.com/home-assistant/supervisor.git
				synced 2025-11-03 16:09:42 +00:00 
			
		
		
		
	Compare commits
	
		
			8 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					c51496ad2f | ||
| 
						 | 
					fbe409337b | ||
| 
						 | 
					443a43cc5b | ||
| 
						 | 
					0e25fad1c0 | ||
| 
						 | 
					488a2327fb | ||
| 
						 | 
					b99ed631c5 | ||
| 
						 | 
					726dd3a8f9 | ||
| 
						 | 
					b94810d044 | 
@@ -1,6 +1,8 @@
 | 
			
		||||
"""Supervisor job manager."""
 | 
			
		||||
from contextvars import ContextVar
 | 
			
		||||
import logging
 | 
			
		||||
from typing import Dict, List, Optional
 | 
			
		||||
from uuid import uuid4
 | 
			
		||||
 | 
			
		||||
from ..coresys import CoreSys, CoreSysAttributes
 | 
			
		||||
from ..utils.common import FileConfiguration
 | 
			
		||||
@@ -8,17 +10,48 @@ from .const import ATTR_IGNORE_CONDITIONS, FILE_CONFIG_JOBS, JobCondition
 | 
			
		||||
from .validate import SCHEMA_JOBS_CONFIG
 | 
			
		||||
 | 
			
		||||
_LOGGER: logging.Logger = logging.getLogger(__package__)
 | 
			
		||||
CONTEXT = ContextVar("id")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SupervisorJob(CoreSysAttributes):
 | 
			
		||||
    """Supervisor running job class."""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, coresys: CoreSys, name: str):
 | 
			
		||||
    def __init__(
 | 
			
		||||
        self,
 | 
			
		||||
        coresys: CoreSys,
 | 
			
		||||
        name: Optional[str] = None,
 | 
			
		||||
        parrent_id: Optional[str] = None,
 | 
			
		||||
    ):
 | 
			
		||||
        """Initialize the JobManager class."""
 | 
			
		||||
        self.coresys: CoreSys = coresys
 | 
			
		||||
        self.name: str = name
 | 
			
		||||
        self._name: Optional[str] = name
 | 
			
		||||
        self._parrent_id: Optional[str] = parrent_id
 | 
			
		||||
        self._progress: int = 0
 | 
			
		||||
        self._stage: Optional[str] = None
 | 
			
		||||
        self._data: Optional[dict] = None
 | 
			
		||||
        self._id = (
 | 
			
		||||
            self.sys_jobs.context.get() if self.parrent_id is None else uuid4().hex
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def id(self) -> str:
 | 
			
		||||
        """Return the ID for the job."""
 | 
			
		||||
        return self._id
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def parrent_id(self) -> Optional[str]:
 | 
			
		||||
        """Return the ID for the parrent job."""
 | 
			
		||||
        return self._parrent_id
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def name(self) -> str:
 | 
			
		||||
        """Return the name for the job."""
 | 
			
		||||
        return self._name or self.id
 | 
			
		||||
 | 
			
		||||
    @name.setter
 | 
			
		||||
    def name(self, value: str) -> None:
 | 
			
		||||
        """Set the name of a job."""
 | 
			
		||||
        self._name = value
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def progress(self) -> int:
 | 
			
		||||
@@ -30,22 +63,33 @@ class SupervisorJob(CoreSysAttributes):
 | 
			
		||||
        """Return the current stage."""
 | 
			
		||||
        return self._stage
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def data(self) -> Optional[str]:
 | 
			
		||||
        """Return additional data for the job."""
 | 
			
		||||
        return self._data
 | 
			
		||||
 | 
			
		||||
    def update(
 | 
			
		||||
        self, progress: Optional[int] = None, stage: Optional[str] = None
 | 
			
		||||
        self,
 | 
			
		||||
        progress: Optional[int] = None,
 | 
			
		||||
        stage: Optional[str] = None,
 | 
			
		||||
        data: Optional[dict] = None,
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """Update the job object."""
 | 
			
		||||
        if progress is not None:
 | 
			
		||||
            if progress >= round(100):
 | 
			
		||||
            if progress >= round(100) and self.parrent_id is None:
 | 
			
		||||
                self.sys_jobs.remove_job(self)
 | 
			
		||||
                return
 | 
			
		||||
            self._progress = round(progress)
 | 
			
		||||
        if stage is not None:
 | 
			
		||||
            self._stage = stage
 | 
			
		||||
        if data is not None:
 | 
			
		||||
            self._data = data
 | 
			
		||||
        _LOGGER.debug(
 | 
			
		||||
            "Job updated; name: %s, progress: %s, stage: %s",
 | 
			
		||||
            'Update: {"name": %s, "progress": %s, "stage": %s, "data": %s}',
 | 
			
		||||
            self.name,
 | 
			
		||||
            self.progress,
 | 
			
		||||
            self.stage,
 | 
			
		||||
            self.data,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -56,6 +100,7 @@ class JobManager(FileConfiguration, CoreSysAttributes):
 | 
			
		||||
        """Initialize the JobManager class."""
 | 
			
		||||
        super().__init__(FILE_CONFIG_JOBS, SCHEMA_JOBS_CONFIG)
 | 
			
		||||
        self.coresys: CoreSys = coresys
 | 
			
		||||
        self.context = CONTEXT
 | 
			
		||||
        self._jobs: Dict[str, SupervisorJob] = {}
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
@@ -68,6 +113,21 @@ class JobManager(FileConfiguration, CoreSysAttributes):
 | 
			
		||||
        """Return a list of ingore condition."""
 | 
			
		||||
        return self._data[ATTR_IGNORE_CONDITIONS]
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def job(self) -> SupervisorJob:
 | 
			
		||||
        """Return the current job based on context ID."""
 | 
			
		||||
        try:
 | 
			
		||||
            self.context.get()
 | 
			
		||||
        except LookupError:
 | 
			
		||||
            self.context.set(uuid4().hex)
 | 
			
		||||
 | 
			
		||||
        context = self.context.get()
 | 
			
		||||
 | 
			
		||||
        if context not in self._jobs:
 | 
			
		||||
            self._jobs[context] = SupervisorJob(self.coresys)
 | 
			
		||||
 | 
			
		||||
        return self._jobs[context]
 | 
			
		||||
 | 
			
		||||
    @ignore_conditions.setter
 | 
			
		||||
    def ignore_conditions(self, value: List[JobCondition]) -> None:
 | 
			
		||||
        """Set a list of ignored condition."""
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,7 @@ class Job(CoreSysAttributes):
 | 
			
		||||
            """Wrap the method."""
 | 
			
		||||
            self._post_init(args)
 | 
			
		||||
 | 
			
		||||
            job = self.sys_jobs.get_job(self.name)
 | 
			
		||||
            job = self.coresys.jobs.job
 | 
			
		||||
 | 
			
		||||
            # Handle condition
 | 
			
		||||
            if self.conditions:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								tests/jobs/test_job_context.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								tests/jobs/test_job_context.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
"""Test the job context vars."""
 | 
			
		||||
 | 
			
		||||
from supervisor.coresys import CoreSys
 | 
			
		||||
from supervisor.jobs.decorator import Job
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def test_job_context(coresys: CoreSys):
 | 
			
		||||
    """Test the job context."""
 | 
			
		||||
 | 
			
		||||
    class TestClass:
 | 
			
		||||
        """Test class."""
 | 
			
		||||
 | 
			
		||||
        def __init__(self, coresys: CoreSys):
 | 
			
		||||
            """Initialize the test class."""
 | 
			
		||||
            self.coresys = coresys
 | 
			
		||||
            self.jobid = str(self.coresys.jobs.job.id)
 | 
			
		||||
 | 
			
		||||
        @Job()
 | 
			
		||||
        async def first(self):
 | 
			
		||||
            """Execute the class method."""
 | 
			
		||||
            await self.second()
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
        @Job()
 | 
			
		||||
        async def second(self):
 | 
			
		||||
            """Execute the class method."""
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
    test = TestClass(coresys)
 | 
			
		||||
    await test.first()
 | 
			
		||||
    assert test.jobid == coresys.jobs.job.id
 | 
			
		||||
    await test.second()
 | 
			
		||||
    assert test.jobid == coresys.jobs.job.id
 | 
			
		||||
		Reference in New Issue
	
	Block a user