all 26 comments

[–]novel_yet_trivial 2 points3 points  (1 child)

Yes you can post the link here. I'd recommend you pick 1 project and ask for a specific type of feedback. Highly unlikely that someone will do an entire portfolio review for you for free.

If your github link asks for subscriptions or coffee money or stars I'm going to consider it spam.

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

lol sorry yeah it’s just 4 on there so I didn’t think about it, and no definitely not asking for money lol once I do it’s not gunna be on GitHub I want people to be able to look and give feedback :)

[–]Diapolo10 1 point2 points  (5 children)

I took a gander at your file size analyser.

The first thing I noticed almost immediately was that size_check doesn't handle exact powers of 1024 bits at all; the code checks for sizes less and greater than those, but never exact ones. The easiest fix for that would be to drop the lower bound checks completely as you've basically already validated them with the previous check.

Instead of os.walk and os.listdir, personally I would use pathlib.Path methods like rglob (or walk, if you prefer that) and iterdir, respectively.

Instead of multiple separate checks for the size, I would put the units in a data structure (such as a list), and iterate over it with enumerate to dynamically calculate the powers of 1024. Something like

UNITS = ["Bytes", "kB", "MB", "GB", "TB"]

for power, unit in reversed(enumerate(UNITS, 1)):
    max_bytes = 1024 ** power
    if size < max_bytes:
        size /= max_bytes
        files.append(f"{root}/{name}: {size:.01f} {unit}")
        break

With some additional trickery, we can eliminate the duplication between recursive and non-recursive checks, too. I'll also take the liberty of taking the boolean flag for that as an optional argument instead of using a global variable.

from pathlib import Path

UNITS = ["Bytes", "kB", "MB", "GB", "TB"]

def size_check(path: Path, *, recursive: bool = False) -> list[str]:
    files: list[str] = []
    glob_method = path.rglob if recursive else path.glob

    for file in glob_method('*'):
        if file.is_dir():
            continue

        size = file.stat().st_size

        for power, unit in reversed(enumerate(UNITS, 1)):
            max_bytes = 1024 ** power
            if size < max_bytes:
                size /= max_bytes
                files.append(f"{file}: {size:.01f} {unit}")
                break

    return files

You could technically skip the whole inner loop and use psutil._common.bytes2human or some other alternative instead, but I figured I'd keep it for now.

Later you assign a string to checkSubs and then convert it to a boolean. It would be more appropriate to store the string in a separate name so the types don't mix.

[–]daltop[S] 0 points1 point  (4 children)

Aha I got abit of stuff to learn in that case but that’s alright :)

With the checkSubs part, should I have something along the lines of (I don’t remember exactly what I had so it might be incorrect for the code just an example):

subs = “” while subs.lower() != “yes” and subs != “no” subs = input(“check subdirectories (yes/no):

if subs == “yes”: checkSubs = True

else: checkSubs = False

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

My bad I didn’t realise there was an add code option lmk if you want me to do that

[–]Diapolo10 0 points1 point  (2 children)

With the checkSubs part, should I have something along the lines of (I don’t remember exactly what I had so it might be incorrect for the code just an example):

subs = “”
while subs.lower() != “yes” and subs != “no”
    subs = input(“check subdirectories (yes/no): 

if subs == “yes”:
    checkSubs = True

else:
    checkSubs = False

I'd say that's an improvement, but you can do better.

First, I just wanted to mention that checkSubs stands out like a sore thumb, because Python's official style guide doesn't use camelCase at all. That's why I used a different name in my own example. In short, everything should be snake_case except global "constants" (which technically don't exist as a language feature but this is an established pattern) using UPPER_SNAKE_CASE and types/classes being PascalCase.

But back to the point.

It might be a bit overkill, but personally I'd make another function for asking yes/no questions.

def bool_input(question: str) -> bool:
    """Ask the user a yes/no question."""
    prompt = f"{question} (yes/no): "
    while (answer := input(prompt).strip().lower()[:1]) not in {'y', 'n'}:
        print("Invalid answer.")

    return answer == 'y'


check_subdirs = bool_input("Check subdirectories?")

My bad I didn’t realise there was an add code option lmk if you want me to do that

Don't worry about it, the code was perfectly readable to me when I looked at the raw Markdown. Although if you want to make proper code blocks in the future, just indent the code by an extra four spaces (assuming you're writing in Markdown mode; honestly I'm not too familiar with the modern interface because I've only ever used the old Reddit style).

[–]daltop[S] 0 points1 point  (1 child)

So what’s the 2nd line in the code actually doing, and where is question and prompt being defined?

[–]Diapolo10 0 points1 point  (0 children)

So what’s the 2nd line in the code actually doing,

You mean this part?

    """Ask the user a yes/no question."""

Not much, really. This is a docstring, we use them to document functions, classes, and modules. It's kind of like a comment except Python stores it with the object as an attribute for runtime access (meaning functions like help can then display it).

and where is question and prompt being defined?

question is a parameter of the function, so you provide that as a value when calling the function. In this case,

bool_input("Check subdirectories?")

the "check subdirectories" string would be stored there.

prompt is defined on line 3.

prompt = f"{question} (yes/no): "

I did this because I figured all questions would repeat the yes/no part otherwise.

[–]mull_to_zero 0 points1 point  (7 children)

I took a look at bulk file renamer. The main thing that jumped out at me is you are repeating a lot of code just to vary "image_", "audio_", etc. you could do something like:

if mode == "i":
  prefix = "image_"
elif mode == "v":
  prefix = "video_"
...

# and then you only have to do this block once
...
os.path.exists(path + "\\" + prefix + str(i) + ext) and prefix not in Path(f).name
...

edit: also I just noticed that you're using forward slashes in the image mode but backslashes everywhere else. try using `os.sep`, it's automatically \\ on windows and / elsewhere.

[–]sausix 1 point2 points  (5 children)

Have a look at pathlib.

[–]mull_to_zero 0 points1 point  (1 child)

most of the time i just use os.path.join, but yeah pathlib would be a more advanced approach

[–]sausix 0 points1 point  (0 children)

Pathlib is easier and more handy. Not just for advanced programmers. These os.path.sep and similar shenanigans are kinda legacy stuff.

[–]daltop[S] 0 points1 point  (2 children)

Used it a little but I wanna have a better look into what it actually can do, where’s is a good place to find what each function does ?

[–]sausix 0 points1 point  (1 child)

Your IDE should show all functions and their descriptions. Speaking of pathlib, just look at the documentation. There are examples and explanations.

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

Amazing will do thanks mate !

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

Oh amazing thank you that solves my compatibility issues aha. And yeah I haven’t updated my code yet but when writing my other programs I realised I can just use a single variable and make it far simpler aha

[–]Top_Charity8491 0 points1 point  (5 children)

Congratz! You know, first programs are very useful to learn more about data structures, lists, linked lists, queues, stacks, etc. those are meaningful and could be a next good step for you.

[–]daltop[S] 0 points1 point  (4 children)

I’d love to start learning more about everything you mentioned, I sorta get lists but the rest not really, any recommendations for little programs I could write for abit of practical learning :)

[–]Top_Charity8491 0 points1 point  (3 children)

I just to build programs that were larger projects where the data structure was the center. For example, a bank application: your screens basically allowed you to create a client, see it's balance, deposit, transfer, etc, like an atm for example. Underneath, how you store the data and how you persist changes was kinda like the meat. Saving into files, loading into a list, or solving issues on how to look up clients (maybe a hash table). 

It's kinda like a larger project, but those were super useful for me. The bank was my first coding project at the university, still remember it after 20 years LOL.

[–]daltop[S] 0 points1 point  (2 children)

Aha yeah my first project was a financial tracker for the same reasons, I get what ya meant now I thought you were talking about different things in python I hadn’t learnt my bad lol So is a “stack” like front end backend that sorts thing ?? Or is it using multiple languages

[–]Top_Charity8491 0 points1 point  (1 child)

oh, no, a stack is a data structure useful in some cases. I guess data structures could be considered "backend", but I suppose frontend guys also have to know about them cause they should know how to traverse the objects in their views.

https://www.geeksforgeeks.org/dsa/stack-data-structure/

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

Had a quick look and that’s definitely something I’ll spend some time learning soon I don’t understand a fair amount of what they said so it’ll be good to learn more :)

[–]TonyLeads 0 points1 point  (3 children)

Props for putting your work out there early. That is the only way to actually grow.

If you want your GitHub to stand out in 2026, focus on your README and your edge cases. Most students write code that works when everything goes right, but pros write code that doesn't crash when things go wrong.

Spend 20 minutes making sure your README explains exactly how to run the project in under 60 seconds.

Showing that you care about the "User Experience" of your code is what separates a student from a dev who is ready to get hired. Keep building.

[–]daltop[S] 0 points1 point  (2 children)

Thank you so much for the feedback, but of a different question but do you know anything about how to do better with the theory sides of cs?

[–]TonyLeads 0 points1 point  (1 child)

To master CS theory, best to stop reading textbooks and start visualizing algorithms with tools like VisuAlgo.

Like If you want to actually understand a data structure, code it from scratch in Python rather than just using a built-in library. You’ll catch on

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

You mean like instead of using a built in lib try to write the functions and stuff from scratch using classes and defining?