GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — Initial FSM PoC by Bibo-Joshi · Pull Request #4669 · python-telegram-bot/python-telegram-bot Conversation
|
| self.admin_id = admin_id | ||
| super().__init__() | ||
|
|
||
| def _get_admin_state(self) -> tuple[State, int]: |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
not sure I like this being private/protected/however the underscore is called
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
So far I see no reason why someone should be allowed to all USM(…).get_admin_state … then again this is only an example, so I don't care :D
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| super().__init__() | ||
|
|
||
| def _get_admin_state(self) -> tuple[State, int]: | ||
| return self._states[self.admin_id] |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
That should not be the private function right
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| def _get_admin_state(self) -> tuple[State, int]: | ||
| return self._states[self.admin_id] | ||
|
|
||
| def get_state_info(self, update: object) -> StateInfo[Optional[int]]: |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
The type hint here is linked to the FSM class type hint above right? I can't have one be a string one be an integer.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Correct, the type variable specifying the type of keys you use.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| if not state_handlers[group]: | ||
| del state_handlers[group] |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Does this remove the group if its empty? Can we comment it
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
yes, that's basically the same as state_handlers.pop(group, None), I think. It will call state_handlers.__del__(group). IMHO this is basic python syntax 😬
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
| from telegram.ext import JobQueue | ||
|
|
||
| _KT = TypeVar("_KT", bound=Hashable) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Im back with my thinking about private stuff. Why do we private it here, not in other files; should we. Hm.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I feel you :D if machine was a public module like telegram.constants, it would have to be protected IMO. Since it's not and we expose the relevant elements only via telegram.ext, it's not so important. Making it clearer what the content exposed by this module is still doesn't hurt.
If you want to go deeper into the rabbit hole: https://discuss.python.org/t/add-the-export-keyword-to-python/28444/6
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| application.fsm = UserSupportMachine(admin_id=123456) | ||
| application.fsm.set_job_queue(application.job_queue) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
these should be part of the builder and the second one set by default imo
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
yes, absolutely. #PoC 👼
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| return f"FSM_Job_{'_'.join(str(hash(k)) for k in keys)}" | ||
|
|
||
| def set_job_queue(self, job_queue: "JobQueue") -> None: | ||
| self.__job_queue = weakref.ref(job_queue) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Why weakref wont it/the user experience break if the supplied job queue gets destroyed
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
There is job_queue.application. that's also weakref b/c we have a cyclic reference: application is application.job_queue.application. Now we also have application is application.fsm.job_queue.application. I'm not 100% sure if this is strictly necessary, but it seemed safer to me 🤔 I can at very least add a comment.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| if raise_exception: | ||
| raise RuntimeError("JobQueue was garbage collected") |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
ha here see. why.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| def __init__(self, uid: Optional[str] = None): | ||
| effective_uid = uid or uuid4().hex | ||
| if effective_uid in self.__knows_uids: | ||
| raise ValueError(f"Duplicate UID: {effective_uid} already registered") |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
is the error saying UID correct? I would understand the optional type hint to be anything hashable
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I don't get you. What do you think is wrong? the phrasing of the error message?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
|
|
||
| class State(abc.ABC): | ||
| __knows_uids: ClassVar[set[str]] = set() |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Wait I must really misunderstand smth, how does this work across states
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
uh … that's how class variables work? :D In the init self.__knows_uids is basically the same as State.__knows_uids …
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
A thought I had: Since this is such a huge change for something so integral to our project, should we provide a beta version/implementation after we are satisfied with the status and announce it to get people to try it out and provide feedback before we make a first release? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
That is indeed a very good idea 👍
that way we wouldn't have to do any additional actual beta releases. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I dont get the first point, what do you mean with not using new states. In conjunction with ConvHandler? I thought this is supposed to fully replace it. In that case I would like a big announcement at least (maybe also in readme or so). We might not really need an extra release now that I think of it, just make a big fuss about it before calling it stable and doing the deprecation error warning. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Yes, this is supposed to replace CH. But, since this is acting on a different level than handlers, the
👍 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Ah yes you mean in the transition period alright. Okay so lets do a release when we are happy and announce that its there and see if we get feedback, and then do a deprecation later. Perfect. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
I'm not sure if this is the right place to mention this but: Is there any plans or ongoing work for a declarative but an extensible (e.g. with hooks) FSM syntax? like I have a fairly complex stateful bot in PTB (and ConversationHandler) and have written a very rudimentary function that parses a generically defined (but limited) transition table (declarative) and performs the transitions given the inputs and also produces some (a set of) outputs or actions. I did it for a subset of states (relatively simple logic) in my application, because in the current PTB framework adding states and extending the FSM logic is somewhat a pain. Code re-usability was another consideration (e.g. several states might want to transition to a very specific state and so using a common transition function or hook for setting up the UI and then entering that state is useful for code reuse). A declarative approach to complex FSM logic specification would both accelerate and simplify development, IMHO. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.