• Re: PSA: A python script to clone your phone exactly, over Wi-Fi or USB

    From Lawrence D?Oliveiro@3:633/10 to All on Thu Aug 20 07:46:26 2026
    On Wed, 19 Aug 2026 22:33:27 -0800, Maria Sophia wrote:

    # Prerequisite: "nova.db" SQL database file created using the
    # last-known-good-version of the Tesla Coil Nova Launcher 7.0.57
    # <https://mobile.softpedia.com/apk/nova-launcher/7.0.57/>

    Why not provide your own commands for initializing a new database
    if it doesn?t already exist? Save the user some work.

    If you want to see an example of how it?s done, have look at the
    ?project-tags? script (yes, it?s a Python script) here <https://gitlab.com/ldo/emacs-prefs>.

    cursor.execute(
    "SELECT DISTINCT screen FROM favorites WHERE container = -100 ORDER BY screen ASC;"
    )
    screens = cursor.fetchall()

    You do this sequence of execute/fetch calls 4 times in your script. I
    see you reuse the same cursor to save some extra setup work each time.
    You can make things a little less fiddly with the help of this routine
    (also to be found in the above script):

    def db_iter(conn, cmd, mapfn = lambda x : x) :
    "executes cmd on a new cursor from connection conn and yields the results in turn."
    for item in conn.cursor().execute(cmd) :
    yield mapfn(item)
    #end for
    #end db_iter

    With this routine, the above sequence becomes

    screens = list(db_iter \
    (
    conn,
    "SELECT DISTINCT screen FROM favorites WHERE container = -100 ORDER BY screen ASC"
    ))

    for (screen_num,) in screens:

    or better still, put the lookup directly into the loop expression:

    for screen_num in db_iter \
    (
    conn,
    "SELECT DISTINCT screen FROM favorites WHERE container = -100 ORDER BY screen ASC",
    mapfn = lambda x : x[0]
    ) :

    cursor.execute(
    "SELECT _id, title FROM favorites WHERE container = -100 AND screen = ?"
    " AND intent IS NULL AND title IS NOT NULL AND TRIM(title) != '';",
    (screen_num,),
    )
    folders = cursor.fetchall()
    for folder_id, folder_name in folders:

    Again, this can be simplified to

    for folder_id, folder_name in db_iter \
    (
    conn,
    "SELECT _id, title FROM favorites WHERE container = -100 AND screen = %d"
    " AND intent IS NULL AND title IS NOT NULL AND TRIM(title) != '';"
    %
    screen_num
    ) :

    and so on.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lawrence D?Oliveiro@3:633/10 to All on Thu Aug 20 22:57:43 2026
    On Thu, 20 Aug 2026 08:32:58 -0800, Maria Sophia wrote:

    If I were to adapt your db_iter concept while keeping parameterized
    queries safe, I'd probably modify it to accept a parameters tuple
    like this:

    Python
    def db_iter(conn, cmd, params=(), mapfn=lambda x: x):
    """Executes cmd with parameters and yields mapped results."""
    for item in conn.cursor().execute(cmd, params):
    yield mapfn(item)

    Yes, fair enough. I prefer to use APSW rather than the SQLite binding
    in the standard library; that seems nicer in some ways, providing more flexibility in placeholders for parameter substitution <https://rogerbinns.github.io/apsw/example.html#why-you-use-bindings-to-provide-values>.

    I tend to fall out of the habit of using placeholder mechanisms,
    because they don?t cope with more advanced cases.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lawrence D?Oliveiro@3:633/10 to All on Fri Aug 21 07:04:20 2026
    On Fri, 21 Aug 2026 04:20:33 -0000 (UTC), Chris wrote:

    Especially python where the lack of whitespace consistency completely
    breaks the code.

    However:

    def netstring_encode(s, as_str = False) :
    "encodes a string or bytes object as a netstring. Returns the encoded" \
    " format as a string or bytes object, depending on as_str."
    if isinstance(s, str) :
    sb = s.encode()
    elif isinstance(s, (bytes, bytearray)) :
    sb = s
    else :
    raise TypeError("input value should be str or bytes")
    if len(sb) > MAX_NETSTRING_LEN :
    raise ValueError("netstring length of %d exceeds %d bytes" % (len(sb), MAX_NETSTRING_LEN))
    result = b"%d:%s," % (len(sb), sb)
    if as_str :
    result = result.decode()
    return \
    result

    Hopeless gibberish. But:

    def netstring_encode(s, as_str = False) :
    "encodes a string or bytes object as a netstring. Returns the encoded" \
    " format as a string or bytes object, depending on as_str."
    if isinstance(s, str) :
    sb = s.encode()
    elif isinstance(s, (bytes, bytearray)) :
    sb = s
    else :
    raise TypeError("input value should be str or bytes")
    #end if
    if len(sb) > MAX_NETSTRING_LEN :
    raise ValueError("netstring length of %d exceeds %d bytes" % (len(sb), MAX_NETSTRING_LEN))
    #end if
    result = b"%d:%s," % (len(sb), sb)
    if as_str :
    result = result.decode()
    #end if
    return \
    result
    #end netstring_encode

    Some chance of restoring meaning.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lawrence D?Oliveiro@3:633/10 to All on Fri Aug 21 22:32:25 2026
    On Wed, 19 Aug 2026 22:33:27 -0800, Maria Sophia wrote:

    CUSTOM_ADB_PATH = r"C:\app\editor\android\scrcpy\adb.exe"

    By the way, I think Python lets you write ?/? instead of ?\?, which
    saves trouble with r-strings.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Fri Aug 21 19:11:29 2026
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Wed, 19 Aug 2026 22:33:27 -0800, Maria Sophia wrote:
    CUSTOM_ADB_PATH = r"C:\app\editor\android\scrcpy\adb.exe"

    By the way, I think Python lets you write ?/? instead of ?\?, which
    saves trouble with r-strings.

    File paths are interpreted by the OS. If an open() call succeeds
    with "C:/app/editor/android/scrcpy/adb.exe", I don't think that has
    anything to do with Python (other than Python not going out of its
    way to make it fail).

    See also the pathlib module.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)