Instruction:
Make a summary of the following Python 3 code
def codepoint_included(self, codepoint):
        if self.codepoints == None:
            return True
        for cp in self.codepoints:
            mismatch = False
            for i in range(len(cp)):
                if (cp[i] is not None) and (cp[i] != codepoint[i]):
                    mismatch = True
                    break
            if not mismatch:
                return True
        return False

Response: Check if codepoint is included in the current codepoints.


Instruction:
Create a Python 3 function for
profiling method used to profile matching codepoints and events.

Response:
def profile(self, frame, event, arg): #PYCHOK arg requ. to match signature
        """Profiling method used to profile matching codepoints and events."""
        if (self.events == None) or (event in self.events):
            frame_info = inspect.getframeinfo(frame)
            cp = (frame_info[0], frame_info[2], frame_info[1])
            if self.codepoint_included(cp):
                objects = muppy.get_objects()
                size = muppy.get_size(objects)
                if cp not in self.memories:
                    self.memories[cp] = [0,0,0,0]
                    self.memories[cp][0] = 1
                    self.memories[cp][1] = size
                    self.memories[cp][2] = size
                else:
                    self.memories[cp][0] += 1
                    if self.memories[cp][1] > size:
                        self.memories[cp][1] = size
                    if self.memories[cp][2] < size:
                        self.memories[cp][2] = size


Instruction:
Can you generate the documentation for the following Python 3 function
def runprofile(mainfunction, output, timeout = 0, calibrate=False):
    '''
    Run the functions profiler and save the result
    If timeout is greater than 0, the profile will automatically stops after timeout seconds
    '''
    if noprofiler == True:
            print('ERROR: profiler and/or pstats library missing ! Please install it (probably package named python-profile) before running a profiling !')
            return False
    # This is the main function for profiling
    def _profile():
        profile.run(mainfunction, output)
    print('=> RUNNING FUNCTIONS PROFILER\n\n'); sys.stdout.flush();
    # Calibrate the profiler (only use this if the profiler produces some funny stuff, but calibration can also produce even more funny stuff with the latest cProfile of Python v2.7! So you should only enable calibration if necessary)
    if calibrate:
        print('Calibrating the profiler...'); sys.stdout.flush();
        cval = calibrateprofile()
        print('Calibration found value : %s' % cval); sys.stdout.flush();
    print('Initializing the profiler...'); sys.stdout.flush();
    # Run in timeout mode (if the function cannot ends by itself, this is the best mode: the function must ends for the profile to be saved)
    if timeout > 0:
        pthread = KThread(target=_profile) # we open the function with the profiler, in a special killable thread (see below why)
        print('Will now run the profiling and terminate it in %s seconds. Results will be saved in %s' % (str(timeout), str(output))); sys.stdout.flush();
        print('\nCountdown:'); sys.stdout.flush();
        for i in range(0,5):
                print(str(5-i))
                sys.stdout.flush()
                time.sleep(1)
        print('0\nStarting to profile...'); sys.stdout.flush();
        pthread.start() # starting the thread
        time.sleep(float(timeout)) # after this amount of seconds, the thread gets killed and the profiler will end its job
        print('\n\nFinishing the profile and saving to the file %s' % str(output)); sys.stdout.flush();
        pthread.kill() # we must end the main function in order for the profiler to output its results (if we didn't launch a thread and just closed the process, it would have done no result)
    # Run in full length mode (we run the function until it ends)
    else:
        print("Running the profiler, please wait until the process terminates by itself (if you forcequit before, the profile won't be saved)")
        _profile()
    print('=> Functions Profile done !')
    return True

Response: Runs profiling and saves the result in a file.


Instruction:
Write a Python 3 script to
calibrate the profiler and return the final value

Response:
def calibrateprofile():
    '''
    Calibrate the profiler (necessary to have non negative and more exact values)
    '''
    pr = profile.Profile()
    calib = []
    crepeat = 10
    for i in range(crepeat):
            calib.append(pr.calibrate(10000))
    final = sum(calib) / crepeat
    profile.Profile.bias = final # Apply computed bias to all Profile instances created hereafter
    return final


Instruction:
Can you write a function in Python 3 where it
parses a profile log and print the result on screen

Response:
def parseprofile(profilelog, out):
    '''
    Parse a profile log and print the result on screen
    '''
    file = open(out, 'w') # opening the output file
    print('Opening the profile in %s...' % profilelog)
    p = pstats.Stats(profilelog, stream=file) # parsing the profile with pstats, and output everything to the file

    print('Generating the stats, please wait...')
    file.write("=== All stats:\n")
    p.strip_dirs().sort_stats(-1).print_stats()
    file.write("=== Cumulative time:\n")
    p.sort_stats('cumulative').print_stats(100)
    file.write("=== Time:\n")
    p.sort_stats('time').print_stats(100)
    file.write("=== Time + cumulative time:\n")
    p.sort_stats('time', 'cum').print_stats(.5, 'init')
    file.write("=== Callees:\n")
    p.print_callees()
    file.write("=== Callers:\n")
    p.print_callers()
    #p.print_callers(.5, 'init')
    #p.add('fooprof')
    file.close()
    print('Stats generated and saved to %s.' % out)
    print('Everything is done. Exiting')


Instruction:
Given the following Python 3 function, write the documentation
def browseprofile(profilelog):
    '''
    Browse interactively a profile log in console
    '''
    print('Starting the pstats profile browser...\n')
    try:
            browser = ProfileBrowser(profilelog)
            print >> browser.stream, "Welcome to the profile statistics browser. Type help to get started."
            browser.cmdloop()
            print >> browser.stream, "Goodbye."
    except KeyboardInterrupt:
            pass

Response: Browse profile log in console


Instruction:
Here you have a function in Python 3, explain what it does
def browseprofilegui(profilelog):
    '''
    Browse interactively a profile log in GUI using RunSnakeRun and SquareMap
    '''
    from runsnakerun import runsnake # runsnakerun needs wxPython lib, if it's not available then we can pass if we don't want a GUI. RunSnakeRun is only used for GUI visualisation, not for profiling (and you can still use pstats for console browsing)
    app = runsnake.RunSnakeRunApp(0)
    app.OnInit(profilelog)
    #app.OnInit()
    app.MainLoop()

Response: Browse a profile log in GUI using RunSnakeRun and SquareMap


Instruction:
Implement a function in Python 3 to
return a list of primes < n

Response:
def rwh_primes1(n):
    # http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    ''' Returns  a list of primes < n '''
    sieve = [True] * (n/2)
    for i in _range(3,int(n**0.5)+1,2):
        if sieve[i/2]:
            sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1)
    return [2] + [2*i+1 for i in _range(1,n/2) if sieve[i]]


Instruction:
Given the following Python 3 function, write the documentation
def find_prime_polynomials(generator=2, c_exp=8, fast_primes=False, single=False):
    '''Compute the list of prime polynomials for the given generator and galois field characteristic exponent.'''
    # fast_primes will output less results but will be significantly faster.
    # single will output the first prime polynomial found, so if all you want is to just find one prime polynomial to generate the LUT for Reed-Solomon to work, then just use that.

    # A prime polynomial (necessarily irreducible) is necessary to reduce the multiplications in the Galois Field, so as to avoid overflows.
    # Why do we need a "prime polynomial"? Can't we just reduce modulo 255 (for GF(2^8) for example)? Because we need the values to be unique.
    # For example: if the generator (alpha) = 2 and c_exp = 8 (GF(2^8) == GF(256)), then the generated Galois Field (0, 1, α, α^1, α^2, ..., α^(p-1)) will be galois field it becomes 0, 1, 2, 4, 8, 16, etc. However, upon reaching 128, the next value will be doubled (ie, next power of 2), which will give 256. Then we must reduce, because we have overflowed above the maximum value of 255. But, if we modulo 255, this will generate 256 == 1. Then 2, 4, 8, 16, etc. giving us a repeating pattern of numbers. This is very bad, as it's then not anymore a bijection (ie, a non-zero value doesn't have a unique index). That's why we can't just modulo 255, but we need another number above 255, which is called the prime polynomial.
    # Why so much hassle? Because we are using precomputed look-up tables for multiplication: instead of multiplying a*b, we precompute alpha^a, alpha^b and alpha^(a+b), so that we can just use our lookup table at alpha^(a+b) and get our result. But just like in our original field we had 0,1,2,...,p-1 distinct unique values, in our "LUT" field using alpha we must have unique distinct values (we don't care that they are different from the original field as long as they are unique and distinct). That's why we need to avoid duplicated values, and to avoid duplicated values we need to use a prime irreducible polynomial.

    # Here is implemented a bruteforce approach to find all these prime polynomials, by generating every possible prime polynomials (ie, every integers between field_charac+1 and field_charac*2), and then we build the whole Galois Field, and we reject the candidate prime polynomial if it duplicates even one value or if it generates a value above field_charac (ie, cause an overflow).
    # Note that this algorithm is slow if the field is too big (above 12), because it's an exhaustive search algorithm. There are probabilistic approaches, and almost surely prime approaches, but there is no determistic polynomial time algorithm to find irreducible monic polynomials. More info can be found at: http://people.mpi-inf.mpg.de/~csaha/lectures/lec9.pdf
    # Another faster algorithm may be found at Adleman, Leonard M., and Hendrik W. Lenstra. "Finding irreducible polynomials over finite fields." Proceedings of the eighteenth annual ACM symposium on Theory of computing. ACM, 1986.

    # Prepare the finite field characteristic (2^p - 1), this also represent the maximum possible value in this field
    root_charac = 2 # we're in GF(2)
    field_charac = int(root_charac**c_exp - 1)
    field_charac_next = int(root_charac**(c_exp+1) - 1)

    prim_candidates = []
    if fast_primes:
        prim_candidates = rwh_primes1(field_charac_next) # generate maybe prime polynomials and check later if they really are irreducible
        prim_candidates = [x for x in prim_candidates if x > field_charac] # filter out too small primes
    else:
        prim_candidates = _range(field_charac+2, field_charac_next, root_charac) # try each possible prime polynomial, but skip even numbers (because divisible by 2 so necessarily not irreducible)

    # Start of the main loop
    correct_primes = []
    for prim in prim_candidates: # try potential candidates primitive irreducible polys
        seen = bytearray(field_charac+1) # memory variable to indicate if a value was already generated in the field (value at index x is set to 1) or not (set to 0 by default)
        conflict = False # flag to know if there was at least one conflict

        # Second loop, build the whole Galois Field
        x = GF2int(1)
        for i in _range(field_charac):
            # Compute the next value in the field (ie, the next power of alpha/generator)
            x = x.multiply(generator, prim, field_charac+1)

            # Rejection criterion: if the value overflowed (above field_charac) or is a duplicate of a previously generated power of alpha, then we reject this polynomial (not prime)
            if x > field_charac or seen[x] == 1:
                conflict = True
                break
            # Else we flag this value as seen (to maybe detect future duplicates), and we continue onto the next power of alpha
            else:
                seen[x] = 1

        # End of the second loop: if there's no conflict (no overflow nor duplicated value), this is a prime polynomial!
        if not conflict:
            correct_primes.append(prim)
            if single: return prim

    # Return the list of all prime polynomials
    return correct_primes

Response: Compute the list of prime polynomials for the given generator and galois field characteristic exponent.


Instruction:
Can you tell what is the following Python 3 function doing
def init_lut(generator=3, prim=0x11b, c_exp=8):
    '''Precompute the logarithm and anti-log (look-up) tables for faster computation later, using the provided primitive polynomial.
    These tables are used for multiplication/division since addition/substraction are simple XOR operations inside GF of characteristic 2.
    The basic idea is quite simple: since b**(log_b(x), log_b(y)) == x * y given any number b (the base or generator of the logarithm), then we can use any number b to precompute logarithm and anti-log (exponentiation) tables to use for multiplying two numbers x and y.
    That's why when we use a different base/generator number, the log and anti-log tables are drastically different, but the resulting computations are the same given any such tables.
    For more infos, see https://en.wikipedia.org/wiki/Finite_field_arithmetic#Implementation_tricks
    '''
    # generator is the generator number (the "increment" that will be used to walk through the field by multiplication, this must be a prime number). This is basically the base of the logarithm/anti-log tables. Also often noted "alpha" in academic books.
    # prim is the primitive/prime (binary) polynomial and must be irreducible (it can't represented as the product of two smaller polynomials). It's a polynomial in the binary sense: each bit is a coefficient, but in fact it's an integer between 0 and 255, and not a list of gf values. For more infos: http://research.swtch.com/field
    # note that the choice of generator or prime polynomial doesn't matter very much: any two finite fields of size p^n have identical structure, even if they give the individual elements different names (ie, the coefficients of the codeword will be different, but the final result will be the same: you can always correct as many errors/erasures with any choice for those parameters). That's why it makes sense to refer to all the finite fields, and all decoders based on Reed-Solomon, of size p^n as one concept: GF(p^n). It can however impact sensibly the speed (because some parameters will generate sparser tables).

    global GF2int_exptable, GF2int_logtable, GF2_charac, GF2_c_exp
    GF2_charac = int(2**c_exp - 1)
    GF2_c_exp = int(c_exp)
    exptable = [-1] * (GF2_charac+1) # anti-log (exponential) table. The first two elements will always be [GF2int(1), generator]
    logtable = [-1] * (GF2_charac+1) # log table, log[0] is impossible and thus unused

    # Construct the anti-log table
    # It's basically the cumulative product of 1 by the generator number, on and on and on until you have walked through the whole field.
    # That's why exptable is always dense (all entries are filled), but logtable may be sparse (lots of empty values, because multiple logtable's entries point to the same exptable's entry).
    g = GF2int(1)
    for i in range(GF2_charac+1): # note that the last item of exptable will always be equal to the first item in the table, because g^p==g^0 because of the modulo p (we're in a finite field!).
        exptable[i] = g # compute anti-log for this value and store it in a table
        #logtable[g] = i # compute logtable at the same time as exptable (but log[1] will always be equal to g^255, which may be weird when compared to lists of logtables online but this is equivalent)
        g = g.multiply(generator, prim, GF2_charac+1) # equivalent to: g = generator**(i+1)

    # Construct the log table
    # Ignore the last element of the field because fields wrap back around.
    # The log of 1 can have two values: either g^0 (the exact value change depending on parameters) or it could be 255 (g^255=1) because of the wraparound
    # Note that either way, this does not change anything any output later (ie, the ecc symbols will be the same either way).
    for i, x in enumerate(exptable[:-1]):
        logtable[x] = i

    # Optimization: convert to integer arrays
    GF2int_exptable = array.array('i', exptable)
    GF2int_logtable = array.array('i', logtable)
    return GF2int_exptable, GF2int_logtable

Response: Initialize the logarithm and anti - log tables for fast computation later using the provided primitive polynomial.


Instruction:
Can you create a Python 3 function that
converts a Galois Field s number into a nice polynomial

Response:
def _to_binpoly(x):
        '''Convert a Galois Field's number into a nice polynomial'''
        if x <= 0: return "0"
        b = 1 # init to 2^0 = 1
        c = [] # stores the degrees of each term of the polynomials
        i = 0 # counter for b = 2^i
        while x > 0:
            b = (1 << i) # generate a number power of 2: 2^0, 2^1, 2^2, ..., 2^i. Equivalent to b = 2^i
            if x & b : # then check if x is divisible by the power of 2. Equivalent to x % 2^i == 0
                # If yes, then...
                c.append(i) # append this power (i, the exponent, gives us the coefficient)
                x ^= b # and compute the remainder of x / b
            i = i+1 # increment to compute the next power of 2
        return " + ".join(["x^%i" % y for y in c[::-1]])


Instruction:
Explain what the following Python 3 code does
def loads( source ):
    source = source.strip()
    assert source.startswith( '{' )
    assert source.endswith( '}' )
    source = source[1:-1]
    result = {}
    for match in attr.finditer( source ):
        key = match.group('key')
        if match.group( 'list' ) is not None:
            value = [
                int(x)
                for x in match.group( 'list' ).strip().replace(',',' ').split()
            ]
        elif match.group( 'int' ) is not None:
            value = int( match.group( 'int' ))
        elif match.group( 'string' ) is not None:
            def deescape( match ):
                return unichr( int( match.group(0)[2:], 16 ))
            value = match.group('string').decode( 'utf-8' )
            value = escape.sub(
                deescape,
                value,
            )
            value = simple_escape.sub(
                lambda x: x.group(1),
                value,
            )
        else:
            raise RuntimeError( "Matched something we don't know how to process:", match.groupdict() )
        result[key] = value
    return result

Response:
Load json structure from meliae from source

    Supports only the required structures to support loading meliae memory dumps


Instruction:
Write a Python 3 function that can
encode a given string or list of values with reed - solomon encoding. Returns a list of values or a string.

Response:
def encode(self, message, poly=False, k=None, return_string=True):
        '''Encode a given string or list of values (between 0 and gf2_charac)
        with reed-solomon encoding. Returns a list of values (or a string if return_string is true)
        with the k message bytes and n-k parity bytes at the end.

        If a message is < k bytes long, it is assumed to be padded at the front
        with null bytes.

        The sequence returned is always n bytes long.

        If poly is not False, returns the encoded Polynomial object instead of
        the polynomial translated back to a string (useful for debugging)
        '''
        n = self.n
        if not k: k = self.k

        if len(message)>k:
            raise ValueError("Message length is max %d. Message was %d" % (k,
                len(message)))

        # If we were given a string, convert to a list (important to support fields above 2^8)
        if isinstance(message, _str):
            message = [ord(x) for x in message]

        # Encode message as a polynomial:
        m = Polynomial([GF2int(x) for x in message])

        # Shift polynomial up by n-k by multiplying by x^(n-k) to reserve the first n-k coefficients for the ecc. This effectively pad the message with \0 bytes for the lower coefficients (where the ecc will be placed).
        mprime = m * Polynomial([GF2int(1)] + [GF2int(0)]*(n-k))

        # mprime = q*g + b for some q
        # so let's find b, the code word (ecc block):
        b = mprime % self.g[k]

        # Subtract out b, so now c = q*g, which is a way of xoring mprime and code word b, which is a way of just saying that we append the polynomial ecc code to the original message (we replace the padded 0 bytes of mprime with the code word)
        c = mprime - b
        # Since c is a multiple of g, it has (at least) n-k roots: α^1 through
        # α^(n-k)

        if not poly:
            # Turn the polynomial c back into a string
            ret = self._list_rjust(c.coefficients, n, 0) # rjust is useful for the nostrip feature
            if return_string and self.gf2_charac < 256:
                ret = self._list2str(ret)
        else:
            ret = c

        return ret


Instruction:
Create a Python 3 function to
verify the codeword is valid by testing that the codeword r divides g returns True or False

Response:
def check(self, r, k=None):
        '''Verifies the codeword is valid by testing that the codeword (message+ecc) as a polynomial code divides g
        returns True/False
        '''
        n = self.n
        if not k: k = self.k
        #h = self.h[k]
        g = self.g[k]

        # If we were given a string, convert to a list (important to support fields above 2^8)
        if isinstance(r, _str):
            r = [ord(x) for x in r]

        # Turn r into a polynomial
        c = Polynomial([GF2int(x) for x in r])

        # This works too, but takes longer. Both checks are just as valid.
        #return (c*h)%gtimesh == Polynomial(x0=0)

        # Since all codewords are multiples of g, checking that codeword c divides g
        # suffices for validating a codeword.
        return c % g == Polynomial(x0=0)


Instruction:
Write a Python 3 function for
fasting check if there s any error in a message + ecc.

Response:
def check_fast(self, r, k=None):
        '''Fast check if there's any error in a message+ecc. Can be used before decoding, in addition to hashes to detect if the message was tampered, or after decoding to check that the message was fully recovered.
        returns True/False
        '''
        n = self.n
        if not k: k = self.k
        #h = self.h[k]
        g = self.g[k]

        # If we were given a string, convert to a list (important to support fields above 2^8)
        if isinstance(r, _str):
            r = [ord(x) for x in r]

        # Turn r into a polynomial
        r = Polynomial([GF2int(x) for x in r])

        # Compute the syndromes:
        sz = self._syndromes(r, k=k)

        # Checking that the syndrome is all 0 is sufficient to check if there are no more any errors in the decoded message
        #return all(int(x) == 0 for x in sz)
        return sz.coefficients.count(GF2int(0)) == len(sz)


Instruction:
Here you have a function in Python 3, explain what it does
def decode(self, r, nostrip=False, k=None, erasures_pos=None, only_erasures=False, return_string=True):
        '''Given a received string or byte array or list r of values between
        0 and gf2_charac, attempts to decode it. If it's a valid codeword, or
        if there are no more than (n-k)/2 errors, the repaired message is returned.

        A message always has k bytes, if a message contained less it is left
        padded with null bytes. When decoded, these leading null bytes are
        stripped, but that can cause problems if decoding binary data. When
        nostrip is True, messages returned are always k bytes long. This is
        useful to make sure no data is lost when decoding binary data.

        Theoretically, we have R(x) = C(x) + E(x) + V(x), where R is the received message, C is the correct message without errors nor erasures, E are the errors and V the erasures. Thus the goal is to compute E and V from R, so that we can compute: C(x) = R(x) - E(x) - V(x), and then we have our original message! The main problem of decoding is to solve the so-called Key Equation, here we use Berlekamp-Massey.

        When stated in the language of spectral estimation, consists of a Fourier transform (syndrome computer), followed by a spectral analysis (Berlekamp-Massey or Euclidian algorithm), followed by an inverse Fourier transform (Chien search).
        (see Blahut, "Algebraic Codes for Data Transmission", 2003, chapter 7.6 Decoding in Time Domain).
        '''
        n = self.n
        if not k: k = self.k

        # If we were given a string, convert to a list (important to support fields above 2^8)
        if isinstance(r, _str):
            r = [ord(x) for x in r]

        # Turn r into a polynomial
        rp = Polynomial([GF2int(x) for x in r])

        if erasures_pos:
            # Convert string positions to coefficients positions for the algebra to work (see _find_erasures_locator(), ecc characters represent the first coefficients while the message is put last, so it's exactly the reverse of the string positions where the message is first and the ecc is last, thus it's just like if you read the message+ecc string in reverse)
            erasures_pos = [len(r)-1-x for x in erasures_pos]
            # Set erasures characters to null bytes
            # Note that you can just leave the original characters as they are, you don't need to set erased characters to null bytes for the decoding to work, but note that it won't help either (ie, fake erasures, meaning characters that were detected as erasures but actually aren't, will still "consume" one ecc symbol, even if you don't set them to null byte, this is because the syndrome is limited to n-k and thus you can't decode above this bound without a clever trick).
            # Example string containing a fake erasure: "hello sam" -> "ooooo sam" with erasures_pos = [0, 1, 2, 3, 4]. Here in fact the last erasure is fake because the original character also was "o" so if we detect "o" as an erasure, we will end up with one fake erasure. But setting it to null byte or not, it will still use up one ecc symbol, it will always be counted as a real erasure. If you're below the n-k bound, then the doceding will be ok. If you're above, then you can't do anything, the decoding won't work. Maybe todo: try to find a clever list decoding algorithm to account for fake erasures....
            # Note: commented out so that the resulting omega (error evaluator polynomial) is the same as the erasure evaluator polynomial when decoding the same number of errors or erasures (ie, decoding 3 erasures only will give the same result as 3 errors only, with of course the errors/erasures on the same characters).
            #for erasure in erasures_pos:
                #rp[erasure] = GF2int(0)

        # Compute the syndromes:
        sz = self._syndromes(rp, k=k)

        if sz.coefficients.count(GF2int(0)) == len(sz): # the code is already valid, there's nothing to do
            # The last n-k bytes are parity
            ret = r[:-(n-k)]
            ecc = r[-(n-k):]
            if not nostrip:
                ret = self._list_lstrip(r[:-(n-k)], 0)
            if return_string and self.gf2_charac < 256:
                ret = self._list2str(ret)
                ecc = self._list2str(ecc)
            return ret, ecc

        # Erasures locator polynomial computation
        erasures_loc = None
        erasures_eval = None
        erasures_count = 0
        if erasures_pos:
            erasures_count = len(erasures_pos)
            # Compute the erasure locator polynomial
            erasures_loc = self._find_erasures_locator(erasures_pos)
            # Compute the erasure evaluator polynomial
            erasures_eval = self._find_error_evaluator(sz, erasures_loc, k=k)

        if only_erasures:
            sigma = erasures_loc
            omega = erasures_eval
        else:
            # Find the error locator polynomial and error evaluator polynomial
            # using the Berlekamp-Massey algorithm
            # if erasures were supplied, BM will generate the errata (errors-and-erasures) locator and evaluator polynomials
            sigma, omega = self._berlekamp_massey(sz, k=k, erasures_loc=erasures_loc, erasures_eval=erasures_eval, erasures_count=erasures_count)
            omega = self._find_error_evaluator(sz, sigma, k=k) # we want to make sure that omega is correct (we know that sigma is always correct, but omega not really)

        # Now use Chien's procedure to find the error locations
        # j is an array of integers representing the positions of the errors, 0
        # being the rightmost byte
        # X is a corresponding array of GF(2^8) values where X_i = alpha^(j_i)
        X, j = self._chien_search(sigma)

        # Sanity check: Cannot guarantee correct decoding of more than n-k errata (Singleton Bound, n-k being the minimum distance), and we cannot even check if it's correct (the syndrome will always be all 0 if we try to decode above the bound), thus it's better to just return the input as-is.
        if len(j) > n-k:
            ret = r[:-(n-k)]
            ecc = r[-(n-k):]
            if not nostrip:
                ret = self._list_lstrip(r[:-(n-k)], 0)
            if return_string and self.gf2_charac < 256:
                ret = self._list2str(ret)
                ecc = self._list2str(ecc)
            return ret, ecc

        # And finally, find the error magnitudes with Forney's Formula
        # Y is an array of GF(2^8) values corresponding to the error magnitude
        # at the position given by the j array
        Y = self._forney(omega, X)

        # Put the error and locations together to form the error polynomial
        # Note that an alternative would be to compute the error-spectrum polynomial E(x) which satisfies E(x)*Sigma(x) = 0 (mod x^n - 1) = Omega(x)(x^n - 1) -- see Blahut, Algebraic codes for data transmission
        Elist = [GF2int(0)] * self.gf2_charac
        if len(Y) >= len(j): # failsafe: if the number of erratas is higher than the number of coefficients in the magnitude polynomial, we failed!
            for i in _range(self.gf2_charac): # FIXME? is this really necessary to go to self.gf2_charac? len(rp) wouldn't be just enough? (since the goal is anyway to substract E to rp)
                if i in j:
                    Elist[i] = Y[j.index(i)]
            E = Polynomial( Elist[::-1] ) # reverse the list because we used the coefficient degrees (j) instead of the error positions
        else:
            E = Polynomial()

        # And we get our real codeword!
        c = rp - E # Remember what we wrote above: R(x) = C(x) + E(x), so here to get back the original codeword C(x) = R(x) - E(x) ! (V(x) the erasures are here is included inside E(x))

        if len(c) > len(r): c = rp # failsafe: in case the correction went totally wrong (we repaired padded null bytes instead of the message! thus we end up with a longer message than what we should have), then we just return the uncorrected message. Note: we compare the length of c with r on purpose, that's not an error: if we compare with rp, if the first few characters were erased (null bytes) in r, then in rp the Polynomial will automatically skip them, thus the length will always be smaller in that case.

        # Split the polynomial into two parts: the corrected message and the corrected ecc
        ret = c.coefficients[:-(n-k)]
        ecc = c.coefficients[-(n-k):]

        if nostrip:
            # Polynomial objects don't store leading 0 coefficients, so we
            # actually need to pad this to k bytes
            ret = self._list_rjust(ret, k, 0)

        if return_string and self.gf2_charac < 256: # automatically disable return_string if the field is above 255 (chr would fail, so it's up to the user to define the mapping)
            # Form it back into a string
            ret = self._list2str(ret)
            ecc = self._list2str(ecc)

        return ret, ecc

Response: Given a received string or byte array or list r attempts to decode it.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _list_lstrip(self, L, val=0):
        '''Left strip the specified value'''
        for i in _range(len(L)):
            if L[i] != val:
                return L[i:]

Response: Left strip the specified value from the specified list.


Instruction:
Can you create a Python 3 function that
leaves pad with the specified value to obtain a list of the specified width

Response:
def _list_rjust(self, L, width, fillchar=0):
        '''Left pad with the specified value to obtain a list of the specified width (length)'''
        length = max(0, width - len(L))
        return [fillchar]*length + L


Instruction:
Make a summary of the following Python 3 code
def _syndromes(self, r, k=None):
        '''Given the received codeword r in the form of a Polynomial object,
        computes the syndromes and returns the syndrome polynomial.
        Mathematically, it's essentially equivalent to a Fourrier Transform (Chien search being the inverse).
        '''
        n = self.n
        if not k: k = self.k
        # Note the + [GF2int(0)] : we add a 0 coefficient for the lowest degree (the constant). This effectively shifts the syndrome, and will shift every computations depending on the syndromes (such as the errors locator polynomial, errors evaluator polynomial, etc. but not the errors positions).
        # This is not necessary as anyway syndromes are defined such as there are only non-zero coefficients (the only 0 is the shift of the constant here) and subsequent computations will/must account for the shift by skipping the first iteration (eg, the often seen range(1, n-k+1)), but you can also avoid prepending the 0 coeff and adapt every subsequent computations to start from 0 instead of 1.
        return Polynomial( [r.evaluate( GF2int(self.generator)**(l+self.fcr) ) for l in _range(n-k-1, -1, -1)] + [GF2int(0)], keep_zero=True )

Response: Given the received codeword r computes the syndromes and returns the syndrome polynomial.


Instruction:
Create a Python 3 function for
finding the erasures locator polynomial from the erasures positions.

Response:
def _find_erasures_locator(self, erasures_pos):
        '''Compute the erasures locator polynomial from the erasures positions (the positions must be relative to the x coefficient, eg: "hello worldxxxxxxxxx" is tampered to "h_ll_ worldxxxxxxxxx" with xxxxxxxxx being the ecc of length n-k=9, here the string positions are [1, 4], but the coefficients are reversed since the ecc characters are placed as the first coefficients of the polynomial, thus the coefficients of the erased characters are n-1 - [1, 4] = [18, 15] = erasures_loc to be specified as an argument.'''
        # See: http://ocw.usu.edu/Electrical_and_Computer_Engineering/Error_Control_Coding/lecture7.pdf and Blahut, Richard E. "Transform techniques for error control codes." IBM Journal of Research and development 23.3 (1979): 299-315. http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.92.600&rep=rep1&type=pdf and also a MatLab implementation here: http://www.mathworks.com/matlabcentral/fileexchange/23567-reed-solomon-errors-and-erasures-decoder/content//RS_E_E_DEC.m
        erasures_loc = Polynomial([GF2int(1)]) # just to init because we will multiply, so it must be 1 so that the multiplication starts correctly without nulling any term
        # erasures_loc is very simple to compute: erasures_loc = prod(1 - x*alpha[j]**i) for i in erasures_pos and where alpha is the alpha chosen to evaluate polynomials (here in this library it's gf(3)). To generate c*x where c is a constant, we simply generate a Polynomial([c, 0]) where 0 is the constant and c is positionned to be the coefficient for x^1. See https://en.wikipedia.org/wiki/Forney_algorithm#Erasures
        for i in erasures_pos:
            erasures_loc = erasures_loc * (Polynomial([GF2int(1)]) - Polynomial([GF2int(self.generator)**i, 0]))
        return erasures_loc


Instruction:
How would you explain what the following Python 3 function does
def _berlekamp_massey(self, s, k=None, erasures_loc=None, erasures_eval=None, erasures_count=0):
        '''Computes and returns the errata (errors+erasures) locator polynomial (sigma) and the
        error evaluator polynomial (omega) at the same time.
        If the erasures locator is specified, we will return an errors-and-erasures locator polynomial and an errors-and-erasures evaluator polynomial, else it will compute only errors. With erasures in addition to errors, it can simultaneously decode up to v+2e <= (n-k) where v is the number of erasures and e the number of errors.
        Mathematically speaking, this is equivalent to a spectral analysis (see Blahut, "Algebraic Codes for Data Transmission", 2003, chapter 7.6 Decoding in Time Domain).
        The parameter s is the syndrome polynomial (syndromes encoded in a
        generator function) as returned by _syndromes.

        Notes:
        The error polynomial:
        E(x) = E_0 + E_1 x + ... + E_(n-1) x^(n-1)

        j_1, j_2, ..., j_s are the error positions. (There are at most s
        errors)

        Error location X_i is defined: X_i = α^(j_i)
        that is, the power of α (alpha) corresponding to the error location

        Error magnitude Y_i is defined: E_(j_i)
        that is, the coefficient in the error polynomial at position j_i

        Error locator polynomial:
        sigma(z) = Product( 1 - X_i * z, i=1..s )
        roots are the reciprocals of the error locations
        ( 1/X_1, 1/X_2, ...)

        Error evaluator polynomial omega(z) is here computed at the same time as sigma, but it can also be constructed afterwards using the syndrome and sigma (see _find_error_evaluator() method).

        It can be seen that the algorithm tries to iteratively solve for the error locator polynomial by
        solving one equation after another and updating the error locator polynomial. If it turns out that it
        cannot solve the equation at some step, then it computes the error and weights it by the last
        non-zero discriminant found, and delays the weighted result to increase the polynomial degree
        by 1. Ref: "Reed Solomon Decoder: TMS320C64x Implementation" by Jagadeesh Sankaran, December 2000, Application Report SPRA686

        The best paper I found describing the BM algorithm for errata (errors-and-erasures) evaluator computation is in "Algebraic Codes for Data Transmission", Richard E. Blahut, 2003.
        '''
        # For errors-and-erasures decoding, see: "Algebraic Codes for Data Transmission", Richard E. Blahut, 2003 and (but it's less complete): Blahut, Richard E. "Transform techniques for error control codes." IBM Journal of Research and development 23.3 (1979): 299-315. http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.92.600&rep=rep1&type=pdf and also a MatLab implementation here: http://www.mathworks.com/matlabcentral/fileexchange/23567-reed-solomon-errors-and-erasures-decoder/content//RS_E_E_DEC.m
        # also see: Blahut, Richard E. "A universal Reed-Solomon decoder." IBM Journal of Research and Development 28.2 (1984): 150-158. http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.84.2084&rep=rep1&type=pdf
        # and another good alternative book with concrete programming examples: Jiang, Yuan. A practical guide to error-control coding using Matlab. Artech House, 2010.
        n = self.n
        if not k: k = self.k

        # Initialize, depending on if we include erasures or not:
        if erasures_loc:
            sigma = [ Polynomial(erasures_loc.coefficients) ] # copy erasures_loc by creating a new Polynomial, so that we initialize the errata locator polynomial with the erasures locator polynomial.
            B = [ Polynomial(erasures_loc.coefficients) ]
            omega = [ Polynomial(erasures_eval.coefficients) ] # to compute omega (the evaluator polynomial) at the same time, we also need to initialize it with the partial erasures evaluator polynomial
            A = [ Polynomial(erasures_eval.coefficients) ] # TODO: fix the initial value of the evaluator support polynomial, because currently the final omega is not correct (it contains higher order terms that should be removed by the end of BM)
        else:
            sigma = [ Polynomial([GF2int(1)]) ] # error locator polynomial. Also called Lambda in other notations.
            B = [ Polynomial([GF2int(1)]) ] # this is the error locator support/secondary polynomial, which is a funky way to say that it's just a temporary variable that will help us construct sigma, the error locator polynomial
            omega = [ Polynomial([GF2int(1)]) ] # error evaluator polynomial. We don't need to initialize it with erasures_loc, it will still work, because Delta is computed using sigma, which itself is correctly initialized with erasures if needed.
            A = [ Polynomial([GF2int(0)]) ] # this is the error evaluator support/secondary polynomial, to help us construct omega
        L = [ 0 ] # update flag: necessary variable to check when updating is necessary and to check bounds (to avoid wrongly eliminating the higher order terms). For more infos, see https://www.cs.duke.edu/courses/spring11/cps296.3/decoding_rs.pdf
        M = [ 0 ] # optional variable to check bounds (so that we do not mistakenly overwrite the higher order terms). This is not necessary, it's only an additional safe check. For more infos, see the presentation decoding_rs.pdf by Andrew Brown in the doc folder.

        # Fix the syndrome shifting: when computing the syndrome, some implementations may prepend a 0 coefficient for the lowest degree term (the constant). This is a case of syndrome shifting, thus the syndrome will be bigger than the number of ecc symbols (I don't know what purpose serves this shifting). If that's the case, then we need to account for the syndrome shifting when we use the syndrome such as inside BM, by skipping those prepended coefficients.
        # Another way to detect the shifting is to detect the 0 coefficients: by definition, a syndrome does not contain any 0 coefficient (except if there are no errors/erasures, in this case they are all 0). This however doesn't work with the modified Forney syndrome (that we do not use in this lib but it may be implemented in the future), which set to 0 the coefficients corresponding to erasures, leaving only the coefficients corresponding to errors.
        synd_shift = 0
        if len(s) > (n-k): synd_shift = len(s) - (n-k)

        # Polynomial constants:
        ONE = Polynomial(z0=GF2int(1))
        ZERO = Polynomial(z0=GF2int(0))
        Z = Polynomial(z1=GF2int(1)) # used to shift polynomials, simply multiply your poly * Z to shift

        # Precaching
        s2 = ONE + s

        # Iteratively compute the polynomials n-k-erasures_count times. The last ones will be correct (since the algorithm refines the error/errata locator polynomial iteratively depending on the discrepancy, which is kind of a difference-from-correctness measure).
        for l in _range(0, n-k-erasures_count): # skip the first erasures_count iterations because we already computed the partial errata locator polynomial (by initializing with the erasures locator polynomial)
            K = erasures_count+l+synd_shift # skip the FIRST erasures_count iterations (not the last iterations, that's very important!)

            # Goal for each iteration: Compute sigma[l+1] and omega[l+1] such that
            # (1 + s)*sigma[l] == omega[l] in mod z^(K)

            # For this particular loop iteration, we have sigma[l] and omega[l],
            # and are computing sigma[l+1] and omega[l+1]

            # First find Delta, the non-zero coefficient of z^(K) in
            # (1 + s) * sigma[l]
            # Note that adding 1 to the syndrome s is not really necessary, you can do as well without.
            # This delta is valid for l (this iteration) only
            Delta = ( s2 * sigma[l] ).get_coefficient(K) # Delta is also known as the Discrepancy, and is always a scalar (not a polynomial).
            # Make it a polynomial of degree 0, just for ease of computation with polynomials sigma and omega.
            Delta = Polynomial(x0=Delta)

            # Can now compute sigma[l+1] and omega[l+1] from
            # sigma[l], omega[l], B[l], A[l], and Delta
            sigma.append( sigma[l] - Delta * Z * B[l] )
            omega.append( omega[l] - Delta * Z * A[l] )

            # Now compute the next support polynomials B and A
            # There are two ways to do this
            # This is based on a messy case analysis on the degrees of the four polynomials sigma, omega, A and B in order to minimize the degrees of A and B. For more infos, see https://www.cs.duke.edu/courses/spring10/cps296.3/decoding_rs_scribe.pdf
            # In fact it ensures that the degree of the final polynomials aren't too large.
            if Delta == ZERO or 2*L[l] > K+erasures_count \
                or (2*L[l] == K+erasures_count and M[l] == 0):
            #if Delta == ZERO or len(sigma[l+1]) <= len(sigma[l]): # another way to compute when to update, and it doesn't require to maintain the update flag L
                # Rule A
                B.append( Z * B[l] )
                A.append( Z * A[l] )
                L.append( L[l] )
                M.append( M[l] )

            elif (Delta != ZERO and 2*L[l] < K+erasures_count) \
                or (2*L[l] == K+erasures_count and M[l] != 0):
            # elif Delta != ZERO and len(sigma[l+1]) > len(sigma[l]): # another way to compute when to update, and it doesn't require to maintain the update flag L
                # Rule B
                B.append( sigma[l] // Delta )
                A.append( omega[l] // Delta )
                L.append( K - L[l] ) # the update flag L is tricky: in Blahut's schema, it's mandatory to use `L = K - L - erasures_count` (and indeed in a previous draft of this function, if you forgot to do `- erasures_count` it would lead to correcting only 2*(errors+erasures) <= (n-k) instead of 2*errors+erasures <= (n-k)), but in this latest draft, this will lead to a wrong decoding in some cases where it should correctly decode! Thus you should try with and without `- erasures_count` to update L on your own implementation and see which one works OK without producing wrong decoding failures.
                M.append( 1 - M[l] )

            else:
                raise Exception("Code shouldn't have gotten here")

        # Hack to fix the simultaneous computation of omega, the errata evaluator polynomial: because A (the errata evaluator support polynomial) is not correctly initialized (I could not find any info in academic papers). So at the end, we get the correct errata evaluator polynomial omega + some higher order terms that should not be present, but since we know that sigma is always correct and the maximum degree should be the same as omega, we can fix omega by truncating too high order terms.
        if omega[-1].degree > sigma[-1].degree: omega[-1] = Polynomial(omega[-1].coefficients[-(sigma[-1].degree+1):])

        # Debuglines, uncomment to show the result of every iterations
        #print "SIGMA BM"
        #for i,x in enumerate(sigma):
            #print i, ":", x

        # Return the last result of the iterations (since BM compute iteratively, the last iteration being correct - it may already be before, but we're not sure)
        return sigma[-1], omega[-1]

Response: Computes and returns the errata locator polynomial and error evaluator polynomial at the same time.


Instruction:
Can you generate the documentation for the following Python 3 function
def _berlekamp_massey_fast(self, s, k=None, erasures_loc=None, erasures_eval=None, erasures_count=0):
        '''Faster implementation of errata (errors-and-erasures) Berlekamp-Massey.
        Returns the error locator polynomial (sigma) and the
        error evaluator polynomial (omega) with a faster implementation.
        '''
        n = self.n
        if not k: k = self.k

        # Initialize, depending on if we include erasures or not:
        if erasures_loc:
            sigma = Polynomial(erasures_loc.coefficients) # copy erasures_loc by creating a new Polynomial, so that we initialize the errata locator polynomial with the erasures locator polynomial.
            sigmaprev = Polynomial(sigma.coefficients)
            B = Polynomial(sigma.coefficients)
            omega = Polynomial(erasures_eval.coefficients) # to compute omega (the evaluator polynomial) at the same time, we also need to initialize it with the partial erasures evaluator polynomial
            omegaprev = Polynomial(omega.coefficients)
            A = Polynomial(omega.coefficients) # TODO: fix the initial value of the evaluator support polynomial, because currently the final omega is not correct (it contains higher order terms that should be removed by the end of BM)
        else:
            sigma = sigmaprev = Polynomial([GF2int(1)]) # error locator polynomial. Also called Lambda in other notations.
            sigmaprev = Polynomial([GF2int(1)]) # we need the previous iteration to compute the next value of the support polynomials
            B = Polynomial([GF2int(1)]) # this is the error locator support/secondary polynomial, which is a funky way to say that it's just a temporary variable that will help us construct sigma, the error locator polynomial
            omega = omegaprev = Polynomial([GF2int(1)]) # error evaluator polynomial. We don't need to initialize it with erasures_loc, it will still work, because Delta is computed using sigma, which itself is correctly initialized with erasures if needed.
            omegaprev = Polynomial([GF2int(1)])
            A = Polynomial([GF2int(0)]) # this is the error evaluator support/secondary polynomial, to help us construct omega
        L = 0 # update flag: necessary variable to check when updating is necessary and to check bounds (to avoid wrongly eliminating the higher order terms). For more infos, see https://www.cs.duke.edu/courses/spring11/cps296.3/decoding_rs.pdf
        #M = 0 # optional variable to check bounds (so that we do not mistakenly overwrite the higher order terms). This is not necessary, it's only an additional safe check. For more infos, see the presentation decoding_rs.pdf by Andrew Brown in the doc folder.

        # Fix the syndrome shifting: when computing the syndrome, some implementations may prepend a 0 coefficient for the lowest degree term (the constant). This is a case of syndrome shifting, thus the syndrome will be bigger than the number of ecc symbols (I don't know what purpose serves this shifting). If that's the case, then we need to account for the syndrome shifting when we use the syndrome such as inside BM, by skipping those prepended coefficients.
        # Another way to detect the shifting is to detect the 0 coefficients: by definition, a syndrome does not contain any 0 coefficient (except if there are no errors/erasures, in this case they are all 0). This however doesn't work with the modified Forney syndrome (that we do not use in this lib but it may be implemented in the future), which set to 0 the coefficients corresponding to erasures, leaving only the coefficients corresponding to errors.
        synd_shift = 0
        if len(s) > (n-k): synd_shift = len(s) - (n-k)

        # Polynomial constants:
        ONE = Polynomial([GF2int(1)])
        ZERO = GF2int(0)
        Z = Polynomial([GF2int(1), GF2int(0)]) # used to shift polynomials, simply multiply your poly * Z to shift

        # Precaching
        s2 = ONE+s

        # Iteratively compute the polynomials n-k-erasures_count times. The last ones will be correct (since the algorithm refines the error/errata locator polynomial iteratively depending on the discrepancy, which is kind of a difference-from-correctness measure).
        for l in _range(n-k-erasures_count): # skip the first erasures_count iterations because we already computed the partial errata locator polynomial (by initializing with the erasures locator polynomial)
            K = erasures_count+l+synd_shift # skip the FIRST erasures_count iterations (not the last iterations, that's very important!)

            # Goal for each iteration: Compute sigma[l+1] and omega[l+1] such that
            # (1 + s)*sigma[l] == omega[l] in mod z^(K)

            # For this particular loop iteration, we have sigma[l] and omega[l],
            # and are computing sigma[l+1] and omega[l+1]

            # First find Delta, the non-zero coefficient of z^(K) in
            # (1 + s) * sigma[l]
            # Note that adding 1 to the syndrome s is not really necessary, you can do as well without.
            # This delta is valid for l (this iteration) only
            Delta = s2.mul_at(sigma, K) # Delta is also known as the Discrepancy, and is always a scalar (not a polynomial). We just need one coefficient at a specific degree, so we can optimize by computing only the polynomial multiplication at this term, and skip the others.

            # Can now compute sigma[l+1] and omega[l+1] from
            # sigma[l], omega[l], B[l], A[l], and Delta
            sigmaprev = sigma
            omegaprev = omega
            sigma = sigma - (Z * B).scale(Delta)
            omega = omega - (Z * A).scale(Delta)

            # Now compute the next support polynomials B and A
            # There are two ways to do this
            # This is based on a messy case analysis on the degrees of the four polynomials sigma, omega, A and B in order to minimize the degrees of A and B. For more infos, see https://www.cs.duke.edu/courses/spring10/cps296.3/decoding_rs_scribe.pdf
            # In fact it ensures that the degree of the final polynomials aren't too large.
            if Delta == ZERO or 2*L > K+erasures_count:
                #or (2*L == K+erasures_count and M == 0):
            #if Delta == ZERO or len(sigma) <= len(sigmaprev): # another way to compute when to update, and it doesn't require to maintain the update flag L
                # Rule A
                B = Z * B
                A = Z * A
                #L = L
                #M = M

            else:
            #elif (Delta != ZERO and 2*L < K+erasures_count) \
            #    or (2*L == K+erasures_count and M != 0):
            # elif Delta != ZERO and len(sigma) > len(sigmaprev): # another way to compute when to update, and it doesn't require to maintain the update flag L
                # Rule B
                B = sigmaprev.scale(Delta.inverse())
                A = omegaprev.scale(Delta.inverse())
                L = K - L # the update flag L is tricky: in Blahut's schema, it's mandatory to use `L = K - L - erasures_count` (and indeed in a previous draft of this function, if you forgot to do `- erasures_count` it would lead to correcting only 2*(errors+erasures) <= (n-k) instead of 2*errors+erasures <= (n-k)), but in this latest draft, this will lead to a wrong decoding in some cases where it should correctly decode! Thus you should try with and without `- erasures_count` to update L on your own implementation and see which one works OK without producing wrong decoding failures.
                #M = 1 - M

            #else:
            #    raise Exception("Code shouldn't have gotten here")

        # Hack to fix the simultaneous computation of omega, the errata evaluator polynomial: because A (the errata evaluator support polynomial) is not correctly initialized (I could not find any info in academic papers). So at the end, we get the correct errata evaluator polynomial omega + some higher order terms that should not be present, but since we know that sigma is always correct and the maximum degree should be the same as omega, we can fix omega by truncating too high order terms.
        if omega.degree > sigma.degree: omega = Polynomial(omega.coefficients[-(sigma.degree+1):])

        # Return the last result of the iterations (since BM compute iteratively, the last iteration being correct - it may already be before, but we're not sure)
        return sigma, omega

Response: Faster implementation of errata ( errors - and - erasures ) Berlekamp - Massey.


Instruction:
Here you have a function in Python 3, explain what it does
def _find_error_evaluator(self, synd, sigma, k=None):
        '''Compute the error (or erasures if you supply sigma=erasures locator polynomial) evaluator polynomial Omega from the syndrome and the error/erasures/errata locator Sigma. Omega is already computed at the same time as Sigma inside the Berlekamp-Massey implemented above, but in case you modify Sigma, you can recompute Omega afterwards using this method, or just ensure that Omega computed by BM is correct given Sigma (as long as syndrome and sigma are correct, omega will be correct).'''
        n = self.n
        if not k: k = self.k

        # Omega(x) = [ (1 + Synd(x)) * Error_loc(x) ] mod x^(n-k+1)
        # NOTE: I don't know why we do 1+Synd(x) here, from docs it seems just Synd(x) is enough (and in practice if you remove the "ONE +" it will still decode correcty) as advised by Blahut in Algebraic Codes for Data Transmission, but it seems it's an implementation detail here.
        #ONE = Polynomial([GF2int(1)])
        #return ((ONE + synd) * sigma) % Polynomial([GF2int(1)] + [GF2int(0)] * (n-k+1)) # NOT CORRECT: in practice it works flawlessly with this implementation (primitive polynomial = 3), but if you use another primitive like in reedsolo lib, it doesn't work! Thus, I guess that adding ONE is not correct for the general case.
        return (synd * sigma) % Polynomial([GF2int(1)] + [GF2int(0)] * (n-k+1))

Response: Compute the error or erasures evaluator polynomial Omega from the syndrome and the error / errata locator polynomial Omega from the syndrome and the error / erasures locator polynomial Sigma.


Instruction:
Write a Python 3 function for
computing the error evaluator polynomial Omega from the syndrome and the error / errata locator polynomial Omega.

Response:
def _find_error_evaluator_fast(self, synd, sigma, k=None):
        '''Compute the error (or erasures if you supply sigma=erasures locator polynomial) evaluator polynomial Omega from the syndrome and the error/erasures/errata locator Sigma. Omega is already computed at the same time as Sigma inside the Berlekamp-Massey implemented above, but in case you modify Sigma, you can recompute Omega afterwards using this method, or just ensure that Omega computed by BM is correct given Sigma (as long as syndrome and sigma are correct, omega will be correct).'''
        n = self.n
        if not k: k = self.k

        # Omega(x) = [ Synd(x) * Error_loc(x) ] mod x^(n-k+1) -- From Blahut, Algebraic codes for data transmission, 2003
        return (synd * sigma)._gffastmod(Polynomial([GF2int(1)] + [GF2int(0)] * (n-k+1)))


Instruction:
Can you generate the documentation for the following Python 3 function
def _chien_search(self, sigma):
        '''Recall the definition of sigma, it has s roots. To find them, this
        function evaluates sigma at all 2^(c_exp-1) (ie: 255 for GF(2^8)) non-zero points to find the roots
        The inverse of the roots are X_i, the error locations

        Returns a list X of error locations, and a corresponding list j of
        error positions (the discrete log of the corresponding X value) The
        lists are up to s elements large.

        This is essentially an inverse Fourrier transform.

        Important technical math note: This implementation is not actually
        Chien's search. Chien's search is a way to evaluate the polynomial
        such that each evaluation only takes constant time. This here simply
        does 255 evaluations straight up, which is much less efficient.
        Said differently, we simply do a bruteforce search by trial substitution to find the zeros of this polynomial, which identifies the error locations.
        '''
        # TODO: find a more efficient algorithm, this is the slowest part of the whole decoding process (~2.5 ms, while any other part is only ~400microsec). Could try the Pruned FFT from "Simple Algorithms for BCH Decoding", by Jonathan Hong and Martin Vetterli, IEEE Transactions on Communications, Vol.43, No.8, August 1995
        X = []
        j = []
        p = GF2int(self.generator)
        # Try for each possible location
        for l in _range(1, self.gf2_charac+1): # range 1:256 is important: if you use range 0:255, if the last byte of the ecc symbols is corrupted, it won't be correctable! You need to use the range 1,256 to include this last byte.
            #l = (i+self.fcr)
            # These evaluations could be more efficient, but oh well
            if sigma.evaluate( p**l ) == 0: # If it's 0, then bingo! It's an error location
                # Compute the error location polynomial X (will be directly used to compute the errors magnitudes inside the Forney algorithm)
                X.append( p**(-l) )
                # Compute the coefficient position (not the error position, it's actually the reverse: we compute the degree of the term where the error is located. To get the error position, just compute n-1-j).
                # This is different than the notes, I think the notes were in error
                # Notes said j values were just l, when it's actually 255-l
                j.append(self.gf2_charac - l)

        # Sanity check: the number of errors/errata positions found should be exactly the same as the length of the errata locator polynomial
        errs_nb = len(sigma) - 1 # compute the exact number of errors/errata that this error locator should find
        if len(j) != errs_nb:
            raise RSCodecError("Too many (or few) errors found by Chien Search for the errata locator polynomial!")

        return X, j

Response: Recall the definition of sigma it has s roots. To find them it has s roots. To find them it has s roots. To find them it has s roots and the error positions of the error locations and j of the error positions of the roots.


Instruction:
Explain what the following Python 3 code does
def _chien_search_fast(self, sigma):
        '''Real chien search, we reuse the previous polynomial evaluation and just multiply by a constant polynomial. This should be faster, but it seems it's just the same speed as the other bruteforce version. However, it should easily be parallelizable.'''
        # TODO: doesn't work when fcr is different than 1 (X values are incorrectly "shifted"...)
        # TODO: try to mix this approach with the optimized walk on only interesting values, implemented in _chien_search_faster()
        X = []
        j = []
        p = GF2int(self.generator)
        if not hasattr(self, 'const_poly'): self.const_poly = [GF2int(self.generator)**(i+self.fcr) for i in _range(self.gf2_charac, -1, -1)] # constant polynomial that will allow us to update the previous polynomial evaluation to get the next one
        const_poly = self.const_poly # caching for more efficiency since it never changes
        ev_poly, ev = sigma.evaluate_array( p**1 ) # compute the first polynomial evaluation
        # Try for each possible location
        for l in _range(1, self.gf2_charac+1): # range 1:256 is important: if you use range 0:255, if the last byte of the ecc symbols is corrupted, it won't be correctable! You need to use the range 1,256 to include this last byte.
            #l = (i+self.fcr)

            # Check if it's a root for the polynomial
            if ev == 0: # If it's 0, then bingo! It's an error location
                # Compute the error location polynomial X (will be directly used to compute the errors magnitudes inside the Forney algorithm)
                X.append( p**(-l) )
                # Compute the coefficient position (not the error position, it's actually the reverse: we compute the degree of the term where the error is located. To get the error position, just compute n-1-j).
                # This is different than the notes, I think the notes were in error
                # Notes said j values were just l, when it's actually 255-l
                j.append(self.gf2_charac - l)

            # Update the polynomial evaluation for the next iteration
            # we simply multiply each term[k] with alpha^k (where here alpha = p = GF2int(generator)).
            # For more info, see the presentation by Andrew Brown, or this one: http://web.ntpu.edu.tw/~yshan/BCH_decoding.pdf
            # TODO: parallelize this loop
            for i in _range(1, len(ev_poly)+1): # TODO: maybe the fcr != 1 fix should be put here?
                ev_poly[-i] *= const_poly[-i]
            # Compute the new evaluation by just summing
            ev = sum(ev_poly)

        return X, j

Response: Real chien search for the next set of ecc symbols.


Instruction:
Create a Python 3 function to
compute the error magnitudes for a given polynomial X and k.

Response:
def _old_forney(self, omega, X, k=None):
        '''Computes the error magnitudes (only works with errors or erasures under t = floor((n-k)/2), not with erasures above (n-k)//2)'''
        # XXX Is floor division okay here? Should this be ceiling?
        if not k: k = self.k
        t = (self.n - k) // 2

        Y = []

        for l, Xl in enumerate(X):

            # Compute the sequence product and multiply its inverse in
            prod = GF2int(1) # just to init the product (1 is the neutral term for multiplication)
            Xl_inv = Xl.inverse()
            for ji in _range(t): # do not change to _range(len(X)) as can be seen in some papers, it won't give the correct result! (sometimes yes, but not always)
                if ji == l:
                    continue
                if ji < len(X):
                    Xj = X[ji]
                else: # if above the maximum degree of the polynomial, then all coefficients above are just 0 (that's logical...)
                    Xj = GF2int(0)
                prod = prod * (Xl - Xj)
                #if (ji != l):
                #    prod = prod * (GF2int(1) - X[ji]*(Xl.inverse()))

            # Compute Yl
            Yl = Xl**t * omega.evaluate(Xl_inv) * Xl_inv * prod.inverse()

            Y.append(Yl)
        return Y


Instruction:
Can you generate the documentation for the following Python 3 function
def _forney(self, omega, X):
        '''Computes the error magnitudes. Works also with erasures and errors+erasures beyond the (n-k)//2 bound, here the bound is 2*e+v <= (n-k-1) with e the number of errors and v the number of erasures.'''
        # XXX Is floor division okay here? Should this be ceiling?

        Y = [] # the final result, the error/erasures polynomial (contain the values that we should minus on the received message to get the repaired message)
        Xlength = len(X)
        for l, Xl in enumerate(X):

            Xl_inv = Xl.inverse()

            # Compute the formal derivative of the error locator polynomial (see Blahut, Algebraic codes for data transmission, pp 196-197).
            # the formal derivative of the errata locator is used as the denominator of the Forney Algorithm, which simply says that the ith error value is given by error_evaluator(gf_inverse(Xi)) / error_locator_derivative(gf_inverse(Xi)). See Blahut, Algebraic codes for data transmission, pp 196-197.
            sigma_prime_tmp = [1 - Xl_inv * X[j] for j in _range(Xlength) if j != l] # TODO? maybe a faster way would be to precompute sigma_prime = sigma[len(sigma) & 1:len(sigma):2] and then just do sigma_prime.evaluate(X[j]) ? (like in reedsolo.py)
            # compute the product
            sigma_prime = 1
            for coef in sigma_prime_tmp:
                sigma_prime = sigma_prime * coef
            # equivalent to: sigma_prime = functools.reduce(mul, sigma_prime, 1)

            # Compute Yl
            # This is a more faithful translation of the theoretical equation contrary to the old forney method. Here it is exactly copy/pasted from the included presentation decoding_rs.pdf: Yl = omega(Xl.inverse()) / prod(1 - Xj*Xl.inverse()) for j in len(X) (in the paper it's for j in s, but it's useless when len(X) < s because we compute neutral terms 1 for nothing, and wrong when correcting more than s erasures or erasures+errors since it prevents computing all required terms).
            # Thus here this method works with erasures too because firstly we fixed the equation to be like the theoretical one (don't know why it was modified in _old_forney(), if it's an optimization, it doesn't enhance anything), and secondly because we removed the product bound on s, which prevented computing errors and erasures above the s=(n-k)//2 bound.
            # The best resource I have found for the correct equation is https://en.wikipedia.org/wiki/Forney_algorithm -- note that in the article, fcr is defined as c.
            Yl = - (Xl**(1-self.fcr)  * omega.evaluate(Xl_inv) / sigma_prime) # sigma_prime is the denominator of the Forney algorithm

            Y.append(Yl)
        return Y

Response: Compute the error magnitudes. Works also with erasures and errors + erasures beyond the 2 bound here the bound is 2 * e + v < = n - k


Instruction:
Explain what the following Python 3 code does
def update(self):
        try:
            p = Popen(['/bin/ps', '-p%s' % self.pid, '-o', 'rss,vsz'],
                      stdout=PIPE, stderr=PIPE)
        except OSError: # pragma: no cover
            pass
        else:
            s = p.communicate()[0].split()
            if p.returncode == 0 and len(s) >= 2: # pragma: no branch
                self.vsz = int(s[-1]) * 1024
                self.rss = int(s[-2]) * 1024
                return True
        return False

Response:
Update the virtual and resident size of the current process via ps. Returns True if it was
        successful.


Instruction:
How would you implement a function in Python 3 that
updates the internal state of the object.

Response:
def update(self):
        """
        Get virtual size of current process by reading the process' stat file.
        This should work for Linux.
        """
        try:
            stat = open('/proc/self/stat')
            status = open('/proc/self/status')
        except IOError: # pragma: no cover
            return False
        else:
            stats = stat.read().split()
            self.vsz = int( stats[22] )
            self.rss = int( stats[23] ) * self.pagesize
            self.pagefaults = int( stats[11] )

            for entry in status.readlines():
                key, value = entry.split(':')
                size_in_bytes = lambda x: int(x.split()[0]) * 1024
                if key == 'VmData':
                    self.data_segment = size_in_bytes(value)
                elif key == 'VmExe':
                    self.code_segment = size_in_bytes(value)
                elif key == 'VmLib':
                    self.shared_segment = size_in_bytes(value)
                elif key == 'VmStk':
                    self.stack_segment = size_in_bytes(value)
                key = self.key_map.get(key)
                if key:
                    self.os_specific.append((key, value.strip()))

            stat.close()
            status.close()
            return True


Instruction:
Here you have a function in Python 3, explain what it does
def CreateControls(self):
        wx.EVT_LIST_COL_CLICK(self, self.GetId(), self.OnReorder)
        wx.EVT_LIST_ITEM_SELECTED(self, self.GetId(), self.OnNodeSelected)
        wx.EVT_MOTION(self, self.OnMouseMove)
        wx.EVT_LIST_ITEM_ACTIVATED(self, self.GetId(), self.OnNodeActivated)
        self.CreateColumns()

Response: Create our sub - controls


Instruction:
Make a summary of the following Python 3 code
def CreateColumns( self ):
        self.SetItemCount(0)
        # clear any current columns...
        for i in range( self.GetColumnCount())[::-1]:
            self.DeleteColumn( i )
        # now create
        for i, column in enumerate(self.columns):
            column.index = i
            self.InsertColumn(i, column.name)
            if not windows or column.targetWidth is None:
                self.SetColumnWidth(i, wx.LIST_AUTOSIZE)
            else:
                self.SetColumnWidth(i, column.targetWidth)

Response: Create our column definitions from current self. columns


Instruction:
Can you create a Python 3 function that
sets the columns to a set of values other than the originals and recreates column controls

Response:
def SetColumns( self, columns, sortOrder=None ):
        """Set columns to a set of values other than the originals and recreates column controls"""
        self.columns = columns
        self.sortOrder = [(x.defaultOrder,x) for x in self.columns if x.sortDefault]
        self.CreateColumns()


Instruction:
Make a summary of the following Python 3 code
def OnNodeActivated(self, event):
        try:
            node = self.sorted[event.GetIndex()]
        except IndexError, err:
            log.warn(_('Invalid index in node activated: %(index)s'),
                     index=event.GetIndex())
        else:
            wx.PostEvent(
                self,
                squaremap.SquareActivationEvent(node=node, point=None,
                                                map=None)
            )

Response: Event handler for node activated event


Instruction:
Given the following Python 3 function, write the documentation
def OnNodeSelected(self, event):
        try:
            node = self.sorted[event.GetIndex()]
        except IndexError, err:
            log.warn(_('Invalid index in node selected: %(index)s'),
                     index=event.GetIndex())
        else:
            if node is not self.selected_node:
                wx.PostEvent(
                    self,
                    squaremap.SquareSelectionEvent(node=node, point=None,
                                                   map=None)
                )

Response: Event handler for node selection


Instruction:
Write a Python 3 script for
setting this node to indicated status

Response:
def SetIndicated(self, node):
        """Set this node to indicated status"""
        self.indicated_node = node
        self.indicated = self.NodeToIndex(node)
        self.Refresh(False)
        return self.indicated


Instruction:
How would you explain what the following Python 3 function does
def SetSelected(self, node):
        self.selected_node = node
        index = self.NodeToIndex(node)
        if index != -1:
            self.Focus(index)
            self.Select(index, True)
        return index

Response: Set our selected node


Instruction:
Write a Python 3 function that can
call when a new record is reordered

Response:
def OnReorder(self, event):
        """Given a request to reorder, tell us to reorder"""
        column = self.columns[event.GetColumn()]
        return self.ReorderByColumn( column )


Instruction:
How would you code a function in Python 3 to
reorder the set of records by a column.

Response:
def ReorderByColumn( self, column ):
        """Reorder the set of records by column"""
        # TODO: store current selection and re-select after sorting...
        single_column = self.SetNewOrder( column )
        self.reorder( single_column = True )
        self.Refresh()


Instruction:
Can you generate the documentation for the following Python 3 function
def SetNewOrder( self, column ):
        if column.sortOn:
            # multiple sorts for the click...
            columns = [self.columnByAttribute(attr) for attr in column.sortOn]
            diff = [(a, b) for a, b in zip(self.sortOrder, columns)
                    if b is not a[1]]
            if not diff:
                self.sortOrder[0] = (not self.sortOrder[0][0], column)
            else:
                self.sortOrder = [
                    (c.defaultOrder, c) for c in columns
                ] + [(a, b) for (a, b) in self.sortOrder if b not in columns]
            return False
        else:
            if column is self.sortOrder[0][1]:
                # reverse current major order
                self.sortOrder[0] = (not self.sortOrder[0][0], column)
            else:
                self.sortOrder = [(column.defaultOrder, column)] + [
                    (a, b)
                    for (a, b) in self.sortOrder if b is not column
                ]
            return True

Response: Sets new sorting order based on column.


Instruction:
Given the following Python 3 function, write the documentation
def reorder(self, single_column=False):
        if single_column:
            columns = self.sortOrder[:1]
        else:
            columns = self.sortOrder
        for ascending,column in columns[::-1]:
            # Python 2.2+ guarantees stable sort, so sort by each column in reverse
            # order will order by the assigned columns
            self.sorted.sort( key=column.get, reverse=(not ascending))

Response: Force a reorder of the displayed items


Instruction:
Can you generate the documentation for the following Python 3 function
def integrateRecords(self, functions):
        self.SetItemCount(len(functions))
        self.sorted = functions[:]
        self.reorder()
        self.Refresh()

Response: Integrate records from the loader


Instruction:
Can you generate a brief explanation for the following Python 3 code
def OnGetItemAttr(self, item):
        if self.indicated > -1 and item == self.indicated:
            return self.indicated_attribute
        return None

Response: Called when the user has requested the attribute of the item.


Instruction:
Explain what the following Python 3 code does
def OnGetItemText(self, item, col):
        # TODO: need to format for rjust and the like...
        try:
            column = self.columns[col]
            value = column.get(self.sorted[item])
        except IndexError, err:
            return None
        else:
            if value is None:
                return u''
            if column.percentPossible and self.percentageView and self.total:
                value = value / float(self.total) * 100.00
            if column.format:
                try:
                    return column.format % (value,)
                except Exception, err:
                    log.warn('Column %s could not format %r value: %r',
                        column.name, type(value), value
                    )
                    value = column.get(self.sorted[item] )
                    if isinstance(value,(unicode,str)):
                        return value
                    return unicode(value)
            else:
                if isinstance(value,(unicode,str)):
                    return value
                return unicode(value)

Response: Retrieve text for the item and column respectively


Instruction:
Can you create a Python 3 function that
encodes the input data with reed - solomon error correction in 223 byte blocks and outputs each block along with 32 parity bytes to a new file by .

Response:
def encode(input, output_filename):
    """Encodes the input data with reed-solomon error correction in 223 byte
    blocks, and outputs each block along with 32 parity bytes to a new file by
    the given filename.

    input is a file-like object

    The outputted image will be in png format, and will be 255 by x pixels with
    one color channel. X is the number of 255 byte blocks from the input. Each
    block of data will be one row, therefore, the data can be recovered if no
    more than 16 pixels per row are altered.
    """
    coder = rs.RSCoder(255,223)

    output = []

    while True:
        block = input.read(223)
        if not block: break
        code = coder.encode_fast(block)
        output.append(code)
        sys.stderr.write(".")

    sys.stderr.write("\n")

    out = Image.new("L", (rowstride,len(output)))
    out.putdata("".join(output))
    out.save(output_filename)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def redirect(url, code=303):
    scriptname = request.environ.get('SCRIPT_NAME', '').rstrip('/') + '/'
    location = urljoin(request.url, urljoin(scriptname, url))
    raise HTTPResponse("", status=code, header=dict(Location=location))

Response: Abort execution and causes a 303 redirect


Instruction:
Here you have a function in Python 3, explain what it does
def parse_date(ims):
    try:
        ts = email.utils.parsedate_tz(ims)
        return time.mktime(ts[:8] + (0,)) - (ts[9] or 0) - time.timezone
    except (TypeError, ValueError, IndexError):
        return None

Response: Parse rfc1123 rfc850 and asctime timestamps and return UTC epoch.


Instruction:
How would you explain what the following Python 3 function does
def run(app=None, server=WSGIRefServer, host='127.0.0.1', port=8080,
        interval=1, reloader=False, **kargs):
    """ Runs bottle as a web server. """
    app = app if app else default_app()
    quiet = bool(kargs.get('quiet', False))
    # Instantiate server, if it is a class instead of an instance
    if isinstance(server, type):
        server = server(host=host, port=port, **kargs)
    if not isinstance(server, ServerAdapter):
        raise RuntimeError("Server must be a subclass of WSGIAdapter")
    if not quiet and isinstance(server, ServerAdapter): # pragma: no cover
        if not reloader or os.environ.get('BOTTLE_CHILD') == 'true':
            print("Bottle server starting up (using %s)..." % repr(server))
            print("Listening on http://%s:%d/" % (server.host, server.port))
            print("Use Ctrl-C to quit.")
            print()
        else:
            print("Bottle auto reloader starting up...")
    try:
        if reloader and interval:
            reloader_run(server, app, interval)
        else:
            server.run(app)
    except KeyboardInterrupt:
        if not quiet: # pragma: no cover
            print("Shutting Down...")

Response: Runs bottle as a web server.


Instruction:
Write a Python 3 function that can
render a template string.

Response:
def template(tpl, template_adapter=SimpleTemplate, **kwargs):
    '''
    Get a rendered template as a string iterator.
    You can use a name, a filename or a template string as first parameter.
    '''
    if tpl not in TEMPLATES or DEBUG:
        settings = kwargs.get('template_settings',{})
        lookup = kwargs.get('template_lookup', TEMPLATE_PATH)
        if isinstance(tpl, template_adapter):
            TEMPLATES[tpl] = tpl
            if settings: TEMPLATES[tpl].prepare(settings)
        elif "\n" in tpl or "{" in tpl or "%" in tpl or '$' in tpl:
            TEMPLATES[tpl] = template_adapter(source=tpl, lookup=lookup, settings=settings)
        else:
            TEMPLATES[tpl] = template_adapter(name=tpl, lookup=lookup, settings=settings)
    if not TEMPLATES[tpl]:
        abort(500, 'Template (%s) not found' % tpl)
    kwargs['abort'] = abort
    kwargs['request'] = request
    kwargs['response'] = response
    return TEMPLATES[tpl].render(**kwargs)


Instruction:
Create a Python 3 function for
returning a list of ( type value ) tokens.

Response:
def tokens(self):
        """ Return a list of (type, value) tokens. """
        if not self._tokens:
            self._tokens = list(self.tokenise(self.route))
        return self._tokens


Instruction:
Make a summary of the following Python 3 code
def tokenise(cls, route):
        ''' Split a string into an iterator of (type, value) tokens. '''
        match = None
        for match in cls.syntax.finditer(route):
            pre, name, rex = match.groups()
            if pre: yield ('TXT', pre.replace('\\:',':'))
            if rex and name: yield ('VAR', (rex, name))
            elif name: yield ('VAR', (cls.default, name))
            elif rex: yield ('ANON', rex)
        if not match:
            yield ('TXT', route.replace('\\:',':'))
        elif match.end() < len(route):
            yield ('TXT', route[match.end():].replace('\\:',':'))

Response: Split a string into an iterator of ( type value ) tokens.


Instruction:
Implement a function in Python 3 to
return a regexp pattern with named groups

Response:
def group_re(self):
        ''' Return a regexp pattern with named groups '''
        out = ''
        for token, data in self.tokens():
            if   token == 'TXT':  out += re.escape(data)
            elif token == 'VAR':  out += '(?P<%s>%s)' % (data[1], data[0])
            elif token == 'ANON': out += '(?:%s)' % data
        return out


Instruction:
Create a Python 3 function for
returning a format string with named fields.

Response:
def format_str(self):
        ''' Return a format string with named fields. '''
        if self.static:
            return self.route.replace('%','%%')
        out, i = '', 0
        for token, value in self.tokens():
            if token == 'TXT': out += value.replace('%','%%')
            elif token == 'ANON': out += '%%(anon%d)s' % i; i+=1
            elif token == 'VAR': out += '%%(%s)s' % value[1]
        return out


Instruction:
Write a Python 3 function that can
return true if the route contains dynamic parts

Response:
def is_dynamic(self):
        ''' Return true if the route contains dynamic parts '''
        if not self._static:
            for token, value in self.tokens():
                if token != 'TXT':
                    return True
        self._static = True
        return False


Instruction:
How would you code a function in Python 3 to
match an URL and returns a tuple of handler target groups

Response:
def match(self, uri):
        ''' Matches an URL and returns a (handler, target) tuple '''
        if uri in self.static:
            return self.static[uri], {}
        for combined, subroutes in self.dynamic:
            match = combined.match(uri)
            if not match: continue
            target, groups = subroutes[match.lastindex - 1]
            groups = groups.match(uri).groupdict() if groups else {}
            return target, groups
        return None, {}


Instruction:
Given the following Python 3 function, write the documentation
def build(self, route_name, **args):
        ''' Builds an URL out of a named route and some parameters.'''
        try:
            return self.named[route_name] % args
        except KeyError:
            raise RouteBuildError("No route found with name '%s'." % route_name)

Response: Builds an URL out of a named route and some parameters.


Instruction:
Write a Python 3 script for
registering a new output filter. Whenever bottle hits a handler output matching ftype func is applied to it.

Response:
def add_filter(self, ftype, func):
        ''' Register a new output filter. Whenever bottle hits a handler output
            matching `ftype`, `func` is applyed to it. '''
        if not isinstance(ftype, type):
            raise TypeError("Expected type object, got %s" % type(ftype))
        self.castfilter = [(t, f) for (t, f) in self.castfilter if t != ftype]
        self.castfilter.append((ftype, func))
        self.castfilter.sort()


Instruction:
How would you implement a function in Python 3 that
finds a callback bound to a path and a specific HTTP method.

Response:
def match_url(self, path, method='GET'):
        """ Find a callback bound to a path and a specific HTTP method.
            Return (callback, param) tuple or (None, {}).
            method: HEAD falls back to GET. HEAD and GET fall back to ALL.
        """
        path = path.strip().lstrip('/')
        handler, param = self.routes.match(method + ';' + path)
        if handler: return handler, param
        if method == 'HEAD':
            handler, param = self.routes.match('GET;' + path)
            if handler: return handler, param
        handler, param = self.routes.match('ANY;' + path)
        if handler: return handler, param
        return None, {}


Instruction:
Given the following Python 3 function, write the documentation
def get_url(self, routename, **kargs):
        return '/' + self.routes.build(routename, **kargs).split(';', 1)[1]

Response: Return a string that matches a named route


Instruction:
Create a Python 3 function for
binding a new WSGI enviroment and clear out all previously computed content.

Response:
def bind(self, environ, app=None):
        """ Bind a new WSGI enviroment and clear out all previously computed
            attributes.

            This is done automatically for the global `bottle.request`
            instance on every request.
        """
        if isinstance(environ, Request): # Recycle already parsed content
            for key in self.__dict__: #TODO: Test this
                setattr(self, key, getattr(environ, key))
            self.app = app
            return
        self._GET = self._POST = self._GETPOST = self._COOKIES = None
        self._body = self._header = None
        self.environ = environ
        self.app = app
        # These attributes are used anyway, so it is ok to compute them here
        self.path = '/' + environ.get('PATH_INFO', '/').lstrip('/')
        self.method = environ.get('REQUEST_METHOD', 'GET').upper()


Instruction:
Write a Python 3 script to
shift some levels of PATH_INFO into SCRIPT_NAME and return the moved part. count defaults to 1

Response:
def path_shift(self, count=1):
        ''' Shift some levels of PATH_INFO into SCRIPT_NAME and return the
            moved part. count defaults to 1'''
        #/a/b/  /c/d  --> 'a','b'  'c','d'
        if count == 0: return ''
        pathlist = self.path.strip('/').split('/')
        scriptlist = self.environ.get('SCRIPT_NAME','/').strip('/').split('/')
        if pathlist and pathlist[0] == '': pathlist = []
        if scriptlist and scriptlist[0] == '': scriptlist = []
        if count > 0 and count <= len(pathlist):
            moved = pathlist[:count]
            scriptlist = scriptlist + moved
            pathlist = pathlist[count:]
        elif count < 0 and count >= -len(scriptlist):
            moved = scriptlist[count:]
            pathlist = moved + pathlist
            scriptlist = scriptlist[:count]
        else:
            empty = 'SCRIPT_NAME' if count < 0 else 'PATH_INFO'
            raise AssertionError("Cannot shift. Nothing left from %s" % empty)
        self['PATH_INFO'] = self.path =  '/' + '/'.join(pathlist) \
                          + ('/' if self.path.endswith('/') and pathlist else '')
        self['SCRIPT_NAME'] = '/' + '/'.join(scriptlist)
        return '/'.join(moved)


Instruction:
Write a Python 3 function that can
return the full URL as requested by the client.

Response:
def url(self):
        """ Full URL as requested by the client (computed).

            This value is constructed out of different environment variables
            and includes scheme, host, port, scriptname, path and query string.
        """
        scheme = self.environ.get('wsgi.url_scheme', 'http')
        host   = self.environ.get('HTTP_X_FORWARDED_HOST', self.environ.get('HTTP_HOST', None))
        if not host:
            host = self.environ.get('SERVER_NAME')
            port = self.environ.get('SERVER_PORT', '80')
            if scheme + port not in ('https443', 'http80'):
                host += ':' + port
        parts = (scheme, host, urlquote(self.fullpath), self.query_string, '')
        return urlunsplit(parts)


Instruction:
Here you have a function in Python 3, explain what it does
def POST(self):
        if self._POST is None:
            save_env = dict() # Build a save environment for cgi
            for key in ('REQUEST_METHOD', 'CONTENT_TYPE', 'CONTENT_LENGTH'):
                if key in self.environ:
                    save_env[key] = self.environ[key]
            save_env['QUERY_STRING'] = '' # Without this, sys.argv is called!
            if TextIOWrapper:
                fb = TextIOWrapper(self.body, encoding='ISO-8859-1')
            else:
                fb = self.body
            data = cgi.FieldStorage(fp=fb, environ=save_env)
            self._POST = MultiDict()
            for item in data.list:
                self._POST[item.name] = item if item.filename else item.value
        return self._POST

Response: The HTTP POST body parsed into a MultiDict.


Instruction:
Make a summary of the following Python 3 code
def params(self):
        if self._GETPOST is None:
            self._GETPOST = MultiDict(self.GET)
            self._GETPOST.update(dict(self.POST))
        return self._GETPOST

Response: A combined MultiDict with POST and GET parameters.


Instruction:
Can you tell what is the following Python 3 function doing
def get_cookie(self, *args):
        value = self.COOKIES.get(*args)
        sec = self.app.config['securecookie.key']
        dec = cookie_decode(value, sec)
        return dec or value

Response: Return the ( decoded ) value of a cookie.


Instruction:
Explain what the following Python 3 code does
def copy(self):
        ''' Returns a copy of self '''
        copy = Response(self.app)
        copy.status = self.status
        copy.headers = self.headers.copy()
        copy.content_type = self.content_type
        return copy

Response: Returns a copy of self


Instruction:
How would you implement a function in Python 3 that
returns a wsgi conform list of header value pairs.

Response:
def wsgiheader(self):
        ''' Returns a wsgi conform list of header/value pairs. '''
        for c in list(self.COOKIES.values()):
            if c.OutputString() not in self.headers.getall('Set-Cookie'):
                self.headers.append('Set-Cookie', c.OutputString())
        return list(self.headers.iterallitems())


Instruction:
How would you explain what the following Python 3 function does
def set_cookie(self, key, value, **kargs):
        if not isinstance(value, str):
            sec = self.app.config['securecookie.key']
            value = cookie_encode(value, sec).decode('ascii') #2to3 hack
        self.COOKIES[key] = value
        for k, v in kargs.items():
            self.COOKIES[key][k.replace('_', '-')] = v

Response: Add a new cookie with various options.


Instruction:
How would you implement a function in Python 3 that
parses the source file and returns the AST of the source file.

Response:
def parse_source_file(file_name):
  """
  Parses the AST of Python file for lines containing
  references to the argparse module.

  returns the collection of ast objects found.

  Example client code:

    1. parser = ArgumentParser(desc="My help Message")
    2. parser.add_argument('filename', help="Name of the file to load")
    3. parser.add_argument('-f', '--format', help='Format of output \nOptions: ['md', 'html']
    4. args = parser.parse_args()

  Variables:
    * nodes 									Primary syntax tree object
    *	argparse_assignments   	The assignment of the ArgumentParser (line 1 in example code)
    * add_arg_assignments     Calls to add_argument() (lines 2-3 in example code)
    * parser_var_name					The instance variable of the ArgumentParser (line 1 in example code)
    * ast_source							The curated collection of all parser related nodes in the client code
  """

  nodes = ast.parse(_openfile(file_name))

  module_imports = get_nodes_by_instance_type(nodes, _ast.Import)
  specific_imports = get_nodes_by_instance_type(nodes, _ast.ImportFrom)

  assignment_objs = get_nodes_by_instance_type(nodes, _ast.Assign)
  call_objects = get_nodes_by_instance_type(nodes, _ast.Call)

  argparse_assignments = get_nodes_by_containing_attr(assignment_objs, 'ArgumentParser')
  add_arg_assignments  = get_nodes_by_containing_attr(call_objects, 'add_argument')
  parse_args_assignment = get_nodes_by_containing_attr(call_objects, 'parse_args')

  ast_argparse_source = chain(
    module_imports,
    specific_imports,
    argparse_assignments,
    add_arg_assignments
    # parse_args_assignment
  )
  return ast_argparse_source