• 0 Posts
  • 38 Comments
Joined 1 year ago
cake
Cake day: July 7th, 2023

help-circle




  • Personally I would recommend to use regex instead for parsing, which would also allow you to more easily test your expressions. You could then get the list as

    import re
    result = re.findall(r'[\w_]+|\S',  yourstring)  # This will preserve ULLONG_MAX as a single word if that's what you want
    

    As for what’s wrong with your expressions:

    First expression: Once you hit (, OneOrMore(Char(printables)) will take over and continue matching every printable char. Instead you should use OR (|) with the alphanumerical first for priority OneOrMore(word | Char(printables))

    Second expression. You’re running into the same issue with your use of +. Once string.punctuation takes over, it will continue matching until it encounters a char that is not a punctuation and then stop the matching. Instead you can write:

    parser = OneOrMore(Word(alphanums) | Word(string.punctuation))
    result = parser.parseString(yourstring)
    

    Do note that underscore is considered a punctutation so ULLONG_MAX will be split, not sure if that’s what you want or not.


  • I don’t have any experience with pipx and personally prefer to just skip the .toml and place the whole pyprojectsetup in setup.py.

    With that method, I would write inside setup()

    packages=find_packages()  # Include every python packages
    package_data={  # Specify additional data files
        'yourpackagename': [
            'config/*'
            etc...
        ]
    }
    

    This would however require you to have a package folder which all your package files/folders are inside, meaning the top level repo folder should not have any files or other folders that you want to distribute. Your MANIFEST.in looks fine.





  • I get the point the author is coming from. When I was teaching first year engineering students programming, the one on the left is how everyone would write, it’s simply how human intuitively think about a process.

    However, the one on the right feels more robust to me. For non trivial processes with multiple branches, it can ugly real quick if you haven’t isolated functionalities into smaller functions. The issue is never when you are first writing the function, but when you’re debugging or coming back to make changes.

    What if you’re told the new Italian chef wants to have 15 different toppings, not just 2. He also got 3 new steps that must be done to prepare the dough before you can bake the pizza, and the heat of the oven will now depend on the different dough used. My first instinct if my code was the one on the left, would be to refactor it to make room for the new functionality. With the one on the right, the framework is already set and you can easily add new functions for preparing the dough and make a few changes to addToppings() and bake()

    If I feel too lazy to write “proper” code and just make one big function for a process, I often end up regretting it and refactoring it into smaller, more manageable functions once I get back to the project the next day. It’s simply easier to wrap your head around

    bakePizza() 
    box()```
    than reading the entire function and look for comments to mark each important step. The pizza got burned? Better take a look at `bakePizza()` then.




  • As others have suggested, ffmpeg is a great cli tool. If you aren’t comfortable with the terminal you can do it via python like this:

    import os
    import sys
    import subprocess
    
    
    def crop_media(file_name: str, w: int, h: int, x: int, y: int, new_dir: str) -> None:
        try:
            subprocess.run(f'ffmpeg -i "{file_name}" -vf "crop={w}:{h}:{x}:{y}" temp.gif -y',
                               shell=True, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            os.rename('temp.gif', os.path.join(new_dir, file_name))
        # Print the error and continue with other gifs, remove try block if you want a complete stop
        except subprocess.CalledProcessError as e:
            print(e)
        except KeyboardInterrupt:
            print('KeyboardInterrupt, cleaning up files...')
            os.remove('temp.gif')
            sys.exit(0)
    
    
    def crop_directory(directory: str, w: int, h: int, x: int, y: int, new_dir: str) -> None:
        for root, _, files in directory:
            for file in files:
                if not file.endswith('.gif'):
                    continue
                if os.path.isfile(os.path.join(new_dir, file)):
                    print(f'{file} already exists in {new_dir}, skipping...')
                    continue
    
                file_path = os.path.normpath(os.path.join(root, file))
                crop_media(file_path, w, h, x, y, new_dir)
    
    
    if __name__ == '__main__':
        width = 0
        height = 0
        x_offset = 0
        y_offset = 0
        gif_directory = ''
        new_directory = ''
        crop_directory(gif_directory, width, height, x_offset, y_offset, new_directory)
    

    This should go through every file in the directory and subdirectories and call the ffmpeg command on each .gif. With new_directory you can set a directory to store every cropped .gif. The ffmpeg command is based on johnpiers suggestion.

    The script assumes unique filenames for each gif and should work with spaces in the filenames. If they aren’t unique, you can just remove the new_directory part, but you will then lose the original gif that you cropped.






  • Clean code would have indentation though, and you can use whatever space you want as indentation. Bonus points if you use tabs so that others with special needs can configure the tab length on their end.

    And I don’t think I’ve encountered an indentation error since the day I learned the language. How often do you encounter that error when writing python scripts? Sounds more like a theoretical problem than something anyone used to python would encounter.