signature:
def root ( self , scope , names ) :
    """Find root of identifier , from scope
 args :
 scope ( Scope ) : current scope
 names ( list ) : identifier name list ( , separated identifiers )
 returns :
 list"""

implementation:
parent = scope . scopename
if parent :
    parent = parent [ - 1 ]
    if parent . parsed :
        parsed_names = [ ]
        for name in names :
            ampersand_count = name . count ( '&' )
            if ampersand_count :
                filtered_parts = [ ]
                for part in parent . parsed :
                    if part and part [ 0 ] not in self . _subp :
                        filtered_parts . append ( part )
                permutations = list ( utility . permutations_with_replacement ( filtered_parts , ampersand_count ) )
                for permutation in permutations :
                    parsed = [ ]
                    for name_part in name :
                        if name_part == "&" :
                            parent_part = permutation . pop ( 0 )
                            if parsed and parsed [ - 1 ] . endswith ( ']' ) :
                                parsed . extend ( ' ' )
                            if parent_part [ - 1 ] == ' ' :
                                parent_part . pop ( )
                            parsed . extend ( parent_part )
                        else :
                            parsed . append ( name_part )
                    parsed_names . append ( parsed )
            else : # NOTE ( saschpe ) : Maybe this code can be expressed with permutations too ?
                for part in parent . parsed :
                    if part and part [ 0 ] not in self . _subp :
                        parsed = [ ]
                        if name [ 0 ] == "@media" :
                            parsed . extend ( name )
                        else :
                            parsed . extend ( part )
                            if part [ - 1 ] != ' ' :
                                parsed . append ( ' ' )
                            parsed . extend ( name )
                        parsed_names . append ( parsed )
                    else :
                        parsed_names . append ( name )
        return parsed_names
return names


signature:
def raw ( self , clean = False ) :
    """Raw identifier .
 args :
 clean ( bool ) : clean name
 returns :
 str"""

implementation:
if clean :
    return '' . join ( '' . join ( p ) for p in self . parsed ) . replace ( '?' , ' ' )
return '%' . join ( '%' . join ( p ) for p in self . parsed ) . strip ( ) . strip ( '%' )


signature:
def copy ( self ) :
    """Return copy of self
 Returns :
 Identifier object"""

implementation:
tokens = ( [ t for t in self . tokens ] if isinstance ( self . tokens , list ) else self . tokens )
return Identifier ( tokens , 0 )


signature:
def fmt ( self , fills ) :
    """Format identifier
 args :
 fills ( dict ) : replacements
 returns :
 str ( CSS )"""

implementation:
name = ',$$' . join ( '' . join ( p ) . strip ( ) for p in self . parsed )
name = re . sub ( '\?(.)\?' , '%(ws)s\\1%(ws)s' , name ) % fills
return name . replace ( '$$' , fills [ 'nl' ] ) . replace ( '  ' , ' ' )


signature:
def add_block ( self , block ) :
    """Add block element to scope
 Args :
 block ( Block ) : Block object"""

implementation:
self [ - 1 ] [ '__blocks__' ] . append ( block )
self [ - 1 ] [ '__names__' ] . append ( block . raw ( ) )


signature:
def remove_block ( self , block , index = "-1" ) :
    """Remove block element from scope
 Args :
 block ( Block ) : Block object"""

implementation:
self [ index ] [ "__blocks__" ] . remove ( block )
self [ index ] [ "__names__" ] . remove ( block . raw ( ) )


signature:
def add_mixin ( self , mixin ) :
    """Add mixin to scope
 Args :
 mixin ( Mixin ) : Mixin object"""

implementation:
raw = mixin . tokens [ 0 ] [ 0 ] . raw ( )
if raw in self . _mixins :
    self . _mixins [ raw ] . append ( mixin )
else :
    self . _mixins [ raw ] = [ mixin ]


signature:
def variables ( self , name ) :
    """Search for variable by name . Searches scope top down
 Args :
 name ( string ) : Search term
 Returns :
 Variable object OR False"""

implementation:
if isinstance ( name , tuple ) :
    name = name [ 0 ]
if name . startswith ( '@{' ) :
    name = '@' + name [ 2 : - 1 ]
i = len ( self )
while i >= 0 :
    i -= 1
    if name in self [ i ] [ '__variables__' ] :
        return self [ i ] [ '__variables__' ] [ name ]
return False


signature:
def mixins ( self , name ) :
    """Search mixins for name .
 Allow ' > ' to be ignored . ' . a . b ( ) ' = = ' . a > . b ( ) '
 Args :
 name ( string ) : Search term
 Returns :
 Mixin object list OR False"""

implementation:
m = self . _smixins ( name )
if m :
    return m
return self . _smixins ( name . replace ( '?>?' , ' ' ) )


signature:
def _smixins ( self , name ) :
    """Inner wrapper to search for mixins by name ."""

implementation: return ( self . _mixins [ name ] if name in self . _mixins else False )


signature:
def blocks ( self , name ) :
    """Search for defined blocks recursively .
 Allow ' > ' to be ignored . ' . a . b ' = = ' . a > . b '
 Args :
 name ( string ) : Search term
 Returns :
 Block object OR False"""

implementation:
b = self . _blocks ( name )
if b :
    return b
return self . _blocks ( name . replace ( '?>?' , ' ' ) )


signature:
def _blocks ( self , name ) :
    """Inner wrapper to search for blocks by name ."""

implementation:
i = len ( self )
while i >= 0 :
    i -= 1
    if name in self [ i ] [ '__names__' ] :
        for b in self [ i ] [ '__blocks__' ] :
            r = b . raw ( )
            if r and r == name :
                return b
    else :
        for b in self [ i ] [ '__blocks__' ] :
            r = b . raw ( )
            if r and name . startswith ( r ) :
                b = utility . blocksearch ( b , name )
                if b :
                    return b
return False


signature:
def update ( self , scope , at = 0 ) :
    """Update scope . Add another scope to this one .
 Args :
 scope ( Scope ) : Scope object
 Kwargs :
 at ( int ) : Level to update"""

implementation:
if hasattr ( scope , '_mixins' ) and not at :
    self . _mixins . update ( scope . _mixins )
self [ at ] [ '__variables__' ] . update ( scope [ at ] [ '__variables__' ] )
self [ at ] [ '__blocks__' ] . extend ( scope [ at ] [ '__blocks__' ] )
self [ at ] [ '__names__' ] . extend ( scope [ at ] [ '__names__' ] )


signature:
def swap ( self , name ) :
    """Swap variable name for variable value
 Args :
 name ( str ) : Variable name
 Returns :
 Variable value ( Mixed )"""

implementation:
if name . startswith ( '@@' ) :
    var = self . variables ( name [ 1 : ] )
    if var is False :
        raise SyntaxError ( 'Unknown variable %s' % name )
    name = '@' + utility . destring ( var . value [ 0 ] )
    var = self . variables ( name )
    if var is False :
        raise SyntaxError ( 'Unknown variable %s' % name )
elif name . startswith ( '@{' ) :
    var = self . variables ( '@' + name [ 2 : - 1 ] )
    if var is False :
        raise SyntaxError ( 'Unknown escaped variable %s' % name )
    if isinstance ( var . value [ 0 ] , string_types ) :
        var . value [ 0 ] = utility . destring ( var . value [ 0 ] )
else :
    var = self . variables ( name )
    if var is False :
        raise SyntaxError ( 'Unknown variable %s' % name )
return var . value


signature:
def process ( self , tokens , scope ) :
    """Process tokenslist , flattening and parsing it
 args :
 tokens ( list ) : tokenlist
 scope ( Scope ) : Current scope
 returns :
 list"""

implementation:
while True :
    tokens = list ( utility . flatten ( tokens ) )
    done = True
    if any ( t for t in tokens if hasattr ( t , 'parse' ) ) :
        tokens = [ t . parse ( scope ) if hasattr ( t , 'parse' ) else t for t in tokens ]
        done = False
    if any ( t for t in tokens if ( utility . is_variable ( t ) ) or str ( type ( t ) ) == "<class 'lesscpy.plib.variable.Variable'>" ) :
        tokens = self . replace_variables ( tokens , scope )
        done = False
    if done :
        break
return tokens


signature:
def replace_variables ( self , tokens , scope ) :
    """Replace variables in tokenlist
 args :
 tokens ( list ) : tokenlist
 scope ( Scope ) : Current scope
 returns :
 list"""

implementation:
list = [ ]
for t in tokens :
    if utility . is_variable ( t ) :
        list . append ( scope . swap ( t ) )
    elif str ( type ( t ) ) == "<class 'lesscpy.plib.variable.Variable'>" :
        list . append ( scope . swap ( t . name ) )
    else :
        list . append ( t )
return list


signature:
def parse ( self , scope ) :
    """Parse node
 args :
 scope ( Scope ) : current scope
 raises :
 SyntaxError
 returns :
 self"""

implementation:
if not self . parsed :
    if len ( self . tokens ) > 2 :
        property , style , _ = self . tokens
        self . important = True
    else :
        property , style = self . tokens
        self . important = False
    self . property = '' . join ( property )
    self . parsed = [ ]
    if style :
        style = self . preprocess ( style )
        self . parsed = self . process ( style , scope )
return self


signature:
def preprocess ( self , style ) :
    """Hackish preprocessing from font shorthand tags .
 Skips expression parse on certain tags .
 args :
 style ( list ) : .
 returns :
 list"""

implementation:
if self . property == 'font' :
    style = [ '' . join ( u . expression ( ) ) if hasattr ( u , 'expression' ) else u for u in style ]
else :
    style = [ ( u , ' ' ) if hasattr ( u , 'expression' ) else u for u in style ]
return style


signature:
def fmt ( self , fills ) :
    """Format node
 args :
 fills ( dict ) : replacements
 returns :
 str"""

implementation:
f = "%(tab)s%(property)s:%(ws)s%(style)s%(important)s;%(nl)s"
imp = ' !important' if self . important else ''
if fills [ 'nl' ] :
    self . parsed = [ ',%s' % fills [ 'ws' ] if p == ',' else p for p in self . parsed ]
style = '' . join ( [ p . fmt ( fills ) if hasattr ( p , 'fmt' ) else str ( p ) for p in self . parsed ] )
# IE cannot handle no space after url ( )
style = re . sub ( "(url\([^\)]*\))([^\s,])" , "\\1 \\2" , style )
fills . update ( { 'property' : self . property , 'style' : style . strip ( ) , 'important' : imp } )
return f % fills


implementation:
self . name , args , self . guards = self . tokens [ 0 ]
self . args = [ a for a in utility . flatten ( args ) if a ]
self . body = Block ( [ None , self . tokens [ 1 ] ] , 0 )
self . vars = list ( utility . flatten ( [ list ( v . values ( ) ) for v in [ s [ '__variables__' ] for s in scope ] ] ) )
return self


signature:
def parse_args ( self , args , scope ) :
    """Parse arguments to mixin . Add them to scope
 as variables . Sets upp special variable @ arguments
 as well .
 args :
 args ( list ) : arguments
 scope ( Scope ) : current scope
 raises :
 SyntaxError"""

implementation:
arguments = list ( zip ( args , [ ' ' ] * len ( args ) ) ) if args and args [ 0 ] else None
zl = itertools . zip_longest if sys . version_info [ 0 ] == 3 else itertools . izip_longest
if self . args :
    parsed = [ v if hasattr ( v , 'parse' ) else v for v in copy . copy ( self . args ) ]
    args = args if isinstance ( args , list ) else [ args ]
    vars = [ self . _parse_arg ( var , arg , scope ) for arg , var in zl ( [ a for a in args ] , parsed ) ]
    for var in vars :
        if var :
            var . parse ( scope )
    if not arguments :
        arguments = [ v . value for v in vars if v ]
if not arguments :
    arguments = ''
Variable ( [ '@arguments' , None , arguments ] ) . parse ( scope )


signature:
def _parse_arg ( self , var , arg , scope ) :
    """Parse a single argument to mixin .
 args :
 var ( Variable object ) : variable
 arg ( mixed ) : argument
 scope ( Scope object ) : current scope
 returns :
 Variable object or None"""

implementation:
if isinstance ( var , Variable ) : # kwarg
    if arg :
        if utility . is_variable ( arg [ 0 ] ) :
            tmp = scope . variables ( arg [ 0 ] )
            if not tmp :
                return None
            val = tmp . value
        else :
            val = arg
        var = Variable ( var . tokens [ : - 1 ] + [ val ] )
else : # arg
    if utility . is_variable ( var ) :
        if arg is None :
            raise SyntaxError ( 'Missing argument to mixin' )
        elif utility . is_variable ( arg [ 0 ] ) :
            tmp = scope . variables ( arg [ 0 ] )
            if not tmp :
                return None
            val = tmp . value
        else :
            val = arg
        var = Variable ( [ var , None , val ] )
    else :
        return None
return var


signature:
def parse_guards ( self , scope ) :
    """Parse guards on mixin .
 args :
 scope ( Scope ) : current scope
 raises :
 SyntaxError
 returns :
 bool ( passes guards )"""

implementation:
if self . guards :
    cor = True if ',' in self . guards else False
    for g in self . guards :
        if isinstance ( g , list ) :
            res = ( g [ 0 ] . parse ( scope ) if len ( g ) == 1 else Expression ( g ) . parse ( scope ) )
            if cor :
                if res :
                    return True
            elif not res :
                return False
return True


signature:
def call ( self , scope , args = [ ] ) :
    """Call mixin . Parses a copy of the mixins body
 in the current scope and returns it .
 args :
 scope ( Scope ) : current scope
 args ( list ) : arguments
 raises :
 SyntaxError
 returns :
 list or False"""

implementation:
ret = False
if args :
    args = [ [ a . parse ( scope ) if isinstance ( a , Expression ) else a for a in arg ] if arg else arg for arg in args ]
try :
    self . parse_args ( args , scope )
except SyntaxError :
    pass
else :
    if self . parse_guards ( scope ) :
        body = self . body . copy ( )
        ret = body . tokens [ 1 ]
        if ret :
            utility . rename ( ret , scope , Block )
return ret


signature:
def parse ( self , scope ) :
    """Parse function
 args :
 scope ( Scope ) : Scope object
 returns :
 self"""

implementation:
self . name , _ , self . value = self . tokens
if isinstance ( self . name , tuple ) :
    if len ( self . name ) > 1 :
        self . name , pad = self . name
        self . value . append ( pad )
    else :
        self . name = self . name [ 0 ]
scope . add_variable ( self )
return self


signature:
def parse ( self , scope ) :
    """Parse Node within scope .
 the functions ~ ( and e ( map to self . escape
 and % ( maps to self . sformat
 args :
 scope ( Scope ) : Current scope"""

implementation:
name = '' . join ( self . tokens [ 0 ] )
parsed = self . process ( self . tokens [ 1 : ] , scope )
if name == '%(' :
    name = 'sformat'
elif name in ( '~' , 'e' ) :
    name = 'escape'
color = Color . Color ( )
args = [ t for t in parsed if not isinstance ( t , string_types ) or t not in '(),' ]
if hasattr ( self , name ) :
    try :
        return getattr ( self , name ) ( * args )
    except ValueError :
        pass
if hasattr ( color , name ) :
    try :
        result = getattr ( color , name ) ( * args )
        try :
            return result + ' '
        except TypeError :
            return result
    except ValueError :
        pass
return name + '' . join ( [ p for p in parsed ] )


signature:
def sformat ( self , string , * args ) :
    """String format .
 args :
 string ( str ) : string to format
 args ( list ) : format options
 returns :
 str"""

implementation:
format = string
items = [ ]
m = re . findall ( '(%[asdA])' , format )
if m and not args :
    raise SyntaxError ( 'Not enough arguments...' )
i = 0
for n in m :
    v = { '%A' : urlquote , '%s' : utility . destring , } . get ( n , str ) ( args [ i ] )
    items . append ( v )
    i += 1
format = format . replace ( '%A' , '%s' )
format = format . replace ( '%d' , '%s' )
return format % tuple ( items )


signature:
def isnumber ( self , string , * args ) :
    """Is number
 args :
 string ( str ) : match
 returns :
 bool"""

implementation:
try :
    n , u = utility . analyze_number ( string )
except SyntaxError :
    return False
return True


signature:
def isurl ( self , string , * args ) :
    """Is url
 args :
 string ( str ) : match
 returns :
 bool"""


signature:
def isstring ( self , string , * args ) :
    """Is string
 args :
 string ( str ) : match
 returns :
 bool"""

implementation:
regex = re . compile ( r'\'[^\']*\'|"[^"]*"' )
return regex . match ( string )


signature:
def increment ( self , value , * args ) :
    """Increment function
 args :
 value ( str ) : target
 returns :
 str"""

implementation:
n , u = utility . analyze_number ( value )
return utility . with_unit ( n + 1 , u )


signature:
def add ( self , * args ) :
    """Add integers
 args :
 args ( list ) : target
 returns :
 str"""

implementation:
if ( len ( args ) <= 1 ) :
    return 0
return sum ( [ int ( v ) for v in args ] )


signature:
def round ( self , value , * args ) :
    """Round number
 args :
 value ( str ) : target
 returns :
 str"""

implementation:
n , u = utility . analyze_number ( value )
return utility . with_unit ( int ( utility . away_from_zero_round ( float ( n ) ) ) , u )


signature:
def ceil ( self , value , * args ) :
    """Ceil number
 args :
 value ( str ) : target
 returns :
 str"""

implementation:
n , u = utility . analyze_number ( value )
return utility . with_unit ( int ( math . ceil ( n ) ) , u )


signature:
def percentage ( self , value , * args ) :
    """Return percentage value
 args :
 value ( str ) : target
 returns :
 str"""

implementation:
n , u = utility . analyze_number ( value )
n = int ( n * 100.0 )
u = '%'
return utility . with_unit ( n , u )


signature:
def process ( self , expression ) :
    """Process color expression
 args :
 expression ( tuple ) : color expression
 returns :
 str"""

implementation:
a , o , b = expression
c1 = self . _hextorgb ( a )
c2 = self . _hextorgb ( b )
r = [ '#' ]
for i in range ( 3 ) :
    v = self . operate ( c1 [ i ] , c2 [ i ] , o )
    if v > 0xff :
        v = 0xff
    if v < 0 :
        v = 0
    r . append ( "%02x" % int ( v ) )
return '' . join ( r )


signature:
def operate ( self , left , right , operation ) :
    """Do operation on colors
 args :
 left ( str ) : left side
 right ( str ) : right side
 operation ( str ) : Operation
 returns :
 str"""

implementation:
operation = { '+' : operator . add , '-' : operator . sub , '*' : operator . mul , '/' : operator . truediv } . get ( operation )
return operation ( left , right )


signature:
def rgb ( self , * args ) :
    """Translate rgb ( . . . ) to color string
 raises :
 ValueError
 returns :
 str"""

implementation:
if len ( args ) == 4 :
    args = args [ : 3 ]
if len ( args ) == 3 :
    try :
        return self . _rgbatohex ( list ( map ( int , args ) ) )
    except ValueError :
        if all ( ( a for a in args if a [ - 1 ] == '%' and 100 >= int ( a [ : - 1 ] ) >= 0 ) ) :
            return self . _rgbatohex ( [ int ( a [ : - 1 ] ) * 255 / 100.0 for a in args ] )
raise ValueError ( 'Illegal color values' )


signature:
def rgba ( self , * args ) :
    """Translate rgba ( . . . ) to color string
 raises :
 ValueError
 returns :
 str"""

implementation:
if len ( args ) == 4 :
    try :
        falpha = float ( list ( args ) [ 3 ] )
        if falpha > 1 :
            args = args [ : 3 ]
        if falpha == 0 :
            values = self . _rgbatohex_raw ( list ( map ( int , args ) ) )
            return "rgba(%s)" % ',' . join ( [ str ( a ) for a in values ] )
        return self . _rgbatohex ( list ( map ( int , args ) ) )
    except ValueError :
        if all ( ( a for a in args if a [ - 1 ] == '%' and 100 >= int ( a [ : - 1 ] ) >= 0 ) ) :
            alpha = list ( args ) [ 3 ]
            if alpha [ - 1 ] == '%' and float ( alpha [ : - 1 ] ) == 0 :
                values = self . _rgbatohex_raw ( [ int ( a [ : - 1 ] ) * 255 / 100.0 for a in args ] )
                return "rgba(%s)" % ',' . join ( [ str ( a ) for a in values ] )
            return self . _rgbatohex ( [ int ( a [ : - 1 ] ) * 255 / 100.0 for a in args ] )
raise ValueError ( 'Illegal color values' )


signature:
def argb ( self , * args ) :
    """Translate argb ( . . . ) to color string
 Creates a hex representation of a color in # AARRGGBB format ( NOT
 # RRGGBBAA ! ) . This format is used in Internet Explorer , and . NET
 and Android development .
 raises :
 ValueError
 returns :
 str"""

implementation:
if len ( args ) == 1 and type ( args [ 0 ] ) is str :
    match = re . match ( r'rgba\((.*)\)' , args [ 0 ] )
    if match : # NOTE ( saschpe ) : Evil hack to cope with rgba ( . . , . . , . . , 0.5 ) passed through untransformed
        rgb = re . sub ( r'\s+' , '' , match . group ( 1 ) ) . split ( ',' )
    else :
        rgb = list ( self . _hextorgb ( args [ 0 ] ) )
else :
    rgb = list ( args )
if len ( rgb ) == 3 :
    return self . _rgbatohex ( [ 255 ] + list ( map ( int , rgb ) ) )
elif len ( rgb ) == 4 :
    rgb = [ rgb . pop ( ) ] + rgb
    # Move Alpha to front
    try :
        fval = float ( list ( rgb ) [ 0 ] )
        if fval > 1 :
            rgb = [ 255 ] + rgb [ 1 : ]
            # Clip invalid integer / float values
        elif 1 >= fval >= 0 :
            rgb = [ fval * 256 ] + rgb [ 1 : ]
            # Convert 0-1 to 0-255 range for _ rgbatohex
        else :
            rgb = [ 0 ] + rgb [ 1 : ]
            # Clip lower bound
        return self . _rgbatohex ( list ( map ( int , rgb ) ) )
    except ValueError :
        if all ( ( a for a in rgb if a [ - 1 ] == '%' and 100 >= int ( a [ : - 1 ] ) >= 0 ) ) :
            return self . _rgbatohex ( [ int ( a [ : - 1 ] ) * 255 / 100.0 for a in rgb ] )
raise ValueError ( 'Illegal color values' )


signature:
def hsl ( self , * args ) :
    """Translate hsl ( . . . ) to color string
 raises :
 ValueError
 returns :
 str"""

implementation:
if len ( args ) == 4 :
    return self . hsla ( * args )
elif len ( args ) == 3 :
    h , s , l = args
    rgb = colorsys . hls_to_rgb ( int ( h ) / 360.0 , utility . pc_or_float ( l ) , utility . pc_or_float ( s ) )
    color = ( utility . convergent_round ( c * 255 ) for c in rgb )
    return self . _rgbatohex ( color )
raise ValueError ( 'Illegal color values' )


signature:
def hsla ( self , * args ) :
    """Translate hsla ( . . . ) to color string
 raises :
 ValueError
 returns :
 str"""

implementation:
if len ( args ) == 4 :
    h , s , l , a = args
    rgb = colorsys . hls_to_rgb ( int ( h ) / 360.0 , utility . pc_or_float ( l ) , utility . pc_or_float ( s ) )
    color = [ float ( utility . convergent_round ( c * 255 ) ) for c in rgb ]
    color . append ( utility . pc_or_float ( a ) )
    return "rgba(%s,%s,%s,%s)" % tuple ( color )
raise ValueError ( 'Illegal color values' )


signature:
def hue ( self , color , * args ) :
    """Return the hue value of a color
 args :
 color ( str ) : color
 raises :
 ValueError
 returns :
 float"""

implementation:
if color :
    h , l , s = self . _hextohls ( color )
    return utility . convergent_round ( h * 360.0 , 3 )
raise ValueError ( 'Illegal color values' )


signature:
def saturation ( self , color , * args ) :
    """Return the saturation value of a color
 args :
 color ( str ) : color
 raises :
 ValueError
 returns :
 float"""

implementation:
if color :
    h , l , s = self . _hextohls ( color )
    return s * 100.0
raise ValueError ( 'Illegal color values' )


signature:
def lighten ( self , color , diff , * args ) :
    """Lighten a color
 args :
 color ( str ) : color
 diff ( str ) : percentage
 returns :
 str"""

implementation:
if color and diff :
    return self . _ophsl ( color , diff , 1 , operator . add )
raise ValueError ( 'Illegal color values' )


signature:
def darken ( self , color , diff , * args ) :
    """Darken a color
 args :
 color ( str ) : color
 diff ( str ) : percentage
 returns :
 str"""

implementation:
if color and diff :
    return self . _ophsl ( color , diff , 1 , operator . sub )
raise ValueError ( 'Illegal color values' )


signature:
def spin ( self , color , degree , * args ) :
    """Spin color by degree . ( Increase / decrease hue )
 args :
 color ( str ) : color
 degree ( str ) : percentage
 raises :
 ValueError
 returns :
 str"""

implementation:
if color and degree :
    if isinstance ( degree , string_types ) :
        degree = float ( degree . strip ( '%' ) )
    h , l , s = self . _hextohls ( color )
    h = ( ( h * 360.0 ) + degree ) % 360.0
    h = 360.0 + h if h < 0 else h
    rgb = colorsys . hls_to_rgb ( h / 360.0 , l , s )
    color = ( utility . convergent_round ( c * 255 ) for c in rgb )
    return self . _rgbatohex ( color )
raise ValueError ( 'Illegal color values' )


signature:
def mix ( self , color1 , color2 , weight = 50 , * args ) :
    """This algorithm factors in both the user - provided weight
 and the difference between the alpha values of the two colors
 to decide how to perform the weighted average of the two RGB values .
 It works by first normalizing both parameters to be within [ - 1 , 1 ] ,
 where 1 indicates " only use color1 " , - 1 indicates " only use color 0 " ,
 and all values in between indicated a proportionately weighted average .
 Once we have the normalized variables w and a ,
 we apply the formula ( w + a ) / ( 1 + w * a )
 to get the combined weight ( in [ - 1 , 1 ] ) of color1.
 This formula has two especially nice properties :
 * When either w or a are - 1 or 1 , the combined weight is also that number
 ( cases where w * a = = - 1 are undefined , and handled as a special case ) .
 * When a is 0 , the combined weight is w , and vice versa
 Finally , the weight of color1 is renormalized to be within [ 0 , 1]
 and the weight of color2 is given by 1 minus the weight of color1.
 Copyright ( c ) 2006-2009 Hampton Catlin , Nathan Weizenbaum , and Chris Eppstein
 http : / / sass - lang . com
 args :
 color1 ( str ) : first color
 color2 ( str ) : second color
 weight ( int / str ) : weight
 raises :
 ValueError
 returns :
 str"""

implementation:
if color1 and color2 :
    if isinstance ( weight , string_types ) :
        weight = float ( weight . strip ( '%' ) )
    weight = ( ( weight / 100.0 ) * 2 ) - 1
    rgb1 = self . _hextorgb ( color1 )
    rgb2 = self . _hextorgb ( color2 )
    alpha = 0
    w1 = ( ( ( weight if weight * alpha == - 1 else weight + alpha ) / ( 1 + weight * alpha ) ) + 1 )
    w1 = w1 / 2.0
    w2 = 1 - w1
    rgb = [ rgb1 [ 0 ] * w1 + rgb2 [ 0 ] * w2 , rgb1 [ 1 ] * w1 + rgb2 [ 1 ] * w2 , rgb1 [ 2 ] * w1 + rgb2 [ 2 ] * w2 , ]
    return self . _rgbatohex ( rgb )
raise ValueError ( 'Illegal color values' )


signature:
def fmt ( self , color ) :
    """Format CSS Hex color code .
 uppercase becomes lowercase , 3 digit codes expand to 6 digit .
 args :
 color ( str ) : color
 raises :
 ValueError
 returns :
 str"""

implementation:
if utility . is_color ( color ) :
    color = color . lower ( ) . strip ( '#' )
    if len ( color ) in [ 3 , 4 ] :
        color = '' . join ( [ c * 2 for c in color ] )
    return '#%s' % color
raise ValueError ( 'Cannot format non-color' )


signature:
def flatten ( lst ) :
    """Flatten list .
 Args :
 lst ( list ) : List to flatten
 Returns :
 generator"""

implementation:
for elm in lst :
    if isinstance ( elm , collections . Iterable ) and not isinstance ( elm , string_types ) :
        for sub in flatten ( elm ) :
            yield sub
    else :
        yield elm


signature:
def pairwise ( lst ) :
    """yield item i and item i + 1 in lst . e . g .
 ( lst [ 0 ] , lst [ 1 ] ) , ( lst [ 1 ] , lst [ 2 ] ) , . . . , ( lst [ - 1 ] , None )
 Args :
 lst ( list ) : List to process
 Returns :
 list"""

implementation:
if not lst :
    return
length = len ( lst )
for i in range ( length - 1 ) :
    yield lst [ i ] , lst [ i + 1 ]
yield lst [ - 1 ] , None


signature:
def rename ( blocks , scope , stype ) :
    """Rename all sub - blocks moved under another
 block . ( mixins )
 Args :
 lst ( list ) : block list
 scope ( object ) : Scope object"""

implementation:
for p in blocks :
    if isinstance ( p , stype ) :
        p . tokens [ 0 ] . parse ( scope )
        if p . tokens [ 1 ] :
            scope . push ( )
            scope . current = p . tokens [ 0 ]
            rename ( p . tokens [ 1 ] , scope , stype )
            scope . pop ( )


signature:
def blocksearch ( block , name ) :
    """Recursive search for name in block ( inner blocks )
 Args :
 name ( str ) : search term
 Returns :
 Block OR False"""

implementation:
if hasattr ( block , 'tokens' ) :
    for b in block . tokens [ 1 ] :
        b = ( b if hasattr ( b , 'raw' ) and b . raw ( ) == name else blocksearch ( b , name ) )
        if b :
            return b
return False


signature:
def reverse_guard ( lst ) :
    """Reverse guard expression . not
 ( @ a > 5 ) - > ( @ a = < 5)
 Args :
 lst ( list ) : Expression
 returns :
 list"""


signature:
def debug_print ( lst , lvl = 0 ) :
    """Print scope tree
 args :
 lst ( list ) : parse result
 lvl ( int ) : current nesting level"""

implementation:
pad = '' . join ( [ '\t.' ] * lvl )
t = type ( lst )
if t is list :
    for p in lst :
        debug_print ( p , lvl )
elif hasattr ( lst , 'tokens' ) :
    print ( pad , t )
    debug_print ( list ( flatten ( lst . tokens ) ) , lvl + 1 )


signature:
def analyze_number ( var , err = '' ) :
    """Analyse number for type and split from unit
 1px - > ( q , ' px ' )
 args :
 var ( str ) : number string
 kwargs :
 err ( str ) : Error message
 raises :
 SyntaxError
 returns :
 tuple"""

implementation:
n , u = split_unit ( var )
if not isinstance ( var , string_types ) :
    return ( var , u )
if is_color ( var ) :
    return ( var , 'color' )
if is_int ( n ) :
    n = int ( n )
elif is_float ( n ) :
    n = float ( n )
else :
    raise SyntaxError ( '%s ´%s´' % ( err , var ) )
return ( n , u )


signature:
def with_unit ( number , unit = None ) :
    """Return number with unit
 args :
 number ( mixed ) : Number
 unit ( str ) : Unit
 returns :
 str"""

implementation:
if isinstance ( number , tuple ) :
    number , unit = number
if number == 0 :
    return '0'
if unit :
    number = str ( number )
    if number . startswith ( '.' ) :
        number = '0' + number
    return "%s%s" % ( number , unit )
return number if isinstance ( number , string_types ) else str ( number )


signature:
def is_color ( value ) :
    """Is string CSS color
 args :
 value ( str ) : string
 returns :
 bool"""

implementation:
if not value or not isinstance ( value , string_types ) :
    return False
if value [ 0 ] == '#' and len ( value ) in [ 4 , 5 , 7 , 9 ] :
    try :
        int ( value [ 1 : ] , 16 )
        return True
    except ValueError :
        pass
return False


signature:
def is_variable ( value ) :
    """Check if string is LESS variable
 args :
 value ( str ) : string
 returns :
 bool"""

implementation:
if isinstance ( value , string_types ) :
    return ( value . startswith ( '@' ) or value . startswith ( '-@' ) )
elif isinstance ( value , tuple ) :
    value = '' . join ( value )
    return ( value . startswith ( '@' ) or value . startswith ( '-@' ) )
return False


signature:
def is_float ( value ) :
    """Is value float
 args :
 value ( str ) : string
 returns :
 bool"""

implementation:
if not is_int ( value ) :
    try :
        float ( str ( value ) )
        return True
    except ( ValueError , TypeError ) :
        pass
return False


signature:
def split_unit ( value ) :
    """Split a number from its unit
 1px - > ( q , ' px ' )
 Args :
 value ( str ) : input
 returns :
 tuple"""

implementation:
r = re . search ( '^(\-?[\d\.]+)(.*)$' , str ( value ) )
return r . groups ( ) if r else ( '' , '' )


signature:
def away_from_zero_round ( value , ndigits = 0 ) :
    """Round half - way away from zero .
 Python2 ' s round ( ) method ."""

implementation:
if sys . version_info [ 0 ] >= 3 :
    p = 10 ** ndigits
    return float ( math . floor ( ( value * p ) + math . copysign ( 0.5 , value ) ) ) / p
else :
    return round ( value , ndigits )


signature:
def convergent_round ( value , ndigits = 0 ) :
    """Convergent rounding .
 Round to neareas even , similar to Python3 ' s round ( ) method ."""

implementation:
if sys . version_info [ 0 ] < 3 :
    if value < 0.0 :
        return - convergent_round ( - value )
    epsilon = 0.0000001
    integral_part , _ = divmod ( value , 1 )
    if abs ( value - ( integral_part + 0.5 ) ) < epsilon :
        if integral_part % 2.0 < epsilon :
            return integral_part
        else :
            nearest_even = integral_part + 0.5
            return math . ceil ( nearest_even )
return round ( value , ndigits )


signature:
def pc_or_float ( s ) :
    """Utility function to process strings that contain either percentiles or floats
 args :
 str : s
 returns :
 float"""

implementation:
if isinstance ( s , string_types ) and '%' in s :
    return float ( s . strip ( '%' ) ) / 100.0
return float ( s )


signature:
def permutations_with_replacement ( iterable , r = None ) :
    """Return successive r length permutations of elements in the iterable .
 Similar to itertools . permutation but withouth repeated values filtering ."""

implementation:
pool = tuple ( iterable )
n = len ( pool )
r = n if r is None else r
for indices in itertools . product ( range ( n ) , repeat = r ) :
    yield list ( pool [ i ] for i in indices )


signature:
def parse ( self , scope ) :
    """Parse Node
 args :
 scope ( Scope ) : Scope object
 raises :
 SyntaxError
 returns :
 str"""

implementation:
assert ( len ( self . tokens ) == 3 )
expr = self . process ( self . tokens , scope )
A , O , B = [ e [ 0 ] if isinstance ( e , tuple ) else e for e in expr if str ( e ) . strip ( ) ]
try :
    a , ua = utility . analyze_number ( A , 'Illegal element in expression' )
    b , ub = utility . analyze_number ( B , 'Illegal element in expression' )
except SyntaxError :
    return ' ' . join ( [ str ( A ) , str ( O ) , str ( B ) ] )
if ( a is False or b is False ) :
    return ' ' . join ( [ str ( A ) , str ( O ) , str ( B ) ] )
if ua == 'color' or ub == 'color' :
    return color . Color ( ) . process ( ( A , O , B ) )
if a == 0 and O == '/' : # NOTE ( saschpe ) : The ugliest but valid CSS since sliced bread : ' font : 0/1 a ; '
    return '' . join ( [ str ( A ) , str ( O ) , str ( B ) , ' ' ] )
out = self . operate ( a , b , O )
if isinstance ( out , bool ) :
    return out
return self . with_units ( out , ua , ub )


signature:
def with_units ( self , val , ua , ub ) :
    """Return value with unit .
 args :
 val ( mixed ) : result
 ua ( str ) : 1st unit
 ub ( str ) : 2nd unit
 raises :
 SyntaxError
 returns :
 str"""

implementation:
if not val :
    return str ( val )
if ua or ub :
    if ua and ub :
        if ua == ub :
            return str ( val ) + ua
        else : # Nodejs version does not seem to mind mismatched
        # units within expressions . So we choose the first
        # as they do
        # raise SyntaxError ( " Error in expression % s ! = % s " % ( ua , ub ) )
            return str ( val ) + ua
    elif ua :
        return str ( val ) + ua
    elif ub :
        return str ( val ) + ub
return repr ( val )


signature:
def operate ( self , vala , valb , oper ) :
    """Perform operation
 args :
 vala ( mixed ) : 1st value
 valb ( mixed ) : 2nd value
 oper ( str ) : operation
 returns :
 mixed"""

implementation:
operation = { '+' : operator . add , '-' : operator . sub , '*' : operator . mul , '/' : operator . truediv , '=' : operator . eq , '>' : operator . gt , '<' : operator . lt , '>=' : operator . ge , '=<' : operator . le , } . get ( oper )
if operation is None :
    raise SyntaxError ( "Unknown operation %s" % oper )
ret = operation ( vala , valb )
if oper in '+-*/' and int ( ret ) == ret :
    ret = int ( ret )
return ret


signature:
def parse ( self , filename = None , file = None , debuglevel = 0 ) :
    """Parse file .
 kwargs :
 filename ( str ) : File to parse
 debuglevel ( int ) : Parser debuglevel"""

implementation:
self . scope . push ( )
if not file : # We use a path .
    file = filename
else : # We use a stream and try to extract the name from the stream .
    if hasattr ( file , 'name' ) :
        if filename is not None :
            raise AssertionError ( 'names of file and filename are in conflict' )
        filename = file . name
    else :
        filename = '(stream)'
self . target = filename
if self . verbose and not self . fail_with_exc :
    print ( 'Compiling target: %s' % filename , file = sys . stderr )
self . result = self . parser . parse ( file , lexer = self . lex , debug = debuglevel )
self . post_parse ( )
self . register . close ( )


signature:
def post_parse ( self ) :
    """Post parse cycle . nodejs version allows calls to mixins
 not yet defined or known to the parser . We defer all calls
 to mixins until after first cycle when all names are known ."""

implementation:
if self . result :
    out = [ ]
    for pu in self . result :
        try :
            out . append ( pu . parse ( self . scope ) )
        except SyntaxError as e :
            self . handle_error ( e , 0 )
    self . result = list ( utility . flatten ( out ) )


signature:
def p_unit_list ( self , p ) :
    """unit _ list : unit _ list unit
 | unit"""

implementation:
if isinstance ( p [ 1 ] , list ) :
    if len ( p ) >= 3 :
        if isinstance ( p [ 2 ] , list ) :
            p [ 1 ] . extend ( p [ 2 ] )
        else :
            p [ 1 ] . append ( p [ 2 ] )
else :
    p [ 1 ] = [ p [ 1 ] ]
p [ 0 ] = p [ 1 ]


signature:
def p_statement_aux ( self , p ) :
    """statement : css _ charset t _ ws css _ string t _ semicolon
 | css _ namespace t _ ws css _ string t _ semicolon"""

implementation:
p [ 0 ] = Statement ( list ( p ) [ 1 : ] , p . lineno ( 1 ) )
p [ 0 ] . parse ( None )


signature:
def p_statement_namespace ( self , p ) :
    """statement : css _ namespace t _ ws word css _ string t _ semicolon"""


signature:
def p_statement_import ( self , p ) :
    """import _ statement : css _ import t _ ws string t _ semicolon
 | css _ import t _ ws css _ string t _ semicolon
 | css _ import t _ ws css _ string media _ query _ list t _ semicolon
 | css _ import t _ ws fcall t _ semicolon
 | css _ import t _ ws fcall media _ query _ list t _ semicolon"""

implementation:
# import pdb ; pdb . set _ trace ( )
if self . importlvl > 8 :
    raise ImportError ( 'Recrusive import level too deep > 8 (circular import ?)' )
if isinstance ( p [ 3 ] , string_types ) :
    ipath = utility . destring ( p [ 3 ] )
elif isinstance ( p [ 3 ] , list ) :
    p [ 3 ] = Import ( p [ 3 ] , p . lineno ( 4 ) ) . parse ( self . scope )
    ipath = utility . destring ( p [ 3 ] )
elif isinstance ( p [ 3 ] , Call ) : # NOTE ( saschpe ) : Always in the form of ' url ( " . . . " ) ; ' , so parse it
# and retrieve the inner css _ string . This whole func is messy .
    p [ 3 ] = p [ 3 ] . parse ( self . scope )
    # Store it as string , Statement . fmt expects it .
    ipath = utility . destring ( p [ 3 ] [ 4 : - 1 ] )
fn , fe = os . path . splitext ( ipath )
if not fe or fe . lower ( ) == '.less' :
    try :
        cpath = os . path . dirname ( os . path . abspath ( self . target ) )
        if not fe :
            ipath += '.less'
        filename = "%s%s%s" % ( cpath , os . sep , ipath )
        if os . path . exists ( filename ) :
            recurse = LessParser ( importlvl = self . importlvl + 1 , verbose = self . verbose , scope = self . scope )
            recurse . parse ( filename = filename , debuglevel = 0 )
            p [ 0 ] = recurse . result
        else :
            err = "Cannot import '%s', file not found" % filename
            self . handle_error ( err , p . lineno ( 1 ) , 'W' )
            p [ 0 ] = None
    except ImportError as e :
        self . handle_error ( e , p )
else :
    p [ 0 ] = Statement ( list ( p ) [ 1 : ] , p . lineno ( 1 ) )
    p [ 0 ] . parse ( None )
sys . stdout . flush ( )


signature:
def p_block ( self , p ) :
    """block _ decl : block _ open declaration _ list brace _ close"""

implementation:
p [ 0 ] = Block ( list ( p ) [ 1 : - 1 ] , p . lineno ( 3 ) )
self . scope . pop ( )
self . scope . add_block ( p [ 0 ] )


signature:
def p_block_replace ( self , p ) :
    """block _ decl : identifier t _ semicolon"""

implementation:
m = p [ 1 ] . parse ( None )
block = self . scope . blocks ( m . raw ( ) )
if block :
    p [ 0 ] = block . copy_inner ( self . scope )
else : # fallback to mixin . Allow calls to mixins without parens
    p [ 0 ] = Deferred ( p [ 1 ] , None , p . lineno ( 2 ) )


signature:
def p_block_open ( self , p ) :
    """block _ open : identifier brace _ open"""

implementation:
try :
    p [ 1 ] . parse ( self . scope )
except SyntaxError :
    pass
p [ 0 ] = p [ 1 ]
self . scope . current = p [ 1 ]


signature:
def p_font_face_open ( self , p ) :
    """block _ open : css _ font _ face t _ ws brace _ open"""

implementation: p [ 0 ] = Identifier ( [ p [ 1 ] , p [ 2 ] ] ) . parse ( self . scope )


signature:
def p_mixin ( self , p ) :
    """mixin _ decl : open _ mixin declaration _ list brace _ close"""

implementation:
self . scope . add_mixin ( Mixin ( list ( p ) [ 1 : ] , p . lineno ( 3 ) ) . parse ( self . scope ) )
self . scope . pop ( )
p [ 0 ] = None


signature:
def p_open_mixin ( self , p ) :
    """open _ mixin : identifier t _ popen mixin _ args _ list t _ pclose brace _ open
 | identifier t _ popen mixin _ args _ list t _ pclose mixin _ guard brace _ open"""

implementation:
p [ 1 ] . parse ( self . scope )
self . scope . current = p [ 1 ]
p [ 0 ] = [ p [ 1 ] , p [ 3 ] ]
if len ( p ) > 6 :
    p [ 0 ] . append ( p [ 5 ] )
else :
    p [ 0 ] . append ( None )


signature:
def p_mixin_guard_cond_list_aux ( self , p ) :
    """mixin _ guard _ cond _ list : mixin _ guard _ cond _ list t _ comma mixin _ guard _ cond
 | mixin _ guard _ cond _ list less _ and mixin _ guard _ cond"""


signature:
def p_call_mixin ( self , p ) :
    """call _ mixin : identifier t _ popen mixin _ args _ list t _ pclose t _ semicolon"""

implementation:
p [ 1 ] . parse ( None )
p [ 0 ] = Deferred ( p [ 1 ] , p [ 3 ] , p . lineno ( 4 ) )


signature:
def p_declaration_list ( self , p ) :
    """declaration _ list : declaration _ list declaration
 | declaration
 | empty"""


signature:
def p_variable_decl ( self , p ) :
    """variable _ decl : variable t _ colon style _ list t _ semicolon"""

implementation:
p [ 0 ] = Variable ( list ( p ) [ 1 : - 1 ] , p . lineno ( 4 ) )
p [ 0 ] . parse ( self . scope )


signature:
def p_property_decl ( self , p ) :
    """property _ decl : prop _ open style _ list t _ semicolon
 | prop _ open style _ list css _ important t _ semicolon
 | prop _ open empty t _ semicolon"""

implementation:
l = len ( p )
p [ 0 ] = Property ( list ( p ) [ 1 : - 1 ] , p . lineno ( l - 1 ) )


signature:
def p_identifier_list_aux ( self , p ) :
    """identifier _ list : identifier _ list t _ comma identifier _ group"""


signature:
def p_identifier_group_op ( self , p ) :
    """identifier _ group : identifier _ group child _ selector ident _ parts
 | identifier _ group ' + ' ident _ parts
 | identifier _ group general _ sibling _ selector ident _ parts
 | identifier _ group ' * '"""


signature:
def p_ident_parts_aux ( self , p ) :
    """ident _ parts : ident _ parts ident _ part
 | ident _ parts filter _ group"""

implementation:
if isinstance ( p [ 2 ] , list ) :
    p [ 1 ] . extend ( p [ 2 ] )
else :
    p [ 1 ] . append ( p [ 2 ] )
p [ 0 ] = p [ 1 ]


signature:
def p_ident_parts ( self , p ) :
    """ident _ parts : ident _ part
 | selector
 | filter _ group"""

implementation:
if not isinstance ( p [ 1 ] , list ) :
    p [ 1 ] = [ p [ 1 ] ]
p [ 0 ] = p [ 1 ]


signature:
def p_media_query_value ( self , p ) :
    """media _ query _ value : number
 | variable
 | word
 | color
 | expression"""

implementation:
if utility . is_variable ( p [ 1 ] ) :
    var = self . scope . variables ( '' . join ( p [ 1 ] ) )
    if var :
        value = var . value [ 0 ]
        if hasattr ( value , 'parse' ) :
            p [ 1 ] = value . parse ( self . scope )
        else :
            p [ 1 ] = value
if isinstance ( p [ 1 ] , Expression ) :
    p [ 0 ] = p [ 1 ] . parse ( self . scope )
else :
    p [ 0 ] = p [ 1 ]


signature:
def p_color ( self , p ) :
    """color : css _ color
 | css _ color t _ ws"""

implementation:
try :
    p [ 0 ] = Color ( ) . fmt ( p [ 1 ] )
    if len ( p ) > 2 :
        p [ 0 ] = [ p [ 0 ] , p [ 2 ] ]
except ValueError :
    self . handle_error ( 'Illegal color value `%s`' % p [ 1 ] , p . lineno ( 1 ) , 'W' )
    p [ 0 ] = p [ 1 ]


signature:
def p_error ( self , t ) :
    """Internal error handler
 args :
 t ( Lex token ) : Error token"""

implementation:
if t :
    error_msg = "E: %s line: %d, Syntax Error, token: `%s`, `%s`" % ( self . target , t . lineno , t . type , t . value )
    self . register . register ( error_msg )
while True :
    t = self . lex . token ( )
    if not t or t . value == '}' :
        if len ( self . scope ) > 1 :
            self . scope . pop ( )
        break
self . parser . restart ( )
return t


signature:
def handle_error ( self , e , line , t = 'E' ) :
    """Custom error handler
 args :
 e ( Mixed ) : Exception or str
 line ( int ) : line number
 t ( str ) : Error type"""

implementation: self . register . register ( "%s: line: %d: %s\n" % ( t , line , e ) )


signature:
def parse ( self , scope ) :
    """Parse node
 args :
 scope ( Scope ) : current scope
 raises :
 SyntaxError
 returns :
 parsed"""

implementation:
if not self . parsed :
    self . parsed = '' . join ( self . process ( self . tokens , scope ) )
return self . parsed


signature:
def NextPage ( gh ) :
    """Checks if a GitHub call returned multiple pages of data .
 : param gh : GitHub ( ) instance
 : rtype : int
 : return : number of next page or 0 if no next page"""

implementation:
header = dict ( gh . getheaders ( ) )
if 'Link' in header :
    parts = header [ 'Link' ] . split ( ',' )
    for part in parts :
        subparts = part . split ( ';' )
        sub = subparts [ 1 ] . split ( '=' )
        if sub [ 0 ] . strip ( ) == 'rel' :
            if sub [ 1 ] == '"next"' :
                page = int ( re . match ( r'.*page=(\d+).*' , subparts [ 0 ] , re . IGNORECASE | re . DOTALL | re . UNICODE ) . groups ( ) [ 0 ] )
                return page
return 0


signature:
def fetch_github_token ( self ) :
    """Fetch GitHub token . First try to use variable provided
 by - - token option , otherwise try to fetch it from git config
 and last CHANGELOG _ GITHUB _ TOKEN env variable .
 : returns : Nothing"""

implementation:
if not self . options . token :
    try :
        for v in GH_CFG_VARS :
            cmd = [ 'git' , 'config' , '--get' , '{0}' . format ( v ) ]
            self . options . token = subprocess . Popen ( cmd , stdout = subprocess . PIPE ) . communicate ( ) [ 0 ] . strip ( )
            if self . options . token :
                break
    except ( subprocess . CalledProcessError , WindowsError ) :
        pass
if not self . options . token :
    self . options . token = os . environ . get ( CHANGELOG_GITHUB_TOKEN )
if not self . options . token :
    print ( NO_TOKEN_PROVIDED )


signature:
def get_all_tags ( self ) :
    """Fetch all tags for repository from Github .
 : return : tags in repository
 : rtype : list"""

implementation:
verbose = self . options . verbose
gh = self . github
user = self . options . user
repo = self . options . project
if verbose :
    print ( "Fetching tags..." )
tags = [ ]
page = 1
while page > 0 :
    if verbose > 2 :
        print ( "." , end = "" )
    rc , data = gh . repos [ user ] [ repo ] . tags . get ( page = page , per_page = PER_PAGE_NUMBER )
    if rc == 200 :
        tags . extend ( data )
    else :
        self . raise_GitHubError ( rc , data , gh . getheaders ( ) )
    page = NextPage ( gh )
if verbose > 2 :
    print ( "." )
if len ( tags ) == 0 :
    if not self . options . quiet :
        print ( "Warning: Can't find any tags in repo. Make sure, that " "you push tags to remote repo via 'git push --tags'" )
        exit ( )
if verbose > 1 :
    print ( "Found {} tag(s)" . format ( len ( tags ) ) )
return tags


signature:
def fetch_closed_issues_and_pr ( self ) :
    """This method fetches all closed issues and separate them to
 pull requests and pure issues ( pull request is kind of issue
 in term of GitHub ) .
 : rtype : list , list
 : return : issues , pull - requests"""

implementation:
verbose = self . options . verbose
gh = self . github
user = self . options . user
repo = self . options . project
if verbose :
    print ( "Fetching closed issues and pull requests..." )
data = [ ]
issues = [ ]
data = [ ]
page = 1
while page > 0 :
    if verbose > 2 :
        print ( "." , end = "" )
    rc , data = gh . repos [ user ] [ repo ] . issues . get ( page = page , per_page = PER_PAGE_NUMBER , state = 'closed' , filter = 'all' )
    if rc == 200 :
        issues . extend ( data )
    else :
        self . raise_GitHubError ( rc , data , gh . getheaders ( ) )
    if len ( issues ) >= self . options . max_issues :
        break
    page = NextPage ( gh )
self . first_issue = data [ - 1 ] if len ( data ) > 0 else [ ]
if verbose > 2 :
    print ( "." )
# separate arrays of issues and pull requests :
prs = [ ]
iss = [ ]
for i in issues :
    if "pull_request" in i :
        prs . append ( i )
    else :
        iss . append ( i )
if verbose > 1 :
    print ( "\treceived {} issues and  {} pull requests." . format ( len ( iss ) , len ( prs ) ) )
return iss , prs


signature:
def fetch_closed_pull_requests ( self ) :
    """Fetch all pull requests . We need them to detect " merged _ at " parameter
 : rtype : list
 : return : all pull requests"""

implementation:
pull_requests = [ ]
verbose = self . options . verbose
gh = self . github
user = self . options . user
repo = self . options . project
if verbose :
    print ( "Fetching closed pull requests..." )
page = 1
while page > 0 :
    if verbose > 2 :
        print ( "." , end = "" )
    if self . options . release_branch :
        rc , data = gh . repos [ user ] [ repo ] . pulls . get ( page = page , per_page = PER_PAGE_NUMBER , state = 'closed' , base = self . options . release_branch )
    else :
        rc , data = gh . repos [ user ] [ repo ] . pulls . get ( page = page , per_page = PER_PAGE_NUMBER , state = 'closed' , )
    if rc == 200 :
        pull_requests . extend ( data )
    else :
        self . raise_GitHubError ( rc , data , gh . getheaders ( ) )
    page = NextPage ( gh )
if verbose > 2 :
    print ( "." )
if verbose > 1 :
    print ( "\tfetched {} closed pull requests." . format ( len ( pull_requests ) ) )
return pull_requests


signature:
def fetch_repo_creation_date ( self ) :
    """Get the creation date of the repository from GitHub .
 : rtype : str , str
 : return : special tag name , creation date as ISO date string"""

implementation:
gh = self . github
user = self . options . user
repo = self . options . project
rc , data = gh . repos [ user ] [ repo ] . get ( )
if rc == 200 :
    return REPO_CREATED_TAG_NAME , data [ "created_at" ]
else :
    self . raise_GitHubError ( rc , data , gh . getheaders ( ) )
return None , None


signature:
def fetch_events_async ( self , issues , tag_name ) :
    """Fetch events for all issues and add them to self . events
 : param list issues : all issues
 : param str tag _ name : name of the tag to fetch events for
 : returns : Nothing"""

implementation:
if not issues :
    return issues
max_simultaneous_requests = self . options . max_simultaneous_requests
verbose = self . options . verbose
gh = self . github
user = self . options . user
repo = self . options . project
self . events_cnt = 0
if verbose :
    print ( "fetching events for {} {}... " . format ( len ( issues ) , tag_name ) )
def worker ( issue ) :
    page = 1
    issue [ 'events' ] = [ ]
    while page > 0 :
        rc , data = gh . repos [ user ] [ repo ] . issues [ issue [ 'number' ] ] . events . get ( page = page , per_page = PER_PAGE_NUMBER )
        if rc == 200 :
            issue [ 'events' ] . extend ( data )
            self . events_cnt += len ( data )
        else :
            self . raise_GitHubError ( rc , data , gh . getheaders ( ) )
        page = NextPage ( gh )
threads = [ ]
cnt = len ( issues )
for i in range ( 0 , ( cnt // max_simultaneous_requests ) + 1 ) :
    for j in range ( max_simultaneous_requests ) :
        idx = i * max_simultaneous_requests + j
        if idx == cnt :
            break
        t = threading . Thread ( target = worker , args = ( issues [ idx ] , ) )
        threads . append ( t )
        t . start ( )
        if verbose > 2 :
            print ( "." , end = "" )
            if not idx % PER_PAGE_NUMBER :
                print ( "" )
    for t in threads :
        t . join ( )
if verbose > 2 :
    print ( "." )


signature:
def fetch_date_of_tag ( self , tag ) :
    """Fetch time for tag from repository .
 : param dict tag : dictionary with tag information
 : rtype : str
 : return : time of specified tag as ISO date string"""

implementation:
if self . options . verbose > 1 :
    print ( "\tFetching date for tag {}" . format ( tag [ "name" ] ) )
gh = self . github
user = self . options . user
repo = self . options . project
rc , data = gh . repos [ user ] [ repo ] . git . commits [ tag [ "commit" ] [ "sha" ] ] . get ( )
if rc == 200 :
    return data [ "committer" ] [ "date" ]
self . raise_GitHubError ( rc , data , gh . getheaders ( ) )


signature:
def fetch_commit ( self , event ) :
    """Fetch commit data for specified event .
 : param dict event : dictionary with event information
 : rtype : dict
 : return : dictionary with commit data"""

implementation:
gh = self . github
user = self . options . user
repo = self . options . project
rc , data = gh . repos [ user ] [ repo ] . git . commits [ event [ "commit_id" ] ] . get ( )
if rc == 200 :
    return data
self . raise_GitHubError ( rc , data , gh . getheaders ( ) )


signature:
def run ( self ) :
    """The entry point of this script to generate change log
 ' ChangelogGeneratorError ' Is thrown when one
 of the specified tags was not found in list of tags ."""

implementation:
if not self . options . project or not self . options . user :
    print ( "Project and/or user missing. " "For help run:\n  pygcgen --help" )
    return
if not self . options . quiet :
    print ( "Generating changelog..." )
log = None
try :
    log = self . generator . compound_changelog ( )
except ChangelogGeneratorError as err :
    print ( "\n\033[91m\033[1m{}\x1b[0m" . format ( err . args [ 0 ] ) )
    exit ( 1 )
if not log :
    if not self . options . quiet :
        print ( "Empty changelog generated. {} not written." . format ( self . options . output ) )
    return
if self . options . no_overwrite :
    out = checkname ( self . options . output )
else :
    out = self . options . output
with codecs . open ( out , "w" , "utf-8" ) as fh :
    fh . write ( log )
if not self . options . quiet :
    print ( "Done!" )
    print ( "Generated changelog written to {}" . format ( out ) )


signature:
def parse_heading ( heading ) :
    """Parse a single heading and return a Hash
 The following heading structures are currently valid :
 - # # [ v1.0.2 ] ( https : / / github . com / zanui / chef - thumbor / tree / v1.0.1 ) ( 2015-03-24)
 - # # [ v1.0.2 ] ( https : / / github . com / zanui / chef - thumbor / tree / v1.0.1)
 - # # v1.0.2 ( 2015-03-24)
 - # # v1.0.2
 @ param [ String ] heading Heading from the ChangeLog File
 @ return [ Hash ] Returns a structured Hash with version , url and date"""

implementation:
heading_structures = [ r"^## \[(?P<version>.+?)\]\((?P<url>.+?)\)( \((?P<date>.+?)\))?$" , r"^## (?P<version>.+?)( \((?P<date>.+?)\))?$" , ]
captures = { "version" : None , "url" : None , "date" : None }
for regexp in heading_structures :
    matches = re . match ( regexp , heading )
    if matches :
        captures . update ( matches . groupdict ( ) )
        break
return captures


signature:
def parse ( data ) :
    """Parse the given ChangeLog data into a list of Hashes .
 @ param [ String ] data File data from the ChangeLog . md
 @ return [ Array < Hash > ] Parsed data , e . g . [ { ' version ' = > . . . , ' url ' = > . . . , ' date ' = > . . . , ' content ' = > . . . } , . . . ]"""

implementation:
sections = re . compile ( "^## .+$" , re . MULTILINE ) . split ( data )
headings = re . findall ( "^## .+?$" , data , re . MULTILINE )
sections . pop ( 0 )
parsed = [ ]
def func ( h , s ) :
    p = parse_heading ( h )
    p [ "content" ] = s
    parsed . append ( p )
list ( map ( func , headings , sections ) )
return parsed


signature:
def _signal_handler_map ( self ) :
    """Create the signal handler map
 create a dictionary with signal : handler mapping based on
 self . signal _ map
 : return : dict"""

implementation:
result = { }
for signum , handler in self . signal_map . items ( ) :
    result [ signum ] = self . _get_signal_handler ( handler )
return result


signature:
def open ( self ) :
    """Daemonize this process
 Do everything that is needed to become a Unix daemon .
 : return : None
 : raise : DaemonError"""

implementation:
if self . is_open :
    return
try :
    os . chdir ( self . working_directory )
    if self . chroot_directory :
        os . chroot ( self . chroot_directory )
    os . setgid ( self . gid )
    os . setuid ( self . uid )
    os . umask ( self . umask )
except OSError as err :
    raise DaemonError ( 'Setting up Environment failed: {0}' . format ( err ) )
if self . prevent_core :
    try :
        resource . setrlimit ( resource . RLIMIT_CORE , ( 0 , 0 ) )
    except Exception as err :
        raise DaemonError ( 'Could not disable core files: {0}' . format ( err ) )
if self . detach_process :
    try :
        if os . fork ( ) > 0 :
            os . _exit ( 0 )
    except OSError as err :
        raise DaemonError ( 'First fork failed: {0}' . format ( err ) )
    os . setsid ( )
    try :
        if os . fork ( ) > 0 :
            os . _exit ( 0 )
    except OSError as err :
        raise DaemonError ( 'Second fork failed: {0}' . format ( err ) )
for ( signal_number , handler ) in self . _signal_handler_map . items ( ) :
    signal . signal ( signal_number , handler )
close_filenos ( self . _files_preserve )
redirect_stream ( sys . stdin , self . stdin )
redirect_stream ( sys . stdout , self . stdout )
redirect_stream ( sys . stderr , self . stderr )
if self . pidfile :
    self . pidfile . acquire ( )
self . _is_open = True


signature:
def user_and_project_from_git ( self , options , arg0 = None , arg1 = None ) :
    """Detects user and project from git ."""

implementation:
user , project = self . user_project_from_option ( options , arg0 , arg1 )
if user and project :
    return user , project
try :
    remote = subprocess . check_output ( [ 'git' , 'config' , '--get' , 'remote.{0}.url' . format ( options . git_remote ) ] )
except subprocess . CalledProcessError :
    return None , None
except WindowsError :
    print ( "git binary not found." )
    exit ( 1 )
else :
    return self . user_project_from_remote ( remote )


signature:
def user_project_from_option ( options , arg0 , arg1 ) :
    """Try to find user and project name from git remote output
 @ param [ String ] output of git remote command
 @ return [ Array ] user and project"""

implementation:
site = options . github_site
if arg0 and not arg1 : # this match should parse strings such as
# " https : / / github . com / skywinder / Github - Changelog - Generator "
# or
# " skywinder / Github - Changelog - Generator "
# to user and project
    match = re . match ( "(?:.+{site}/)?(.+)/(.+)" . format ( site = site ) , arg0 )
    if not match :
        print ( "Can't detect user and name from first " "parameter: '{arg0}' -> exit'" . format ( arg0 = arg0 ) )
        exit ( 1 )
    return match . groups ( )
return None , None


signature:
def user_project_from_remote ( remote ) :
    """Try to find user and project name from git remote output
 @ param [ String ] output of git remote command
 @ return [ Array ] user and project"""

implementation:
# try to find repo in format :
# origingit @ github . com : skywinder / Github - Changelog - Generator . git ( fetch )
# git @ github . com : skywinder / Github - Changelog - Generator . git
regex1 = br".*(?:[:/])(?P<user>(-|\w|\.)*)/" br"(?P<project>(-|\w|\.)*)(\.git).*"
match = re . match ( regex1 , remote )
if match :
    return match . group ( "user" ) , match . group ( "project" )
# try to find repo in format :
# originhttps : / / github . com / skywinder / ChangelogMerger ( fetch )
# https : / / github . com / skywinder / ChangelogMerger
regex2 = r".*/((?:-|\w|\.)*)/((?:-|\w|\.)*).*"
match = re . match ( regex2 , remote )
if match :
    return match . group ( "user" ) , match . group ( "project" )
return None , None


signature:
def timestring_to_datetime ( timestring ) :
    """Convert an ISO formated date and time string to a datetime object .
 : param str timestring : String with date and time in ISO format .
 : rtype : datetime
 : return : datetime object"""

implementation:
with warnings . catch_warnings ( ) :
    warnings . filterwarnings ( "ignore" , category = UnicodeWarning )
    result = dateutil_parser ( timestring )
return result


signature:
def fetch_events_for_issues_and_pr ( self ) :
    """Fetch event for issues and pull requests
 @ return [ Array ] array of fetched issues"""

implementation:
# Async fetching events :
self . fetcher . fetch_events_async ( self . issues , "issues" )
self . fetcher . fetch_events_async ( self . pull_requests , "pull requests" )


signature:
def fetch_tags_dates ( self ) :
    """Async fetching of all tags dates ."""

implementation:
if self . options . verbose :
    print ( "Fetching dates for {} tags..." . format ( len ( self . filtered_tags ) ) )
def worker ( tag ) :
    self . get_time_of_tag ( tag )
# Async fetching tags :
threads = [ ]
max_threads = 50
cnt = len ( self . filtered_tags )
for i in range ( 0 , ( cnt // max_threads ) + 1 ) :
    for j in range ( max_threads ) :
        idx = i * 50 + j
        if idx == cnt :
            break
        t = threading . Thread ( target = worker , args = ( self . filtered_tags [ idx ] , ) )
        threads . append ( t )
        t . start ( )
        if self . options . verbose > 2 :
            print ( "." , end = "" )
    for t in threads :
        t . join ( )
if self . options . verbose > 2 :
    print ( "." )
if self . options . verbose > 1 :
    print ( "Fetched dates for {} tags." . format ( len ( self . tag_times_dict ) ) )


signature:
def detect_actual_closed_dates ( self , issues , kind ) :
    """Find correct closed dates , if issues was closed by commits .
 : param list issues : issues to check
 : param str kind : either " issues " or " pull requests "
 : rtype : list
 : return : issues with updated closed dates"""

implementation:
if self . options . verbose :
    print ( "Fetching closed dates for {} {}..." . format ( len ( issues ) , kind ) )
all_issues = copy . deepcopy ( issues )
for issue in all_issues :
    if self . options . verbose > 2 :
        print ( "." , end = "" )
        if not issues . index ( issue ) % 30 :
            print ( "" )
    self . find_closed_date_by_commit ( issue )
    if not issue . get ( 'actual_date' , False ) :
        if issue . get ( 'closed_at' , False ) :
            print ( "Skipping closed non-merged issue: #{0} {1}" . format ( issue [ "number" ] , issue [ "title" ] ) )
        all_issues . remove ( issue )
if self . options . verbose > 2 :
    print ( "." )
return all_issues


signature:
def find_closed_date_by_commit ( self , issue ) :
    """Fill " actual _ date " parameter of specified issue by closed date of
 the commit , if it was closed by commit .
 : param dict issue : issue to edit"""

implementation:
if not issue . get ( 'events' ) :
    return
# if it ' s PR - > then find " merged event " , in case
# of usual issue - > find closed date
compare_string = "merged" if 'merged_at' in issue else "closed"
# reverse ! - to find latest closed event . ( event goes in date order )
# if it were reopened and closed again .
issue [ 'events' ] . reverse ( )
found_date = False
for event in issue [ 'events' ] :
    if event [ "event" ] == compare_string :
        self . set_date_from_event ( event , issue )
        found_date = True
        break
if not found_date : # TODO : assert issues , that remain without
# ' actual _ date ' hash for some reason .
    print ( "\nWARNING: Issue without 'actual_date':" " #{0} {1}" . format ( issue [ "number" ] , issue [ "title" ] ) )


signature:
def set_date_from_event ( self , event , issue ) :
    """Set closed date from this issue .
 : param dict event : event data
 : param dict issue : issue data"""

implementation:
if not event . get ( 'commit_id' , None ) :
    issue [ 'actual_date' ] = timestring_to_datetime ( issue [ 'closed_at' ] )
    return
try :
    commit = self . fetcher . fetch_commit ( event )
    issue [ 'actual_date' ] = timestring_to_datetime ( commit [ 'author' ] [ 'date' ] )
except ValueError :
    print ( "WARNING: Can't fetch commit {0}. " "It is probably referenced from another repo." . format ( event [ 'commit_id' ] ) )
    issue [ 'actual_date' ] = timestring_to_datetime ( issue [ 'closed_at' ] )


signature:
def encapsulate_string ( raw_string ) :
    """Encapsulate characters to make markdown look as expected .
 : param str raw _ string : string to encapsulate
 : rtype : str
 : return : encapsulated input string"""

implementation:
raw_string . replace ( '\\' , '\\\\' )
enc_string = re . sub ( "([<>*_()\[\]#])" , r"\\\1" , raw_string )
return enc_string


signature:
def compound_changelog ( self ) :
    """Main function to start change log generation
 : rtype : str
 : return : Generated change log file"""

implementation:
self . fetch_and_filter_tags ( )
tags_sorted = self . sort_tags_by_date ( self . filtered_tags )
self . filtered_tags = tags_sorted
self . fetch_and_filter_issues_and_pr ( )
log = str ( self . options . frontmatter ) if self . options . frontmatter else u""
log += u"{0}\n\n" . format ( self . options . header )
if self . options . unreleased_only :
    log += self . generate_unreleased_section ( )
else :
    log += self . generate_log_for_all_tags ( )
try :
    with open ( self . options . base ) as fh :
        log += fh . read ( )
except ( TypeError , IOError ) :
    pass
return log


signature:
def generate_sub_section ( self , issues , prefix ) :
    """Generate formated list of issues for changelog .
 : param list issues : Issues to put in sub - section .
 : param str prefix : Title of sub - section .
 : rtype : str
 : return : Generated ready - to - add sub - section ."""

implementation:
log = ""
if issues :
    if not self . options . simple_list :
        log += u"{0}\n\n" . format ( prefix )
    for issue in issues :
        merge_string = self . get_string_for_issue ( issue )
        log += u"- {0}\n" . format ( merge_string )
    log += "\n"
return log


signature:
def generate_header ( self , newer_tag_name , newer_tag_link , newer_tag_time , older_tag_link , project_url ) :
    """Generate a header for a tag section with specific parameters .
 : param str newer _ tag _ name : Name ( title ) of newer tag .
 : param str newer _ tag _ link : Tag name of newer tag , used for links .
 Could be same as * * newer _ tag _ name * * or some
 specific value , like ` HEAD ` .
 : param datetime newer _ tag _ time : Date and time when
 newer tag was created .
 : param str older _ tag _ link : Tag name of older tag , used for links .
 : param str project _ url : URL for current project .
 : rtype : str
 : return : Generated ready - to - add tag section ."""

implementation:
log = ""
# Generate date string :
# noinspection PyUnresolvedReferences
time_string = newer_tag_time . strftime ( self . options . date_format )
# Generate tag name and link
if self . options . release_url :
    release_url = self . options . release_url . format ( newer_tag_link )
else :
    release_url = u"{project_url}/tree/{newer_tag_link}" . format ( project_url = project_url , newer_tag_link = newer_tag_link )
if not self . options . unreleased_with_date and newer_tag_name == self . options . unreleased_label :
    log += u"## [{newer_tag_name}]({release_url})\n\n" . format ( newer_tag_name = newer_tag_name , release_url = release_url )
else :
    log += u"## [{newer_tag_name}]({release_url}) " u"({time_string})\n" . format ( newer_tag_name = newer_tag_name , release_url = release_url , time_string = time_string )
if self . options . compare_link and older_tag_link != REPO_CREATED_TAG_NAME : # Generate compare link
    log += u"[Full Changelog]"
    log += u"({project_url}/compare/{older_tag_link}" . format ( project_url = project_url , older_tag_link = older_tag_link , )
    log += u"...{newer_tag_link})\n\n" . format ( newer_tag_link = newer_tag_link )
return log


signature:
def generate_log_between_tags ( self , older_tag , newer_tag ) :
    """Generate log between 2 specified tags .
 : param dict older _ tag : All issues before this tag ' s date will be
 excluded . May be special value , if new tag is
 the first tag . ( Means * * older _ tag * * is when
 the repo was created . )
 : param dict newer _ tag : All issues after this tag ' s date will be
 excluded . May be title of unreleased section .
 : rtype : str
 : return : Generated ready - to - add tag section for newer tag ."""

implementation:
filtered_issues , filtered_pull_requests = self . filter_issues_for_tags ( newer_tag , older_tag )
older_tag_name = older_tag [ "name" ] if older_tag else self . detect_since_tag ( )
if not filtered_issues and not filtered_pull_requests : # do not generate an unreleased section if it would be empty
    return ""
return self . generate_log_for_tag ( filtered_pull_requests , filtered_issues , newer_tag , older_tag_name )


signature:
def filter_issues_for_tags ( self , newer_tag , older_tag ) :
    """Apply all filters to issues and pull requests .
 : param dict older _ tag : All issues before this tag ' s date will be
 excluded . May be special value , if new tag is
 the first tag . ( Means * * older _ tag * * is when
 the repo was created . )
 : param dict newer _ tag : All issues after this tag ' s date will be
 excluded . May be title of unreleased section .
 : rtype : list ( dict ) , list ( dict )
 : return : Filtered issues and pull requests ."""

implementation:
filtered_pull_requests = self . delete_by_time ( self . pull_requests , older_tag , newer_tag )
filtered_issues = self . delete_by_time ( self . issues , older_tag , newer_tag )
newer_tag_name = newer_tag [ "name" ] if newer_tag else None
if self . options . filter_issues_by_milestone : # delete excess irrelevant issues ( according milestones ) . Issue # 22.
    filtered_issues = self . filter_by_milestone ( filtered_issues , newer_tag_name , self . issues )
    filtered_pull_requests = self . filter_by_milestone ( filtered_pull_requests , newer_tag_name , self . pull_requests )
return filtered_issues , filtered_pull_requests


signature:
def generate_log_for_all_tags ( self ) :
    """The full cycle of generation for whole project .
 : rtype : str
 : return : The complete change log for released tags ."""

implementation:
if self . options . verbose :
    print ( "Generating log..." )
self . issues2 = copy . deepcopy ( self . issues )
log1 = ""
if self . options . with_unreleased :
    log1 = self . generate_unreleased_section ( )
log = ""
for index in range ( len ( self . filtered_tags ) - 1 ) :
    log += self . do_generate_log_for_all_tags_part1 ( log , index )
if self . options . tag_separator and log1 :
    log = log1 + self . options . tag_separator + log
else :
    log = log1 + log
if len ( self . filtered_tags ) != 0 :
    log += self . do_generate_log_for_all_tags_part2 ( log )
return log


signature:
def generate_unreleased_section ( self ) :
    """Generate log for unreleased closed issues .
 : rtype : str
 : return : Generated ready - to - add unreleased section ."""

implementation:
if not self . filtered_tags :
    return ""
now = datetime . datetime . utcnow ( )
now = now . replace ( tzinfo = dateutil . tz . tzutc ( ) )
head_tag = { "name" : self . options . unreleased_label }
self . tag_times_dict [ head_tag [ "name" ] ] = now
unreleased_log = self . generate_log_between_tags ( self . filtered_tags [ 0 ] , head_tag )
return unreleased_log


signature:
def get_string_for_issue ( self , issue ) :
    """Parse issue and generate single line formatted issue line .
 Example output :
 - Add coveralls integration [ \ # 223 ] ( https : / / github . com / skywinder / github - changelog - generator / pull / 223 ) ( [ skywinder ] ( https : / / github . com / skywinder ) )
 - Add coveralls integration [ \ # 223 ] ( https : / / github . com / skywinder / github - changelog - generator / pull / 223 ) ( @ skywinder )
 : param dict issue : Fetched issue from GitHub .
 : rtype : str
 : return : Markdown - formatted single issue ."""

implementation:
encapsulated_title = self . encapsulate_string ( issue [ 'title' ] )
try :
    title_with_number = u"{0} [\\#{1}]({2})" . format ( encapsulated_title , issue [ "number" ] , issue [ "html_url" ] )
except UnicodeEncodeError : # TODO : why did i add this ? Is it needed ?
    title_with_number = "ERROR ERROR ERROR: #{0} {1}" . format ( issue [ "number" ] , issue [ 'title' ] )
    print ( title_with_number , '\n' , issue [ "html_url" ] )
return self . issue_line_with_user ( title_with_number , issue )


signature:
def issue_line_with_user ( self , line , issue ) :
    """If option author is enabled , a link to the profile of the author
 of the pull reqest will be added to the issue line .
 : param str line : String containing a markdown - formatted single issue .
 : param dict issue : Fetched issue from GitHub .
 : rtype : str
 : return : Issue line with added author link ."""

implementation:
if not issue . get ( "pull_request" ) or not self . options . author :
    return line
if not issue . get ( "user" ) :
    line += u" (Null user)"
elif self . options . username_as_tag :
    line += u" (@{0})" . format ( issue [ "user" ] [ "login" ] )
else :
    line += u" ([{0}]({1}))" . format ( issue [ "user" ] [ "login" ] , issue [ "user" ] [ "html_url" ] )
return line


signature:
def generate_log_for_tag ( self , pull_requests , issues , newer_tag , older_tag_name ) :
    """Generates log for tag section with header and body .
 : param list ( dict ) pull _ requests : List of PR ' s in this tag section .
 : param list ( dict ) issues : List of issues in this tag section .
 : param dict newer _ tag : Github data of tag for this section .
 : param str older _ tag _ name : Older tag , used for the links .
 May be special value , if * * newer tag * * is
 the first tag . ( Means * * older _ tag * * is when
 the repo was created . )
 : rtype : str
 : return : Ready - to - add and parsed tag section ."""

implementation:
newer_tag_link , newer_tag_name , newer_tag_time = self . detect_link_tag_time ( newer_tag )
github_site = "https://github.com" or self . options . github_endpoint
project_url = "{0}/{1}/{2}" . format ( github_site , self . options . user , self . options . project )
log = self . generate_header ( newer_tag_name , newer_tag_link , newer_tag_time , older_tag_name , project_url )
if self . options . issues : # Generate issues :
    log += self . issues_to_log ( issues , pull_requests )
if self . options . include_pull_request : # Generate pull requests :
    log += self . generate_sub_section ( pull_requests , self . options . merge_prefix )
return log


signature:
def issues_to_log ( self , issues , pull_requests ) :
    """Generate ready - to - paste log from list of issues and pull requests .
 : param list ( dict ) issues : List of issues in this tag section .
 : param list ( dict ) pull _ requests : List of PR ' s in this tag section .
 : rtype : str
 : return : Generated log for issues and pull requests ."""

implementation:
log = ""
sections_a , issues_a = self . parse_by_sections ( issues , pull_requests )
for section , s_issues in sections_a . items ( ) :
    log += self . generate_sub_section ( s_issues , section )
log += self . generate_sub_section ( issues_a , self . options . issue_prefix )
return log


signature:
def parse_by_sections ( self , issues , pull_requests ) :
    """This method sort issues by types ( bugs , features , etc . or
 just closed issues ) by labels .
 : param list ( dict ) issues : List of issues in this tag section .
 : param list ( dict ) pull _ requests : List of PR ' s in this tag section .
 : rtype : dict ( list ( dict ) ) , list ( dict )
 : return : Issues and PR ' s sorted into sections ."""

implementation:
issues_a = [ ]
sections_a = OrderedDict ( )
if not self . options . sections :
    return [ sections_a , issues ]
for key in self . options . sections :
    sections_a . update ( { key : [ ] } )
self . parse_by_sections_for_issues ( issues , sections_a , issues_a )
self . parse_by_sections_for_pr ( pull_requests , sections_a )
return [ sections_a , issues_a ]


signature:
def exclude_issues_by_labels ( self , issues ) :
    """Delete all issues with labels from exclude - labels option .
 : param list ( dict ) issues : All issues for tag .
 : rtype : list ( dict )
 : return : Filtered issues ."""

implementation:
if not self . options . exclude_labels :
    return copy . deepcopy ( issues )
remove_issues = set ( )
exclude_labels = self . options . exclude_labels
include_issues = [ ]
for issue in issues :
    for label in issue [ "labels" ] :
        if label [ "name" ] in exclude_labels :
            remove_issues . add ( issue [ "number" ] )
            break
for issue in issues :
    if issue [ "number" ] not in remove_issues :
        include_issues . append ( issue )
return include_issues


signature:
def filter_by_milestone ( self , filtered_issues , tag_name , all_issues ) :
    """: param list ( dict ) filtered _ issues : Filtered issues .
 : param str tag _ name : Name ( title ) of tag .
 : param list ( dict ) all _ issues : All issues .
 : rtype : list ( dict )
 : return : Filtered issues according milestone ."""

implementation:
filtered_issues = self . remove_issues_in_milestones ( filtered_issues )
if tag_name : # add missed issues ( according milestones )
    issues_to_add = self . find_issues_to_add ( all_issues , tag_name )
    filtered_issues . extend ( issues_to_add )
return filtered_issues


signature:
def find_issues_to_add ( all_issues , tag_name ) :
    """Add all issues , that should be in that tag , according to milestone .
 : param list ( dict ) all _ issues : All issues .
 : param str tag _ name : Name ( title ) of tag .
 : rtype : List [ dict ]
 : return : Issues filtered by milestone ."""

implementation:
filtered = [ ]
for issue in all_issues :
    if issue . get ( "milestone" ) :
        if issue [ "milestone" ] [ "title" ] == tag_name :
            iss = copy . deepcopy ( issue )
            filtered . append ( iss )
return filtered


signature:
def remove_issues_in_milestones ( self , filtered_issues ) :
    """: param list ( dict ) filtered _ issues : Filtered issues .
 : rtype : list ( dict )
 : return : List with removed issues , that contain milestones with
 same name as a tag ."""

implementation:
for issue in filtered_issues : # leave issues without milestones
    if issue [ "milestone" ] : # check , that this milestone is in tag list :
        for tag in self . filtered_tags :
            if tag [ "name" ] == issue [ "milestone" ] [ "title" ] :
                filtered_issues . remove ( issue )
return filtered_issues


signature:
def delete_by_time ( self , issues , older_tag , newer_tag ) :
    """Filter issues that belong to specified tag range .
 : param list ( dict ) issues : Issues to filter .
 : param dict older _ tag : All issues before this tag ' s date will be
 excluded . May be special value , if * * newer _ tag * *
 is the first tag . ( Means * * older _ tag * * is when
 the repo was created . )
 : param dict newer _ tag : All issues after this tag ' s date will be
 excluded . May be title of unreleased section .
 : rtype : list ( dict )
 : return : Filtered issues ."""

implementation:
if not older_tag and not newer_tag : # in case if no tags are specified - return unchanged array
    return copy . deepcopy ( issues )
newer_tag_time = self . get_time_of_tag ( newer_tag )
older_tag_time = self . get_time_of_tag ( older_tag )
filtered = [ ]
for issue in issues :
    if issue . get ( 'actual_date' ) :
        rslt = older_tag_time < issue [ 'actual_date' ] <= newer_tag_time
        if rslt :
            filtered . append ( copy . deepcopy ( issue ) )
return filtered


signature:
def include_issues_by_labels ( self , all_issues ) :
    """Include issues with labels , specified in self . options . include _ labels .
 : param list ( dict ) all _ issues : All issues .
 : rtype : list ( dict )
 : return : Filtered issues ."""

implementation:
included_by_labels = self . filter_by_include_labels ( all_issues )
wo_labels = self . filter_wo_labels ( all_issues )
il = set ( [ f [ "number" ] for f in included_by_labels ] )
wl = set ( [ w [ "number" ] for w in wo_labels ] )
filtered_issues = [ ]
for issue in all_issues :
    if issue [ "number" ] in il or issue [ "number" ] in wl :
        filtered_issues . append ( issue )
return filtered_issues


signature:
def filter_wo_labels ( self , all_issues ) :
    """Filter all issues that don ' t have a label .
 : rtype : list ( dict )
 : return : Issues without labels ."""

implementation:
issues_wo_labels = [ ]
if not self . options . add_issues_wo_labels :
    for issue in all_issues :
        if not issue [ 'labels' ] :
            issues_wo_labels . append ( issue )
return issues_wo_labels


signature:
def filter_by_include_labels ( self , issues ) :
    """Filter issues to include only issues with labels
 specified in include _ labels .
 : param list ( dict ) issues : Pre - filtered issues .
 : rtype : list ( dict )
 : return : Filtered issues ."""

implementation:
if not self . options . include_labels :
    return copy . deepcopy ( issues )
filtered_issues = [ ]
include_labels = set ( self . options . include_labels )
for issue in issues :
    labels = [ label [ "name" ] for label in issue [ "labels" ] ]
    if include_labels . intersection ( labels ) :
        filtered_issues . append ( issue )
return filtered_issues


signature:
def filter_by_labels ( self , all_issues , kind ) :
    """Filter issues for include / exclude labels .
 : param list ( dict ) all _ issues : All issues .
 : param str kind : Either " issues " or " pull requests " .
 : rtype : list ( dict )
 : return : Filtered issues ."""

implementation:
filtered_issues = self . include_issues_by_labels ( all_issues )
filtered = self . exclude_issues_by_labels ( filtered_issues )
if self . options . verbose > 1 :
    print ( "\tremaining {}: {}" . format ( kind , len ( filtered ) ) )
return filtered


signature:
def get_filtered_pull_requests ( self , pull_requests ) :
    """This method fetches missing params for PR and filter them
 by specified options . It include add all PR ' s with labels
 from options . include _ labels and exclude all from
 options . exclude _ labels .
 : param list ( dict ) pull _ requests : All pull requests .
 : rtype : list ( dict )
 : return : Filtered pull requests ."""

implementation:
pull_requests = self . filter_by_labels ( pull_requests , "pull requests" )
pull_requests = self . filter_merged_pull_requests ( pull_requests )
if self . options . verbose > 1 :
    print ( "\tremaining pull requests: {}" . format ( len ( pull_requests ) ) )
return pull_requests


signature:
def filter_merged_pull_requests ( self , pull_requests ) :
    """This method filter only merged PR and fetch missing required
 attributes for pull requests . Using merged date is more correct
 than closed date .
 : param list ( dict ) pull _ requests : Pre - filtered pull requests .
 : rtype : list ( dict )
 : return :"""

implementation:
if self . options . verbose :
    print ( "Fetching merge date for pull requests..." )
closed_pull_requests = self . fetcher . fetch_closed_pull_requests ( )
if not pull_requests :
    return [ ]
pulls = copy . deepcopy ( pull_requests )
for pr in pulls :
    fetched_pr = None
    for fpr in closed_pull_requests :
        if fpr [ 'number' ] == pr [ 'number' ] :
            fetched_pr = fpr
    if fetched_pr :
        pr [ 'merged_at' ] = fetched_pr [ 'merged_at' ]
        closed_pull_requests . remove ( fetched_pr )
for pr in pulls :
    if not pr . get ( 'merged_at' ) :
        pulls . remove ( pr )
return pulls


signature:
def fetch_and_filter_tags ( self ) :
    """Fetch and filter tags , fetch dates and sort them in time order ."""

implementation:
self . all_tags = self . fetcher . get_all_tags ( )
self . filtered_tags = self . get_filtered_tags ( self . all_tags )
self . fetch_tags_dates ( )


signature:
def sort_tags_by_date ( self , tags ) :
    """Sort all tags by date .
 : param list ( dict ) tags : All tags .
 : rtype : list ( dict )
 : return : Sorted list of tags ."""

implementation:
if self . options . verbose :
    print ( "Sorting tags..." )
tags . sort ( key = lambda x : self . get_time_of_tag ( x ) )
tags . reverse ( )
return tags


signature:
def get_time_of_tag ( self , tag ) :
    """Get date and time for tag , fetching it if not already cached .
 : param dict tag : Tag to get the datetime for .
 : rtype : datetime
 : return : datetime for specified tag ."""

implementation:
if not tag :
    raise ChangelogGeneratorError ( "tag is nil" )
name_of_tag = tag [ "name" ]
time_for_name = self . tag_times_dict . get ( name_of_tag , None )
if time_for_name :
    return time_for_name
else :
    time_string = self . fetcher . fetch_date_of_tag ( tag )
    try :
        self . tag_times_dict [ name_of_tag ] = timestring_to_datetime ( time_string )
    except UnicodeWarning :
        print ( "ERROR ERROR:" , tag )
        self . tag_times_dict [ name_of_tag ] = timestring_to_datetime ( time_string )
    return self . tag_times_dict [ name_of_tag ]


signature:
def detect_link_tag_time ( self , tag ) :
    """Detect link , name and time for specified tag .
 : param dict tag : Tag data .
 : rtype : str , str , datetime
 : return : Link , name and time of the tag ."""

implementation:
# if tag is nil - set current time
newer_tag_time = self . get_time_of_tag ( tag ) if tag else datetime . datetime . now ( )
# if it ' s future release tag - set this value
if tag [ "name" ] == self . options . unreleased_label and self . options . future_release :
    newer_tag_name = self . options . future_release
    newer_tag_link = self . options . future_release
elif tag [ "name" ] is not self . options . unreleased_label : # put unreleased label if there is no name for the tag
    newer_tag_name = tag [ "name" ]
    newer_tag_link = newer_tag_name
else :
    newer_tag_name = self . options . unreleased_label
    newer_tag_link = "HEAD"
return [ newer_tag_link , newer_tag_name , newer_tag_time ]


signature:
def version_of_first_item ( self ) :
    """Try to detect the newest tag from self . options . base , otherwise
 return a special value indicating the creation of the repo .
 : rtype : str
 : return : Tag name to use as ' oldest ' tag . May be special value ,
 indicating the creation of the repo ."""

implementation:
try :
    sections = read_changelog ( self . options )
    return sections [ 0 ] [ "version" ]
except ( IOError , TypeError ) :
    return self . get_temp_tag_for_repo_creation ( )


signature:
def get_temp_tag_for_repo_creation ( self ) :
    """If not already cached , fetch the creation date of the repo , cache it
 and return the special value indicating the creation of the repo .
 : rtype : str
 : return : value indicating the creation"""

implementation:
tag_date = self . tag_times_dict . get ( REPO_CREATED_TAG_NAME , None )
if not tag_date :
    tag_name , tag_date = self . fetcher . fetch_repo_creation_date ( )
    self . tag_times_dict [ tag_name ] = timestring_to_datetime ( tag_date )
return REPO_CREATED_TAG_NAME


signature:
def get_filtered_tags ( self , all_tags ) :
    """Return tags after filtering tags in lists provided by
 option : - - between - tags & - - exclude - tags
 : param list ( dict ) all _ tags : All tags .
 : rtype : list ( dict )
 : return : Filtered tags ."""

implementation:
filtered_tags = self . filter_since_tag ( all_tags )
if self . options . between_tags :
    filtered_tags = self . filter_between_tags ( filtered_tags )
if self . options . due_tag :
    filtered_tags = self . filter_due_tag ( filtered_tags )
return self . filter_excluded_tags ( filtered_tags )


signature:
def filter_since_tag ( self , all_tags ) :
    """Filter tags according since _ tag option .
 : param list ( dict ) all _ tags : All tags .
 : rtype : list ( dict )
 : return : Filtered tags ."""

implementation:
tag = self . detect_since_tag ( )
if not tag or tag == REPO_CREATED_TAG_NAME :
    return copy . deepcopy ( all_tags )
filtered_tags = [ ]
tag_names = [ t [ "name" ] for t in all_tags ]
try :
    idx = tag_names . index ( tag )
except ValueError :
    self . warn_if_tag_not_found ( tag , "since-tag" )
    return copy . deepcopy ( all_tags )
since_tag = all_tags [ idx ]
since_date = self . get_time_of_tag ( since_tag )
for t in all_tags :
    tag_date = self . get_time_of_tag ( t )
    if since_date <= tag_date :
        filtered_tags . append ( t )
return filtered_tags


signature:
def filter_due_tag ( self , all_tags ) :
    """Filter tags according due _ tag option .
 : param list ( dict ) all _ tags : Pre - filtered tags .
 : rtype : list ( dict )
 : return : Filtered tags ."""

implementation:
filtered_tags = [ ]
tag = self . options . due_tag
tag_names = [ t [ "name" ] for t in all_tags ]
try :
    idx = tag_names . index ( tag )
except ValueError :
    self . warn_if_tag_not_found ( tag , "due-tag" )
    return copy . deepcopy ( all_tags )
due_tag = all_tags [ idx ]
due_date = self . get_time_of_tag ( due_tag )
for t in all_tags :
    tag_date = self . get_time_of_tag ( t )
    if tag_date <= due_date :
        filtered_tags . append ( t )
return filtered_tags


signature:
def filter_between_tags ( self , all_tags ) :
    """Filter tags according between _ tags option .
 : param list ( dict ) all _ tags : Pre - filtered tags .
 : rtype : list ( dict )
 : return : Filtered tags ."""

implementation:
tag_names = [ t [ "name" ] for t in all_tags ]
between_tags = [ ]
for tag in self . options . between_tags :
    try :
        idx = tag_names . index ( tag )
    except ValueError :
        raise ChangelogGeneratorError ( "ERROR: can't find tag {0}, specified with " "--between-tags option." . format ( tag ) )
    between_tags . append ( all_tags [ idx ] )
between_tags = self . sort_tags_by_date ( between_tags )
if len ( between_tags ) == 1 : # if option - - between - tags was only 1 tag given , duplicate it
# to generate the changelog only for that one tag .
    between_tags . append ( between_tags [ 0 ] )
older = self . get_time_of_tag ( between_tags [ 1 ] )
newer = self . get_time_of_tag ( between_tags [ 0 ] )
for tag in all_tags :
    if older < self . get_time_of_tag ( tag ) < newer :
        between_tags . append ( tag )
if older == newer :
    between_tags . pop ( 0 )
return between_tags


signature:
def filter_excluded_tags ( self , all_tags ) :
    """Filter tags according exclude _ tags and exclude _ tags _ regex option .
 : param list ( dict ) all _ tags : Pre - filtered tags .
 : rtype : list ( dict )
 : return : Filtered tags ."""

implementation:
filtered_tags = copy . deepcopy ( all_tags )
if self . options . exclude_tags :
    filtered_tags = self . apply_exclude_tags ( filtered_tags )
if self . options . exclude_tags_regex :
    filtered_tags = self . apply_exclude_tags_regex ( filtered_tags )
return filtered_tags


signature:
def apply_exclude_tags_regex ( self , all_tags ) :
    """Filter tags according exclude _ tags _ regex option .
 : param list ( dict ) all _ tags : Pre - filtered tags .
 : rtype : list ( dict )
 : return : Filtered tags ."""

implementation:
filtered = [ ]
for tag in all_tags :
    if not re . match ( self . options . exclude_tags_regex , tag [ "name" ] ) :
        filtered . append ( tag )
if len ( all_tags ) == len ( filtered ) :
    self . warn_if_nonmatching_regex ( )
return filtered


signature:
def apply_exclude_tags ( self , all_tags ) :
    """Filter tags according exclude _ tags option .
 : param list ( dict ) all _ tags : Pre - filtered tags .
 : rtype : list ( dict )
 : return : Filtered tags ."""

implementation:
filtered = copy . deepcopy ( all_tags )
for tag in all_tags :
    if tag [ "name" ] not in self . options . exclude_tags :
        self . warn_if_tag_not_found ( tag , "exclude-tags" )
    else :
        filtered . remove ( tag )
return filtered


signature:
def random_chars ( n ) :
    """Generate a random string from a - zA - Z0-9
 : param n : length of the string
 : return : the random string"""

implementation: return '' . join ( random . SystemRandom ( ) . choice ( string . ascii_letters + string . digits ) for _ in range ( n ) )


signature:
def random_letters ( n ) :
    """Generate a random string from a - zA - Z
 : param n : length of the string
 : return : the random string"""

implementation: return '' . join ( random . SystemRandom ( ) . choice ( string . ascii_letters ) for _ in range ( n ) )


signature:
def random_numbers ( n ) :
    """Generate a random string from 0-9
 : param n : length of the string
 : return : the random string"""

implementation: return '' . join ( random . SystemRandom ( ) . choice ( string . digits ) for _ in range ( n ) )


signature:
def dict_search ( d , k , v ) :
    """Search dictionary list by key and value
 : param d : dictionary list
 : param k : key
 : param v : value
 : return : the index of the first dictionary in the array with the specific key / value"""

implementation:
for i in range ( len ( d ) ) :
    if d [ i ] [ k ] == v :
        return i
return None


signature:
def dict_merge ( a , b , k ) :
    """Merge two dictionary lists
 : param a : original list
 : param b : alternative list , element will replace the one in original list with same key
 : param k : key
 : return : the merged list"""

implementation:
c = a . copy ( )
for j in range ( len ( b ) ) :
    flag = False
    for i in range ( len ( c ) ) :
        if c [ i ] [ k ] == b [ j ] [ k ] :
            c [ i ] = b [ j ] . copy ( )
            flag = True
    if not flag :
        c . append ( b [ j ] . copy ( ) )
return c


signature:
def dict_sort ( d , k ) :
    """Sort a dictionary list by key
 : param d : dictionary list
 : param k : key
 : return : sorted dictionary list"""

implementation: return sorted ( d . copy ( ) , key = lambda i : i [ k ] )


signature:
def dict_top ( d , k , n , reverse = False ) :
    """Return top n of a dictionary list sorted by key
 : param d : dictionary list
 : param k : key
 : param n : top n
 : param reverse : whether the value should be reversed
 : return : top n of the sorted dictionary list"""

implementation:
h = list ( )
for i in range ( len ( d ) ) :
    heappush ( h , ( - d [ i ] [ k ] if reverse else d [ i ] [ k ] , i ) )
r = list ( )
while len ( r ) < n and len ( h ) > 0 :
    _ , i = heappop ( h )
    r . append ( d [ i ] . copy ( ) )
return r


signature:
def dict_flatten ( d ) :
    """Replace nested dict keys to underscore - connected keys
 : param d : the dictionary
 : return : flattened dictionary"""

implementation:
if type ( d ) != dict :
    return d
else :
    dd = dict ( )
    for key , value in d . items ( ) :
        if type ( value ) == dict :
            for k , v in value . items ( ) :
                dd [ key + '_' + k ] = dict_flatten ( v )
        else :
            dd [ key ] = value
    return dd


signature:
def dict_format_type ( d , source , formatter , include_list = True ) :
    """Replace the values of a dict with certain type to other values
 : param d : the dictionary
 : param source : the source type , e . g . , int
 : param formatter : the formatter method , e . g . , return the string format of an int
 : param include _ list : whether list should be formatted , otherwise list will be considered as source type
 : return : formatted dictionary"""

implementation:
if not isinstance ( d , dict ) :
    if isinstance ( d , source ) :
        return formatter ( d )
    else :
        return d
else :
    dd = dict ( )
    for key , value in d . items ( ) :
        if include_list and isinstance ( value , list ) :
            dd [ key ] = [ dict_format_type ( i , source , formatter ) for i in value ]
        elif isinstance ( value , dict ) :
            dd [ key ] = dict_format_type ( value , source , formatter )
        elif isinstance ( value , source ) :
            dd [ key ] = formatter ( value )
        else :
            dd [ key ] = value
    return dd


signature:
def dict_remove_key ( d , k ) :
    """Recursively remove a key from a dict
 : param d : the dictionary
 : param k : key which should be removed
 : return : formatted dictionary"""

implementation:
dd = dict ( )
for key , value in d . items ( ) :
    if not key == k :
        if isinstance ( value , dict ) :
            dd [ key ] = dict_remove_key ( value , k )
        elif isinstance ( value , list ) :
            dd [ key ] = [ dict_remove_key ( i , k ) for i in value ]
        else :
            dd [ key ] = value
return dd


signature:
def dict_remove_value ( d , v ) :
    """Recursively remove keys with a certain value from a dict
 : param d : the dictionary
 : param v : value which should be removed
 : return : formatted dictionary"""

implementation:
dd = dict ( )
for key , value in d . items ( ) :
    if not value == v :
        if isinstance ( value , dict ) :
            dd [ key ] = dict_remove_value ( value , v )
        elif isinstance ( value , list ) :
            dd [ key ] = [ dict_remove_value ( i , v ) for i in value ]
        else :
            dd [ key ] = value
return dd


signature:
def dict_as_tuple_list ( d , as_list = False ) :
    """Format a dict to a list of tuples
 : param d : the dictionary
 : param as _ list : return a list of lists rather than a list of tuples
 : return : formatted dictionary list"""

implementation:
dd = list ( )
for k , v in d . items ( ) :
    dd . append ( [ k , v ] if as_list else ( k , v ) )
return dd


signature:
def tuple_search ( t , i , v ) :
    """Search tuple array by index and value
 : param t : tuple array
 : param i : index of the value in each tuple
 : param v : value
 : return : the first tuple in the array with the specific index / value"""

implementation:
for e in t :
    if e [ i ] == v :
        return e
return None