Managing state for control of which methods can be called when? /u/jpgoldberg Python Education

I’m not sure if this sort of question is approprate for this group, but here goes.

The problem (in brief)

Here is a quick overview of the problem I am facing (more details further below). I have a number of classes, lets call the IndEav, IndCpa, IndCca1, and IndCca2 (with more to be added later) that differ (almost) only in which sequences their methods can be called. So I have created a superclass that defines the methods.

Current approach with more detail

I have a solution that I am not fully happy with for managing the allowed sequence of methods for each of the subclasses. For the sake of getting more concrete and keeping things simple, I will just talk about two of the subclasses, IndEav and IndCpa; and I will talk about just two of the methods, encrypt_one() and finalizze(). The only difference between the two classes is that encrypt_one() can only be called once in IndEav but it can be called multiple times in IndCpa.

I have a transition table, unique to each of the subclasses, contains, well, the transition table specificing how state changes when methods are called and which the state in which a method can be called. (I phrased that badly, but the details of that don’t matter.) It is a seprate constant, T_TABLE for each subclass.

What matters is that the current state is an instance variable of the subclass. So when a method is called, state handling needs to know which method was called and also what the current state is. What I have looks something like this (all defined in the super class, Ind.)

“`python class Ind(Generic[K]):

def _handle_state(self, name: Action) -> None: if name not in self._t_table[self._state]: raise StateError(f"{name} not allowed in state {self._state}") self._state = (self._t_table[self._state])[name] def encrypt_one(self, m0: bytes, m1: bytes) -> bytes: whoami = Action.ENCRYPT_ONE self._handle_state(whoami) ... 

“`

(don’t worry about the type parameter K or the Action and State enums.)

My dissatisfiaction with it.

It works and I can live with this if this really is the best way to do this, but the state handling really cries out to be sone wrapper/decorator, instead of me writing the whoami thing in each method.

So what I would like is something like

python def state_decorator(func): def wrapper(): if func.__name__ not in self._t_table[self._state]: raise StateError func() # well, I need to handle arguents to it, etc self._state = (self._t_table[self._state])[func.__name__] return wrapper

The problem is that self._state is an instance variable. So this is not a solution.

Any suggestions on how to do this better? I would prefer to not have to use inspect as that just feels icky to me.

The fuller contexxt

In case I left something out of my description of what I am doing, you can look at the documentation for these classes or the current source.

submitted by /u/jpgoldberg
[link] [comments]

​r/learnpython I’m not sure if this sort of question is approprate for this group, but here goes. The problem (in brief) Here is a quick overview of the problem I am facing (more details further below). I have a number of classes, lets call the IndEav, IndCpa, IndCca1, and IndCca2 (with more to be added later) that differ (almost) only in which sequences their methods can be called. So I have created a superclass that defines the methods. Current approach with more detail I have a solution that I am not fully happy with for managing the allowed sequence of methods for each of the subclasses. For the sake of getting more concrete and keeping things simple, I will just talk about two of the subclasses, IndEav and IndCpa; and I will talk about just two of the methods, encrypt_one() and finalizze(). The only difference between the two classes is that encrypt_one() can only be called once in IndEav but it can be called multiple times in IndCpa. I have a transition table, unique to each of the subclasses, contains, well, the transition table specificing how state changes when methods are called and which the state in which a method can be called. (I phrased that badly, but the details of that don’t matter.) It is a seprate constant, T_TABLE for each subclass. What matters is that the current state is an instance variable of the subclass. So when a method is called, state handling needs to know which method was called and also what the current state is. What I have looks something like this (all defined in the super class, Ind.) “`python class Ind(Generic[K]): def _handle_state(self, name: Action) -> None: if name not in self._t_table[self._state]: raise StateError(f”{name} not allowed in state {self._state}”) self._state = (self._t_table[self._state])[name] def encrypt_one(self, m0: bytes, m1: bytes) -> bytes: whoami = Action.ENCRYPT_ONE self._handle_state(whoami) … “` (don’t worry about the type parameter K or the Action and State enums.) My dissatisfiaction with it. It works and I can live with this if this really is the best way to do this, but the state handling really cries out to be sone wrapper/decorator, instead of me writing the whoami thing in each method. So what I would like is something like python def state_decorator(func): def wrapper(): if func.__name__ not in self._t_table[self._state]: raise StateError func() # well, I need to handle arguents to it, etc self._state = (self._t_table[self._state])[func.__name__] return wrapper The problem is that self._state is an instance variable. So this is not a solution. Any suggestions on how to do this better? I would prefer to not have to use inspect as that just feels icky to me. The fuller contexxt In case I left something out of my description of what I am doing, you can look at the documentation for these classes or the current source. submitted by /u/jpgoldberg [link] [comments] 

I’m not sure if this sort of question is approprate for this group, but here goes.

The problem (in brief)

Here is a quick overview of the problem I am facing (more details further below). I have a number of classes, lets call the IndEav, IndCpa, IndCca1, and IndCca2 (with more to be added later) that differ (almost) only in which sequences their methods can be called. So I have created a superclass that defines the methods.

Current approach with more detail

I have a solution that I am not fully happy with for managing the allowed sequence of methods for each of the subclasses. For the sake of getting more concrete and keeping things simple, I will just talk about two of the subclasses, IndEav and IndCpa; and I will talk about just two of the methods, encrypt_one() and finalizze(). The only difference between the two classes is that encrypt_one() can only be called once in IndEav but it can be called multiple times in IndCpa.

I have a transition table, unique to each of the subclasses, contains, well, the transition table specificing how state changes when methods are called and which the state in which a method can be called. (I phrased that badly, but the details of that don’t matter.) It is a seprate constant, T_TABLE for each subclass.

What matters is that the current state is an instance variable of the subclass. So when a method is called, state handling needs to know which method was called and also what the current state is. What I have looks something like this (all defined in the super class, Ind.)

“`python class Ind(Generic[K]):

def _handle_state(self, name: Action) -> None: if name not in self._t_table[self._state]: raise StateError(f"{name} not allowed in state {self._state}") self._state = (self._t_table[self._state])[name] def encrypt_one(self, m0: bytes, m1: bytes) -> bytes: whoami = Action.ENCRYPT_ONE self._handle_state(whoami) ... 

“`

(don’t worry about the type parameter K or the Action and State enums.)

My dissatisfiaction with it.

It works and I can live with this if this really is the best way to do this, but the state handling really cries out to be sone wrapper/decorator, instead of me writing the whoami thing in each method.

So what I would like is something like

python def state_decorator(func): def wrapper(): if func.__name__ not in self._t_table[self._state]: raise StateError func() # well, I need to handle arguents to it, etc self._state = (self._t_table[self._state])[func.__name__] return wrapper

The problem is that self._state is an instance variable. So this is not a solution.

Any suggestions on how to do this better? I would prefer to not have to use inspect as that just feels icky to me.

The fuller contexxt

In case I left something out of my description of what I am doing, you can look at the documentation for these classes or the current source.

submitted by /u/jpgoldberg
[link] [comments] 

Leave a Reply

Your email address will not be published. Required fields are marked *