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

fix for #242 - Initial framework for HID Cerberus integration #244

Open
wants to merge 71 commits into
base: develop
Choose a base branch
from

Conversation

Tahvohck
Copy link

Throwing this up as a draft as I've got the main things mentioned in #242 already coded in. It's not complete but the framework is there.

pycodestyle config will most likely be removed later - I committed it out of habit and never removed it.

@Tahvohck Tahvohck marked this pull request as ready for review September 18, 2019 07:26
@Tahvohck
Copy link
Author

I had to force-push this because it had some work-related email information that I needed to delete. As far as I can see, this successfully reset the author information on all commits without losing date info, basic history, etc.

@WhiteMagic
Copy link
Owner

I'll look over it tonight and see if I can give some feedback. The registry based interface shouldn't be really complicated or need much changing since if we can just use that as the API reference and the HidCerberus interface can mimick it well enough we can just model based off the registry based one without needing to change much or anything.

@Tahvohck
Copy link
Author

I've actually already written up an interface class, now it's just a matter of making sure that the registry provider responds as expected to it. I was planning on doing some level of statefulness for the interface class actually, things like what devices are hidden already and whether or not the program has whitelisted itself.

Decorator now runs the function, does error handling,
uses functools.wraps to maintain help info, falls back
on EAFP principles, and passes the return value to the
interface class function.
This is largely in preparation for the implementation of the Registry provider
but will also future-proof the Cerberus provider. Partial implentation of this
step in the Registry provider (checks if program is run in admin mode)
wraps() needs to be passed the function that's getting wrapped.
Cerberus provider get_device_list didn't have a return value
HID strings now supported:
HID\VID_????&PID_????
HID\VID_????&PID_????&MI_??
@WhiteMagic
Copy link
Owner

I don't really think adding statefulness is needed and likely will cause some grief. The state should be retrievable via the interface to HidGuardian. That way there is no need to make sure everything is kept in sync, as there is nothing preventing people whitelisting devices via means other then Gremlin. So my feeling is that adding this would not really give us anything we couldn't do already and would require a lot of careful synchronization and checking code.

Basically the same as the code in hid_guardian but compressed and using with
statements (turns out winreg keys support that!)
@Tahvohck
Copy link
Author

Tahvohck commented Oct 2, 2019

Good point. All I added on that level so far was the backing data structures (AKA two empty lists), so that's simple enough to not add.

@WhiteMagic
Copy link
Owner

I finally got some time to look over the changes. Overall I think it seems sensible though I probably would change the design a bit. The way it currently works is a bit opaque, due to the decorator class function lookup magic. The same behavior could be achieved using simple inheritance. Something along the following lines:

import abs

class HidGuardianAbstract(metaclass=abc.ABCMeta:
    def __init__(self,):
        pass
    
    @abc.abstracmethod
    def add_device(self, identifier):
        pass

class HidGuardianRegistry(HidGuardianAbstract):
    def __init__(self):
        super().__init__()
        # Run initialization
    
    def add_device(self, identifier):
        # Registry implementation
        pass

class HidGuardianCerberus(HidGuardianAbstract):
    def __init__(self):
        super().__init__()
        # Run initialization
    
    def add_device(self, identifier):
        # HidCerberus implementation
        pass

def hg_interface():
    # Determine which interface to use
    has_registry = False
    has_cerberus = True
    if has_registry:
        return HidGuardianRegistry()
    elif has_cerberus:
        return HidGuardianCerberus()
    else:
        # Handle case of no interface
        return None

While this undoes the whole classmethod thing and technically there is no need to have methods with state, I think this makes it a bit clearer for anyone in the future looking over this. In Gremlin, there are only two places where the interface to HidGuardian is used. The main script which whitelists the instance of Gremlin and then the options UI dialog, which adds and removes devices from HidGuardian. As none of the places the interfaces are used in has high call rates, the overhead of creating or recreating the object isn't going to matter much.

Another minor note I try to adhere to PEP8 naming conventions, which is CamelCase for classes and names_width_underscores for variables and functions and methods.

@Tahvohck
Copy link
Author

Tahvohck commented Oct 17, 2019

I'll poke at this when I get a chance, Been kinda busy this past week. I'll remove the decorator class, which should make it far less opaque, and actually will keep the classmethod abstraction (it's really just a difference in how it's called). Edit: Actually, I'll look deeper into the abstract class thing. If this is a way that python has to enforce inheritance that's something I didn't realize was present in python.

As far as Pep8, I'll go in and fix all of that, I'm surprised my PEP8 linter (pycodestyle) didn't catch that.

@WhiteMagic
Copy link
Owner

Yeah no worries take your time. And yeah the abc module allows Python to enforce abstract interfaces that need to be implemented by derived classes.

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

Successfully merging this pull request may close these issues.

3 participants