Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split responsibilities to Mode, Method, activate() and activate_using() (v. 0.8.0) #69

Closed
7 tasks done
fohrloop opened this issue Nov 4, 2023 · 3 comments
Closed
7 tasks done
Assignees
Milestone

Comments

@fohrloop
Copy link
Owner

fohrloop commented Nov 4, 2023

This is basically a ticket to myself, and is continuation of work in the PR #51, which left the main branch in an unfinished and bit messy state.

Modes

  • Clean up code for Mode. The purpose of Mode is to simply provide the main API and context manager for the user. Everything else should be handled elsewhere. (PR #70)
  • Remove creation of DBusAdapter instances from Modes. Pass the DBusAdapter class to a ModeActivationManager -> ModeActivator -> Caller and create an instance of the adapter there (in separate thread) (PR #70)
  • Remove prioritization of methods from Modes. Prioritization should be done in ModeActivator. (PR #70)
  • Implement Mode.__exit__ and add ModeExit exception which can be used to exit the mode with statement block. (PR #72)
  • The callables for Modes like keep.running and keep.presenting should be functions which return instances of Modes. Calling keep.running() should call return a fresh instance of Mode (for supporting running wakepy in multiple threads) (PR #71)
  • Create tests for Mode (PR #71)

Deprecated

work done on this ticket but not relevant anymore

  • Create a ModeActivationManager class. (PR #76)
    using the queues.
@fohrloop fohrloop added this to the wakepy 0.8.0 milestone Nov 4, 2023
@fohrloop fohrloop self-assigned this Nov 4, 2023
@fohrloop fohrloop changed the title Split responsibilities to Mode, ModeActivationManager and ModeActivator Split responsibilities to Mode, ModeActivationManager and ModeActivator (v. 0.8.0) Nov 5, 2023
@fohrloop
Copy link
Owner Author

fohrloop commented Nov 9, 2023

I wrote some initial ideas in #75 about renaming ModeActivator to ModeActivationProcess and splitting the responsibilities in three: MethodSelector, MethodPrioritizer and ModeActivator.

I could try to implement the classes next. Modifying the list above to reflect the changes.

@fohrloop fohrloop changed the title Split responsibilities to Mode, ModeActivationManager and ModeActivator (v. 0.8.0) Split responsibilities to Mode, Method, activate() and activate_using() (v. 0.8.0) Dec 19, 2023
@fohrloop
Copy link
Owner Author

fohrloop commented Dec 19, 2023

As mentioned in #100, wakepy Mode activation process will be a blocking operation. This makes it possible to do everything, except heartbeat, in the main thread, which in turn makes things a lot easier. I've already written some documentation to the 0.8.0dev ("main") docs about how this all will work. The plan is roughly:

  • Have Mode class as the context manager
  • Have activate(methods, ...) function which can activate a "mode" (list of method classes)
  • Have activate_using(method, ...) function which may activate a "mode" using a single Method.
  • Have Method class for sole purpose of defining subclasses Method
  • Have a Heartbeat class which runs a heartbeat in separate thread.

Rough implementation of activate():

def activate(methods: list[MethodCls], ...) -> tuple[ActivationResult, HeartBeat|None]:
    prioritized_methods = prioritize_methods(methods)
    result = ActivationResult()

    for method in prioritized_methods:
        methodresult, heartbeat = activate_using(method, ...)
        result.add(methodresult)
        if result.success:
            break
    return result, heartbeat
  • The idea behind activate() function is that you don't need to have Mode instance in order to activate a "mode" defined by a list of Methods.

Rough implementation of activate_using() (pseudocode):

def activate_using(methodcls: MethodCls, ...) -> tuple[MethodUsageResult, HeartBeat|None]:
    method = methodcls()
    if check_platform_support(method) is False:
         return MethodUsageResult(failure_stage=PLATFORM_SUPPORT), None
    if check_requirements(method) is False:
        return MethodUsageResult(failure_stage=REQUIREMENTS), None
    entered = try_enter_mode(method)
    heartbeat_started = try_heartbeat(method)
    if not entered or not heartbeat_started:
        return MethodUsageResult(failure_stage=ACTIVATION), None
    if heartbeat_started:
        heartbeat = Heartbeat(method)
        heartbeat.start()
    return MethodUsageResult(), heartbeat
  • The idea behind the activate_using() function is that it should be possible to use a single Method without Modes etc. If there are no other uses, at least it makes the code a bit more modular.
  • DbusAdapters etc. should be initialized only once and passed to activate_using, which should accept classes and instances.

New Tasks

@fohrloop
Copy link
Owner Author

The rest of the work on this ticket has been split into multiple tickets. This one is done and can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant