-
Notifications
You must be signed in to change notification settings - Fork 47
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
base: develop
Are you sure you want to change the base?
Conversation
69edec6
to
99a3a12
Compare
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. |
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. |
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_??
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!)
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. |
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. |
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. |
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. |
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.