gilbert189's avatar

@gilbert189
Beta tester

i'm gilbert_given_189 on Scratch.
Wall

Let’s play a game of “Fortunately, Unfortunately“. Respond the previous post (the first comment below this post) by replying this post (not the previous post!)

I’ll start with: “I found this website.“

14 1 93

Why save if inflation would make them worthless anyway

—my UI/UX lecturer

1 0 1

I can’t sleep (=

5 0 0

I don’t think I’m using social media correctly

5 0 3

Why doesn’t tbgclient work like scratchattach? Why the forum classes?

scratchattach (and others like it) allows the session to create the object it needs, passing itself to the object for the created object to refer on later.

import scratchattach as sa
session = sa.login("username", "password")
topic = session.connect_topic(603418)

By doing so, objects will have to store the session somewhere, and that doesn’t seem right to me.

Forum classes are supposed to be abstractions of the elements in the TBGs. Message is supposed to represent messages, User represents users, etc. Sessions have no place in these classes, so obviously they don’t store them. This is made more serious by the fact that all the classes are dataclasses as well. [1]

For the sake of the argument, say that the classes do store the creator session. (Incidentally, this is the approach that the older tbgclient-legacy uses.) There are problems with this approach:

  • When an object is created, they have to specify the session to use. From experience of developing tbgclient-legacy, this act turned into a massive, unnecessary chore, especially since the objects have to pass in what would most likely be the same, single session for this one script.

  • An object storing something opaquely could bring unexpected behaviour. What should be done with this session could be done with another session, just because the other is their creator. I know DIs are one useful pattern, but for a loose dependency like this, it’s only a burden that’s asking for trouble. Explicit is better than implicit.

  • Serialization could be a problem. If a post has to be stored and retrieved, the session is lost along the way (since it has no reason to be stored) and has to be provided. It would be easier and nicer if the class reflects this limitation. After all, this was part of a mass forum scraper, and that fact hasn’t changed until now.

To solve this issue, I implemented the UsesSession mixin. Anything that needs a session could retrieve the current one by the implemented session property. This also means the process of getting the current session is delegated to this class. Creating objects becomes much easier. As for the sessions, they are stored in a shared session context, so other objects (that bases UsesSession) don’t have to store them. This also makes serialization easier.

This solution works, but not completely watertight. Having a global state is generally a big no-no for various reasons (if you read this, you should already know that). tbgclient does its best to alleviate this, by distinguishing context by the thread, event loop, and process; and including a self-destructing check if something may have tampered the stack. [2]

On a more serious note, this means the way of updating and submitting objects is completely different than libraries like scratchattach. Instead of doing it all from the session, you have to make the object first, then call the object’s function. An equivalent tbgclient code of the scratchattach example above would look something like this:

from tbgclient import Topic, Session
session = Session().login("username", "password")
with session:
    topic = Topic(tid=170).update()

If this really bothers you, there are convenience functions in the tbgclient module. These functions could be much more straightforward to read for programmers familiar with scratchattach and alike.

[1] You could annotate the dataclass so the session attribute is an InitVar, but that doesn’t eradicate the problem that the object still stores the session somewhere.

[2] If you see an error related to the context system, either something is abusing it, or there’s a bug in my code. In either case, do tell!

I had no idea where to post this for feedback so here would have to do

1 0 0

as much as I want to keep this message count…

…I have to open it to check if I got alerted by saying “wicked”

rip =’(

edit: I didn’t (get alerted)

2 0 3

we need tgoradashw but it’s shinies

I just enabled screen lock in Firefox Mobile and I CAN’T DISABLE IT AAAAAAAAA

EVEN REMOVING MY PHONE LOCK DOESN’T REMOVE THIS DUMB FEATURE

2 0 0

Unicode added Covemounty in 2024

𜱍

My Mii dropped a domino before he even said ready wth

i declare victory

hello today I’m fighting with DPIs again

2 1 1

hello today I’m fighting with DPIs again

2 1 1

my phone works again, but it’s still not happy about it

at least I can renew my domain now

my phone has developed a mild case of spicy pillow syndrome

I CAN’T RECHARGE MY DOMAIN WITHOUT MY PHONE AAAAAAAH PANIC PANIC PANIC

2 0 0

I heart regular expressions

pattern = re.compile(r"""
# Super Duper Hyper Mega Email Address Regex Pattern
# Only matches valid email "mailboxes"
# as specified in RFC 5321 (section 4.1.2)
(   # Local part of the address.
    # Dotted string 
    [A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+
    (?:\.
        [A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+
    )*
    |
    # Quoted string
    \"(?:[ -!#-\[\]-~]|\\[ -~])\"
)
@
(   # Domain of the address.
    # Domain name
    [A-Za-z-0-9]
    (?:[A-Za-z-0-9-]*[A-Za-z-0-9])?
    (?:\.
        [A-Za-z-0-9]
        (?:[A-Za-z-0-9-]*[A-Za-z-0-9])?
    )*
    |
    # Address literals
    \[(?:
        # IPv4 address
        \d{1,3}
        (?:\.
            \d{1,3}
        ){3}
        |
        IPv6:(?:
            # In full
            [0-9A-Fa-f]{1,4}
            (?::
                [0-9A-Fa-f]{1,4}
            ){7}
            |
            # Shortened
            # Section 4.1.3 noted that the terms on the left and the right 
            # must be no more than 6, so the main pattern is repeated
            # over and over again (since regex doesn't do math)
            (?:
                # 0 on the left, at least 6 on the right
                ::
                (?:
                    [0-9A-Fa-f]{1,4}
                    (?::
                        [0-9A-Fa-f]{1,4}
                    ){0,5}
                )?
                |
                # 1 on the left, at least 5 on the right
                [0-9A-Fa-f]{1,4}
                ::
                (?:
                    [0-9A-Fa-f]{1,4}
                    (?::
                        [0-9A-Fa-f]{1,4}
                    ){0,2}
                )?
                |
                # 2 on the left, at least 4 on the right
                [0-9A-Fa-f]{1,4}
                (?::
                    [0-9A-Fa-f]{1,4}
                )
                ::
                (?:
                    [0-9A-Fa-f]{1,4}
                    (?::
                        [0-9A-Fa-f]{1,4}
                    ){0,3}
                )?
                |
                # 3 on the left, at least 3 on the right
                [0-9A-Fa-f]{1,4}
                (?::
                    [0-9A-Fa-f]{1,4}
                ){2}
                ::
                (?:
                    [0-9A-Fa-f]{1,4}
                    (?::
                        [0-9A-Fa-f]{1,4}
                    ){0,2}
                )?
                |
                # 4 on the left, at least 2 on the right
                [0-9A-Fa-f]{1,4}
                (?::
                    [0-9A-Fa-f]{1,4}
                ){3}
                ::
                (?:
                    [0-9A-Fa-f]{1,4}
                    (?::
                        [0-9A-Fa-f]{1,4}
                    ){0,1}
                )?
                |
                # 5 on the left, at least 1 on the right
                [0-9A-Fa-f]{1,4}
                (?::
                    [0-9A-Fa-f]{1,4}
                ){4}
                ::
                (?:
                    [0-9A-Fa-f]{1,4}
                )?
                # 6 on the left, none on the right
                [0-9A-Fa-f]{1,4}
                (?::
                    [0-9A-Fa-f]{1,4}
                ){4}
                ::
            )
            |
            # In full (with IPv4 address)
            [0-9A-Fa-f]{1,4}
            (?::
                [0-9A-Fa-f]{1,4}
            ){5}
            :\d{1,3}
            (?:\.
                \d{1,3}
            ){3}
            |
            # Shortened (with IPv4 address)
            # See the previous comment for explanation of the repetition.
            (?:
                # 0 on the left, at least 4 on the right
                ::
                (?:
                    [0-9A-Fa-f]{1,4}
                    (?::
                        [0-9A-Fa-f]{1,4}
                    ){0,3}
                    :
                )?
                \d{1,3}
                (?:\.
                    \d{1,3}
                ){3}
                |
                # 1 on the left, at least 3 on the right
                [0-9A-Fa-f]{1,4}
                ::
                (?:
                    [0-9A-Fa-f]{1,4}
                    (?::
                        [0-9A-Fa-f]{1,4}
                    ){0,2}
                    :
                )?
                \d{1,3}
                (?:\.
                    \d{1,3}
                ){3}
                |
                # 2 on the left, at least 2 on the right
                [0-9A-Fa-f]{1,4}
                (?::
                    [0-9A-Fa-f]{1,4}
                )
                ::
                (?:
                    [0-9A-Fa-f]{1,4}
                    (?::
                        [0-9A-Fa-f]{1,4}
                    ){0,1}
                    :
                )?
                \d{1,3}
                (?:\.
                    \d{1,3}
                ){3}
                |
                # 3 on the left, at least 1 on the right
                [0-9A-Fa-f]{1,4}
                (?::
                    [0-9A-Fa-f]{1,4}
                ){2}
                ::
                (?:
                    [0-9A-Fa-f]{1,4}
                    :
                )?
                \d{1,3}
                (?:\.
                    \d{1,3}
                ){3}
                |
                # 4 on the left, none on the right
                [0-9A-Fa-f]{1,4}
                (?::
                    [0-9A-Fa-f]{1,4}
                ){3}
                ::
                \d{1,3}
                (?:\.
                    \d{1,3}
                ){3}
            )
        )
        |
        # General address
        # Verifying the tag should be done separately
        [A-Za-z-0-9-]*[A-Za-z-0-9]
        :([!-Z^-~])+
    )\]
)
""", re.X)