Convert Integer to Binary String This code takes a user input number which is a positive integer, and outputs a string representation of the number in binary.  For example, input 2 outputs '10' and input 25 outputs '11001'.  As far as I can tell it works correctly.
Please review it for good style and organization, and I'm especially looking for a critique of the algorithm and level of documentation.  My goals are correctness and that it is obvious what the code is doing.  My experience level is I've been using Python for about 7 years, hobbyist, haven't collaborated with other programmers ever, and I'm now in a Comp Sci degree program.
I chose the log2 function and the for loop to calculate how long to run, rather than trying to guess if the calc is over on each pass of the loop, but I assume there is a cleaner/simpler way to do that.
from math import log2, floor

def integer_to_binary_string(int_value):
    '''Converts integer to a string of base-2 bits,
        
    example: 20 becomes '10100'
        
    '''
    rev_str = integer_to_reverse_binary(int_value)
    forward_str = reverse_string(rev_str)
    return forward_str

def integer_to_reverse_binary(int_value):
    '''returns a string, not a numerical'''
    out_s = ''
    if int_value == 0:
        #to avoid ValueError on the log2 call
        return '0'
    #find length of bin string
    bin_digits = floor(log2(int_value)) + 1
    for i in range(bin_digits):
        out_s = out_s + str(int_value // 2**i % 2)
    return out_s

def reverse_string(s):
    return s[::-1]    #start:stop:step slice notation

if __name__ == '__main__':
    user_input = int(input())
    print(integer_to_binary_string(user_input))
Your implementation seems fine at a glance, but Python actually provides two really easy ways to do this:

string.format
bin

Your function would then become:
def integer_to_binary_string(int_value):
    '''Converts integer to a string of base-2 bits,
        
    example: 20 becomes '10100'
        
    '''
    return f&quot;{int_value:b}&quot;
    # or 
    # return bin(int_value)[2:]

The advantages of this are numerous:

Obvious what is happening &amp; idiomatic Python
Doesn't require someone to understand the math behind it
Way faster (timeit with 1,000,000 iterations clocks at 0.23s for my method, 1.82s for yours)

Now to actually review your code (the reinventing-the-wheel tag was added after I started writing this):

Generally, I prefer list comprehensions over an explicit loop; they're often faster
Creating a function called reverse_string is unnecessary - the idiomatic/Pythonic way to do this is using the slice notation you mentioned - hiding it behind a method is just going to confuse experienced Python users.
Repeatedly appending to strings/lists/things is generally not the best from a performance perspective (this has to do with how memory is allocated). Instead, use str.join, as it will do better from a memory allocation perspective

What I would end up with looks like this:
def integer_to_binary_string2(int_value):
    &quot;&quot;&quot;Converts integer to a string of base-2 bits,

    example: 20 becomes '10100'

    &quot;&quot;&quot;
    if int_value == 0:
        return &quot;0&quot;
    bin_digits = floor(log2(int_value)) + 1
    return &quot;&quot;.join([
        str(int_value // 2 ** i % 2) 
        for i in range(bin_digits)
    ])[::-1]

You can use a generator comprehension instead of a list comprehension, but as pointed out by @Graipher in the comments, in CPython str.join turns arbitrary iterables into lists as the very first step, negating any potential benefits. Generally speaking I prefer generator comprehensions to list comprehensions because they can be more memory efficient &amp; are lazily evaluated, but they add no benefit here.