×

pfst 0.3.0: High-level Python source manipulation by Pristine_Cat in Python

[–]Pristine_Cat[S] 2 points3 points  (0 children)

I'm not exactly an expert with LibCST so maybe the function can be optimized further, but here is an example with minimal code for both LibCST and pfst to add a keyword argument with a comment to all logger.info() calls which don't already have the specific keyword argument correlation_id.

LibCST function:

from libcst import *
from libcst.matchers import *

def inject_logging_metadata(src: str) -> str:
    module = parse_module(src)

    new_arg = (parse_module('f(correlation_id=CID  # blah\n)')
        .body[0].body[0].value.args[0])

    class AddArg(CSTTransformer):
        def leave_Call(self, _, node):
            if matches(node.func, Attribute(Name('logger'), Name('info'))):
                if not any(a.keyword and a.keyword.value == 'correlation_id'
                        for a in node.args):
                    return node.with_changes(args=[*node.args, new_arg])
            return node

    module = module.visit(AddArg())

    return module.code

pfst function:

from fst import *
from fst.match import *

def inject_logging_metadata(src: str) -> str:
    module = FST(src)

    for m in module.search(MCall(
        func=MAttribute('logger', 'info'),
        keywords=MNOT([MQSTAR, Mkeyword('correlation_id'), MQSTAR]),
    )):
        m.matched.append('correlation_id=CID  # blah', trivia=())

    return module.src

Input source:

logger.info('Hello world...')  # hey
logger.info('Already have id', correlation_id=other_cid)  # ho
logger.info()  # its off to work we go

class cls:
    def method(self, thing, extra):
        (logger) . info(  # start
            f'a {thing}',  # this is fine
            extra=extra,  # also this
        )  # end

LibCST output:

logger.info('Hello world...', correlation_id=CID  # blah
)  # hey
logger.info('Already have id', correlation_id=other_cid)  # ho
logger.info(correlation_id=CID  # blah
)  # its off to work we go

class cls:
    def method(self, thing, extra):
        (logger) . info(  # start
            f'a {thing}',  # this is fine
            extra=extra,  # also this
        correlation_id=CID  # blah
        )  # end

pfst output:

logger.info('Hello world...', correlation_id=CID  # blah
)  # hey
logger.info('Already have id', correlation_id=other_cid)  # ho
logger.info(correlation_id=CID  # blah
)  # its off to work we go

class cls:
    def method(self, thing, extra):
        (logger) . info(  # start
            f'a {thing}',  # this is fine
            extra=extra,  # also this
            correlation_id=CID  # blah
        )  # end

If you want LibCST to align the argument its significantly more code, but that can be left for a formatter after the file processing.

pfst: High-level Python AST/CST manipulation that preserves formatting by Pristine_Cat in Python

[–]Pristine_Cat[S] 0 points1 point  (0 children)

Python's builtin, but have special cases for each version quirks for py 3.10 to 3.14.

pfst: High-level Python AST/CST manipulation that preserves formatting by Pristine_Cat in Python

[–]Pristine_Cat[S] 0 points1 point  (0 children)

For a refactor its fine if you go through the files once making the edits, I've actually used its this way on its own code at a couple of points. Its if you make multiple passes making many small changes each time that you may start to feel its not so fast.

As for comparisons with others, makes sense, will do so at some point in next doc cycle.

[deleted by user] by [deleted] in Python

[–]Pristine_Cat 0 points1 point  (0 children)

To give an idea of the API, here is a quick script to inject a correlation_id into logger.info() calls.

from fst import *  # pip install pfst, import fst

module = FST(src)

for call in module.walk(Call):
    if (call.func.is_Attribute and call.func.attr == 'info'
        and call.func.value.is_Name and call.func.value.id == 'logger'
        and not any(kw.arg == 'correlation_id' for kw in call.keywords)
    ):
        call.append('correlation_id=CID', trivia=(False, False))

print(module.src)

Transformation:

    # Before
    (logger).info(
        f'not a {thing}',  # this is fine
        extra=extra,  # also this
    )

    # After
    (logger).info(
        f'not a {thing}',  # this is fine
        extra=extra, correlation_id=CID # also this
    )

More thorough recipes and examples: https://tom-pytel.github.io/pfst/fst/docs/d12_examples.html

BIOS setup is a blank screen by Pristine_Cat in techsupport

[–]Pristine_Cat[S] 0 points1 point  (0 children)

Yes, did all this, though waited 5 mins instead of 10. Will try longer juuust in case, but looks like warranty case then like you say. Thx for the help.

BIOS setup is a blank screen by Pristine_Cat in techsupport

[–]Pristine_Cat[S] 0 points1 point  (0 children)

Thx for the suggestion but no luck, same blank screen. Like I said above it is not the common problem about missing the key to press, but rather once the entry into bios setup starts, it clears the splash screen then just waits on a blank screen in a non-crashed state. :( If no key is pressed it proceeds with normal Windows boot.

Also tried pulling the 4090, resetting BIOS again and booting just with integrated gfx in case the BIOS couldn't decide where to display, same thing. This BIOS setup does not want to run after a clear.

Looking for a Simple Notepad like CAS for personal use by Osmanchilln in math

[–]Pristine_Cat 1 point2 points  (0 children)

I don't know how heavy the math you want to do but this is powered by the SymPy symbolic math package and all that has to offer, supporting user variables and lambdas in a locally-served browser WYSIWYG window in notepad format.

https://github.com/Pristine-Cat/SymPad

Hyperbolic sine taylor series expansion by Pristine_Cat in askmath

[–]Pristine_Cat[S] 1 point2 points  (0 children)

That's what I thought, thank you much :)