def deserialize_dataframe(reader, data_type_id):
    """
    Deserialize a dataframe.

    Parameters
    ----------
    reader : file
        File-like object to read from. Must be opened in binary mode.
    data_type_id : dict
        Serialization format of the raw data.
        See the azureml.DataTypeIds class for constants.

    Returns
    -------
    pandas.DataFrame
        Dataframe object.
    """
    _not_none('reader', reader)
    _not_none_or_empty('data_type_id', data_type_id)

    serializer = _SERIALIZERS.get(data_type_id)
    if serializer is None:
        raise UnsupportedDatasetTypeError(data_type_id)
    return serializer[1](reader=reader)

def deserialize_dataframe ( reader , data_type_id ) : _not_none ( 'reader' , reader ) _not_none_or_empty ( 'data_type_id' , data_type_id ) serializer = _SERIALIZERS . get ( data_type_id ) if serializer is None : raise UnsupportedDatasetTypeError ( data_type_id ) return serializer [ 1 ] ( reader = reader )


def _update_from_dataframe(self, dataframe, data_type_id=None, name=None,
                              description=None):
        """
        Serialize the specified DataFrame and replace the existing dataset.

        Parameters
        ----------
        dataframe : pandas.DataFrame
            Data to serialize.
        data_type_id : str, optional
            Format to serialize to.
            If None, the existing format is preserved.
            Supported formats are:
                'PlainText'
                'GenericCSV'
                'GenericTSV'
                'GenericCSVNoHeader'
                'GenericTSVNoHeader'
            See the azureml.DataTypeIds class for constants.
        name : str, optional
            Name for the dataset.
            If None, the name of the existing dataset is used.
        description : str, optional
            Description for the dataset.
            If None, the name of the existing dataset is used.
        """
        _not_none('dataframe', dataframe)

        if data_type_id is None:
            data_type_id = self.data_type_id
        if name is None:
            name = self.name
        if description is None:
            description = self.description

        try:
            output = BytesIO()
            serialize_dataframe(output, data_type_id, dataframe)
            raw_data = output.getvalue()
        finally:
            output.close()

        self._upload_and_refresh(raw_data, data_type_id, name, description)

def _update_from_dataframe ( self , dataframe , data_type_id = None , name = None , description = None ) : _not_none ( 'dataframe' , dataframe ) if data_type_id is None : data_type_id = self . data_type_id if name is None : name = self . name if description is None : description = self . description try : output = BytesIO ( ) serialize_dataframe ( output , data_type_id , dataframe ) raw_data = output . getvalue ( ) finally : output . close ( ) self . _upload_and_refresh ( raw_data , data_type_id , name , description )

Serialize the specified DataFrame and replace the existing dataset .


def _update_from_raw_data(self, raw_data, data_type_id=None, name=None,
                             description=None):
        """
        Upload already serialized raw data and replace the existing dataset.

        Parameters
        ----------
        raw_data: bytes
            Dataset contents to upload.
        data_type_id : str
            Serialization format of the raw data.
            If None, the format of the existing dataset is used.
            Supported formats are:
                'PlainText'
                'GenericCSV'
                'GenericTSV'
                'GenericCSVNoHeader'
                'GenericTSVNoHeader'
                'ARFF'
            See the azureml.DataTypeIds class for constants.
        name : str, optional
            Name for the dataset.
            If None, the name of the existing dataset is used.
        description : str, optional
            Description for the dataset.
            If None, the name of the existing dataset is used.
        """
        _not_none('raw_data', raw_data)

        if data_type_id is None:
            data_type_id = self.data_type_id
        if name is None:
            name = self.name
        if description is None:
            description = self.description

        self._upload_and_refresh(raw_data, data_type_id, name, description)

def _update_from_raw_data ( self , raw_data , data_type_id = None , name = None , description = None ) : _not_none ( 'raw_data' , raw_data ) if data_type_id is None : data_type_id = self . data_type_id if name is None : name = self . name if description is None : description = self . description self . _upload_and_refresh ( raw_data , data_type_id , name , description )

Upload already serialized raw data and replace the existing dataset .


def contents_url(self):
        """Full URL to the dataset contents."""
        loc = self.download_location
        return loc.base_uri + loc.location + loc.access_credential

def contents_url ( self ) : loc = self . download_location return loc . base_uri + loc . location + loc . access_credential


def add_from_dataframe(self, dataframe, data_type_id, name, description):
        """
        Serialize the specified DataFrame and upload it as a new dataset.

        Parameters
        ----------
        dataframe : pandas.DataFrame
            Data to serialize.
        data_type_id : str
            Format to serialize to.
            Supported formats are:
                'PlainText'
                'GenericCSV'
                'GenericTSV'
                'GenericCSVNoHeader'
                'GenericTSVNoHeader'
            See the azureml.DataTypeIds class for constants.
        name : str
            Name for the new dataset.
        description : str
            Description for the new dataset.

        Returns
        -------
        SourceDataset
            Dataset that was just created.
            Use open(), read_as_binary(), read_as_text() or to_dataframe() on
            the dataset object to get its contents as a stream, bytes, str or
            pandas DataFrame.
        """
        _not_none('dataframe', dataframe)
        _not_none_or_empty('data_type_id', data_type_id)
        _not_none_or_empty('name', name)
        _not_none_or_empty('description', description)

        try:
            output = BytesIO()
            serialize_dataframe(output, data_type_id, dataframe)
            raw_data = output.getvalue()
        finally:
            output.close()

        return self._upload(raw_data, data_type_id, name, description)

def add_from_dataframe ( self , dataframe , data_type_id , name , description ) : _not_none ( 'dataframe' , dataframe ) _not_none_or_empty ( 'data_type_id' , data_type_id ) _not_none_or_empty ( 'name' , name ) _not_none_or_empty ( 'description' , description ) try : output = BytesIO ( ) serialize_dataframe ( output , data_type_id , dataframe ) raw_data = output . getvalue ( ) finally : output . close ( ) return self . _upload ( raw_data , data_type_id , name , description )

Serialize the specified DataFrame and upload it as a new dataset .


def add_from_raw_data(self, raw_data, data_type_id, name, description):
        """
        Upload already serialized raw data as a new dataset.

        Parameters
        ----------
        raw_data: bytes
            Dataset contents to upload.
        data_type_id : str
            Serialization format of the raw data.
            Supported formats are:
                'PlainText'
                'GenericCSV'
                'GenericTSV'
                'GenericCSVNoHeader'
                'GenericTSVNoHeader'
                'ARFF'
            See the azureml.DataTypeIds class for constants.
        name : str
            Name for the new dataset.
        description : str
            Description for the new dataset.

        Returns
        -------
        SourceDataset
            Dataset that was just created.
            Use open(), read_as_binary(), read_as_text() or to_dataframe() on
            the dataset object to get its contents as a stream, bytes, str or
            pandas DataFrame.
        """
        _not_none('raw_data', raw_data)
        _not_none_or_empty('data_type_id', data_type_id)
        _not_none_or_empty('name', name)
        _not_none_or_empty('description', description)

        return self._upload(raw_data, data_type_id, name, description)

def add_from_raw_data ( self , raw_data , data_type_id , name , description ) : _not_none ( 'raw_data' , raw_data ) _not_none_or_empty ( 'data_type_id' , data_type_id ) _not_none_or_empty ( 'name' , name ) _not_none_or_empty ( 'description' , description ) return self . _upload ( raw_data , data_type_id , name , description )

Upload already serialized raw data as a new dataset .


def open(self):
        '''Open and return a stream for the dataset contents.'''
        return self.workspace._rest.open_intermediate_dataset_contents(
            self.workspace.workspace_id,
            self.experiment.experiment_id,
            self.node_id,
            self.port_name
        )

def open ( self ) : return self . workspace . _rest . open_intermediate_dataset_contents ( self . workspace . workspace_id , self . experiment . experiment_id , self . node_id , self . port_name )

Open and return a stream for the dataset contents .


def read_as_binary(self):
        '''Read and return the dataset contents as binary.'''
        return self.workspace._rest.read_intermediate_dataset_contents_binary(
            self.workspace.workspace_id,
            self.experiment.experiment_id,
            self.node_id,
            self.port_name
        )

Read and return the dataset contents as binary .


def read_as_text(self):
        '''Read and return the dataset contents as text.'''
        return self.workspace._rest.read_intermediate_dataset_contents_text(
            self.workspace.workspace_id,
            self.experiment.experiment_id,
            self.node_id,
            self.port_name
        )

def read_as_text ( self ) : return self . workspace . _rest . read_intermediate_dataset_contents_text ( self . workspace . workspace_id , self . experiment . experiment_id , self . node_id , self . port_name )

Read and return the dataset contents as text .


def _to_dataframe(self):
        """Read and return the dataset contents as a pandas DataFrame."""
        #TODO: figure out why passing in the opened stream directly gives invalid data
        data = self.read_as_binary()
        reader = BytesIO(data)
        return deserialize_dataframe(reader, self.data_type_id)

Read and return the dataset contents as a pandas DataFrame .


def get_intermediate_dataset(self, node_id, port_name, data_type_id):
        """
        Get an intermediate dataset.

        Parameters
        ----------
        node_id : str
            Module node id from the experiment graph.
        port_name : str
            Output port of the module.
        data_type_id : str
            Serialization format of the raw data.
            See the azureml.DataTypeIds class for constants.

        Returns
        -------
        IntermediateDataset
            Dataset object.
            Use open(), read_as_binary(), read_as_text() or to_dataframe() on
            the dataset object to get its contents as a stream, bytes, str or
            pandas DataFrame.
        """
        return IntermediateDataset(self.workspace, self, node_id, port_name, data_type_id)

def get_intermediate_dataset ( self , node_id , port_name , data_type_id ) : return IntermediateDataset ( self . workspace , self , node_id , port_name , data_type_id )


def get_experiments(self, workspace_id):
        """Runs HTTP GET request to retrieve the list of experiments."""
        api_path = self.EXPERIMENTS_URI_FMT.format(workspace_id)
        return self._send_get_req(api_path)

def get_experiments ( self , workspace_id ) : api_path = self . EXPERIMENTS_URI_FMT . format ( workspace_id ) return self . _send_get_req ( api_path )

Runs HTTP GET request to retrieve the list of experiments .


def get_datasets(self, workspace_id):
        """Runs HTTP GET request to retrieve the list of datasets."""
        api_path = self.DATASOURCES_URI_FMT.format(workspace_id)
        return self._send_get_req(api_path)

def get_datasets ( self , workspace_id ) : api_path = self . DATASOURCES_URI_FMT . format ( workspace_id ) return self . _send_get_req ( api_path )

Runs HTTP GET request to retrieve the list of datasets .


def get_dataset(self, workspace_id, dataset_id):
        """Runs HTTP GET request to retrieve a single dataset."""
        api_path = self.DATASOURCE_URI_FMT.format(workspace_id, dataset_id)
        return self._send_get_req(api_path)

def get_dataset ( self , workspace_id , dataset_id ) : api_path = self . DATASOURCE_URI_FMT . format ( workspace_id , dataset_id ) return self . _send_get_req ( api_path )

Runs HTTP GET request to retrieve a single dataset .


def publish(func_or_workspace_id, workspace_id_or_token = None, workspace_token_or_none = None, files=(), endpoint=None):
    '''publishes a callable function or decorates a function to be published.

Returns a callable, iterable object.  Calling the object will invoke the published service.
Iterating the object will give the API URL, API key, and API help url.

To define a function which will be published to Azure you can simply decorate it with
the @publish decorator.  This will publish the service, and then future calls to the
function will run against the operationalized version of the service in the cloud.

>>> @publish(workspace_id, workspace_token)
>>> def func(a, b):
>>>    return a + b

After publishing you can then invoke the function using:
func.service(1, 2)

Or continue to invoke the function locally:
func(1, 2)

You can also just call publish directly to publish a function:

>>> def func(a, b): return a + b
>>>
>>> res = publish(func, workspace_id, workspace_token)
>>>
>>> url, api_key, help_url = res
>>> res(2, 3)
5
>>> url, api_key, help_url = res.url, res.api_key, res.help_url

The returned result will be the published service.

You can specify a list of files which should be published along with the function.
The resulting files will be stored in a subdirectory called 'Script Bundle'.  The
list of files can be one of:
    (('file1.txt', None), )                      # file is read from disk
    (('file1.txt', b'contents'), )              # file contents are provided
    ('file1.txt', 'file2.txt')                  # files are read from disk, written with same filename
    ((('file1.txt', 'destname.txt'), None), )   # file is read from disk, written with different destination name

The various formats for each filename can be freely mixed and matched.
'''
    if not callable(func_or_workspace_id):
        def do_publish(func):
            func.service = _publish_worker(func, files, func_or_workspace_id, workspace_id_or_token, endpoint)
            return func
        return do_publish

    return _publish_worker(func_or_workspace_id, files, workspace_id_or_token, workspace_token_or_none, endpoint)

def publish ( func_or_workspace_id , workspace_id_or_token = None , workspace_token_or_none = None , files = ( ) , endpoint = None ) : if not callable ( func_or_workspace_id ) : def do_publish ( func ) : func . service = _publish_worker ( func , files , func_or_workspace_id , workspace_id_or_token , endpoint ) return func return do_publish return _publish_worker ( func_or_workspace_id , files , workspace_id_or_token , workspace_token_or_none , endpoint )

publishes a callable function or decorates a function to be published .


def service(url, api_key, help_url = None):
    '''Marks a function as having been published and causes all invocations to go to the remote
operationalized service.

>>> @service(url, api_key)
>>> def f(a, b):
>>>     pass
'''
    def do_publish(func):
        return published(url, api_key, help_url, func, None)
    return do_publish

def service ( url , api_key , help_url = None ) : def do_publish ( func ) : return published ( url , api_key , help_url , func , None ) return do_publish

Marks a function as having been published and causes all invocations to go to the remote operationalized service .


def types(**args):
    """Specifies the types used for the arguments of a published service.

@types(a=int, b = str)
def f(a, b):
    pass
"""
    def l(func):
        if hasattr(func, '__annotations__'):
            func.__annotations__.update(args)
        else:
            func.__annotations__ = args
        return func
    return l

def types ( * * args ) : def l ( func ) : if hasattr ( func , '__annotations__' ) : func . __annotations__ . update ( args ) else : func . __annotations__ = args return func return l

Specifies the types used for the arguments of a published service .


def returns(type):
    """Specifies the return type for a published service.

@returns(int)
def f(...):
    pass
"""
    def l(func):
        if hasattr(func, '__annotations__'):
            func.__annotations__['return'] = type
        else:
            func.__annotations__ = {'return': type}
        return func
    return l

def returns ( type ) : def l ( func ) : if hasattr ( func , '__annotations__' ) : func . __annotations__ [ 'return' ] = type else : func . __annotations__ = { 'return' : type } return func return l

Specifies the return type for a published service .


def attach(name, contents = None):
    """attaches a file to the payload to be uploaded.

If contents is omitted the file is read from disk.
If name is a tuple it specifies the on-disk filename and the destination filename.
"""
    def do_attach(func):
        if hasattr(func, '__attachments__'):
            func.__attachments__.append((name, contents))
        else:
            func.__attachments__ = [(name, contents)]
        return func
    return do_attach

def attach ( name , contents = None ) : def do_attach ( func ) : if hasattr ( func , '__attachments__' ) : func . __attachments__ . append ( ( name , contents ) ) else : func . __attachments__ = [ ( name , contents ) ] return func return do_attach

attaches a file to the payload to be uploaded .


def find_globals(code):
        """walks the byte code to find the variables which are actually globals"""
        cur_byte = 0
        byte_code = code.co_code

        names = set()
        while cur_byte < len(byte_code):
            op = ord(byte_code[cur_byte])

            if op >= dis.HAVE_ARGUMENT:
                if op == _LOAD_GLOBAL:
                    oparg = ord(byte_code[cur_byte + 1]) + (ord(byte_code[cur_byte + 2]) << 8)
                    name = code.co_names[oparg]
                    names.add(name)

                cur_byte += 2
            cur_byte += 1

        return names

def find_globals ( code ) : cur_byte = 0 byte_code = code . co_code names = set ( ) while cur_byte < len ( byte_code ) : op = ord ( byte_code [ cur_byte ] ) if op >= dis . HAVE_ARGUMENT : if op == _LOAD_GLOBAL : oparg = ord ( byte_code [ cur_byte + 1 ] ) + ( ord ( byte_code [ cur_byte + 2 ] ) << 8 ) name = code . co_names [ oparg ] names . add ( name ) cur_byte += 2 cur_byte += 1 return names


def copy(self):
        """Create a copy of this pen."""
        pen = Pen()
        pen.__dict__ = self.__dict__.copy()
        return pen

def copy ( self ) : pen = Pen ( ) pen . __dict__ = self . __dict__ . copy ( ) return pen


def lookup_color(c):
    """Return RGBA values of color c

    c should be either an X11 color or a brewer color set and index
    e.g. "navajowhite", "greens3/2"

    """
    import sys
    import gi
    gi.require_version('Gtk', '3.0')
    gi.require_version('PangoCairo', '1.0')

    from gi.repository import Gdk

    try:
        color = Gdk.color_parse(c)
    except ValueError:
        pass
    else:
        s = 1.0/65535.0
        r = color.red*s
        g = color.green*s
        b = color.blue*s
        a = 1.0
        return r, g, b, a

    try:
        dummy, scheme, index = c.split('/')
        r, g, b = brewer_colors[scheme][int(index)]
    except (ValueError, KeyError):
        pass
    else:
        s = 1.0/255.0
        r = r*s
        g = g*s
        b = b*s
        a = 1.0
        return r, g, b, a

    sys.stderr.write("warning: unknown color '%s'\n" % c)
    return None

def
lookup_color
(
c
)
:
import
sys
import
gi
gi
.
require_version
(
'Gtk'
,
'3.0'
)
gi
.
require_version
(
'PangoCairo'
,
'1.0'
)
from
gi
.
repository
import
Gdk
try
:
color
=
Gdk
.
color_parse
(
c
)
except
ValueError
:
pass
else
:
s
=
1.0
/
65535.0
r
=
color
.
red
*
s
g
=
color
.
green
*
s
b
=
color
.
blue
*
s
a
=
1.0
return
r
,
g
,
b
,
a
try
:
dummy
,
scheme
,
index
=
c
.
split
(
'/'
)
r
,
g
,
b
=
brewer_colors
[
scheme
]
[
int
(
index
)
]
except
(
ValueError
,
KeyError
)
:
pass
else
:
s
=
1.0
/
255.0
r
=
r
*
s
g
=
g
*
s
b
=
b
*
s
a
=
1.0
return
r
,
g
,
b
,
a
sys
.
stderr
.
write
(
"warning: unknown color '%s'\n"
%
c
)
return


def draw(self, cr, highlight=False, bounding=None):
        """Draw this shape with the given cairo context"""
        if bounding is None or self._intersects(bounding):
            self._draw(cr, highlight, bounding)

def draw ( self , cr , highlight = False , bounding = None ) : if bounding is None or self . _intersects ( bounding ) : self . _draw ( cr , highlight , bounding )


def _cubic_bernstein_extrema(p0, p1, p2, p3):
        """
        Find extremas of a function of real domain defined by evaluating
        a cubic bernstein polynomial of given bernstein coefficients.
        """
        # compute coefficients of derivative
        a = 3.*(p3-p0+3.*(p1-p2))
        b = 6.*(p0+p2-2.*p1)
        c = 3.*(p1-p0)

        if a == 0:
            if b == 0:
                return ()  # constant
            return (-c / b,)  # linear

        # quadratic
        # compute discriminant
        d = b*b - 4.*a*c
        if d < 0:
            return ()

        k = -2. * a
        if d == 0:
            return (b / k,)

        r = math.sqrt(d)
        return ((b + r) / k, (b - r) / k)

def
_cubic_bernstein_extrema
(
p0
,
p1
,
p2
,
p3
)
:
# compute coefficients of derivative
a
=
3.
*
(
p3
p0
+
3.
*
(
p1
p2
)
)
b
=
6.
*
(
p0
+
p2
2.
*
p1
)
c
=
3.
*
(
p1
p0
)
if
a
==
0
:
if
b
==
0
:
return
(
)
# constant
return
(
c
/
b
,
)
# linear
# quadratic
# compute discriminant
d
=
b
*
b
4.
*
a
*
c
if
d
<
0
:
return
(
)
k
=
2.
*
a
if
d
==
0
:
return
(
b
/
k
,
)
r
=
math
.
sqrt
(
d
)
return
(
(
b
+
r
)
/
k
,
(
b
r
)
/
k
)

Find extremas of a function of real domain defined by evaluating a cubic bernstein polynomial of given bernstein coefficients .


def _cubic_bernstein(p0, p1, p2, p3, t):
        """
        Evaluate polynomial of given bernstein coefficients
        using de Casteljau's algorithm.
        """
        u = 1 - t
        return p0*(u**3) + 3*t*u*(p1*u + p2*t) + p3*(t**3)

Evaluate polynomial of given bernstein coefficients using de Casteljau s algorithm .


def _build_choices(self):
        """Build choices list runtime using 'sitetree_tree' tag"""
        tree_token = u'sitetree_tree from "%s" template "%s"' % (self.tree, self.template)

        context_kwargs = {'current_app': 'admin'}
        context = template.Context(context_kwargs) if VERSION >= (1, 8) else template.Context(**context_kwargs)
        context.update({'request': object()})

        choices_str = sitetree_tree(
            Parser(None), Token(token_type=TOKEN_BLOCK, contents=tree_token)
        ).render(context)

        tree_choices = [(ITEMS_FIELD_ROOT_ID, self.root_title)]

        for line in choices_str.splitlines():
            if line.strip():
                splitted = line.split(':::')
                tree_choices.append((splitted[0], mark_safe(splitted[1])))

        return tree_choices

Build choices list runtime using sitetree_tree tag


def options_getter(command_options):
    """Compatibility function to get rid of optparse in management commands after Django 1.10.

    :param tuple command_options: tuple with `CommandOption` objects.

    """
    def get_options(option_func=None):
        from optparse import make_option
        from django.core.management.base import BaseCommand

        func = option_func or make_option

        options = tuple([func(*option.args, **option.kwargs) for option in command_options])

        if option_func is None:
            if VERSION < (1, 8):
                result = BaseCommand.option_list + options
            else:
                result = []

        else:
            result = options

        return result

    return get_options

def options_getter ( command_options ) : def get_options ( option_func = None ) : from optparse import make_option from django . core . management . base import BaseCommand func = option_func or make_option options = tuple ( [ func ( * option . args , * * option . kwargs ) for option in command_options ] ) if option_func is None : if VERSION < ( 1 , 8 ) : result = BaseCommand . option_list + options else : result = [ ] else : result = options return result return get_options

Compatibility function to get rid of optparse in management commands after Django 1 . 10 .


def register_items_hook(func):
    """Registers a hook callable to process tree items right before they are passed to templates.

    Callable should be able to:

        a) handle ``tree_items`` and ``tree_sender`` key params.
            ``tree_items`` will contain a list of extended TreeItem objects ready to pass to template.
            ``tree_sender`` will contain navigation type identifier
                (e.g.: `menu`, `sitetree`, `breadcrumbs`, `menu.children`, `sitetree.children`)

        b) return a list of extended TreeItems objects to pass to template.

    Example::

        # Put the following code somewhere where it'd be triggered as expected. E.g. in app view.py.

        # First import the register function.
        from sitetree.sitetreeapp import register_items_hook

        # The following function will be used as items processor.
        def my_items_processor(tree_items, tree_sender):
            # Suppose we want to process only menu child items.
            if tree_sender == 'menu.children':
                # Lets add 'Hooked: ' to resolved titles of every item.
                for item in tree_items:
                    item.title_resolved = 'Hooked: %s' % item.title_resolved
            # Return items list mutated or not.
            return tree_items

        # And we register items processor.
        register_items_hook(my_items_processor)

    :param func:
    """
    global _ITEMS_PROCESSOR
    global _ITEMS_PROCESSOR_ARGS_LEN

    _ITEMS_PROCESSOR = func

    if func:
        args_len = len(getargspec(func).args)
        if args_len not in {2, 3}:
            raise SiteTreeError('`register_items_hook()` expects a function with two or three arguments.')
        _ITEMS_PROCESSOR_ARGS_LEN = args_len

Registers a hook callable to process tree items right before they are passed to templates .


def compose_dynamic_tree(src, target_tree_alias=None, parent_tree_item_alias=None, include_trees=None):
    """Returns a structure describing a dynamic sitetree.utils
    The structure can be built from various sources,

    :param str|iterable src: If a string is passed to `src`, it'll be treated as the name of an app,
        from where one want to import sitetrees definitions. `src` can be an iterable
        of tree definitions (see `sitetree.toolbox.tree()` and `item()` functions).

    :param str|unicode target_tree_alias: Static tree alias to attach items from dynamic trees to.

    :param str|unicode parent_tree_item_alias: Tree item alias from a static tree to attach items from dynamic trees to.

    :param list include_trees: Sitetree aliases to filter `src`.

    :rtype: dict
    """
    def result(sitetrees=src):
        if include_trees is not None:
            sitetrees = [tree for tree in sitetrees if tree.alias in include_trees]

        return {
            'app': src,
            'sitetrees': sitetrees,
            'tree': target_tree_alias,
            'parent_item': parent_tree_item_alias}

    if isinstance(src, six.string_types):
        # Considered to be an application name.
        try:
            module = import_app_sitetree_module(src)
            return None if module is None else result(getattr(module, 'sitetrees', None))

        except ImportError as e:
            if settings.DEBUG:
                warnings.warn('Unable to register dynamic sitetree(s) for `%s` application: %s. ' % (src, e))
            return None

    return result()

Returns a structure describing a dynamic sitetree . utils The structure can be built from various sources


def init(self):
        """Initializes local cache from Django cache."""

        # Drop cache flag set by .reset() method.
        cache.get('sitetrees_reset') and self.empty(init=False)

        self.cache = cache.get(
            'sitetrees', {'sitetrees': {}, 'parents': {}, 'items_by_ids': {}, 'tree_aliases': {}})

Initializes local cache from Django cache .


def empty(self, **kwargs):
        """Empties cached sitetree data."""
        cache.delete('sitetrees')
        cache.delete('sitetrees_reset')

        kwargs.get('init', True) and self.init()

def empty ( self , * * kwargs ) : cache . delete ( 'sitetrees' ) cache . delete ( 'sitetrees_reset' ) kwargs . get ( 'init' , True ) and self . init ( )


def get_entry(self, entry_name, key):
        """Returns cache entry parameter value by its name.

        :param str|unicode entry_name:
        :param key:
        :return:
        """
        return self.cache[entry_name].get(key, False)

def get_entry ( self , entry_name , key ) : return self . cache [ entry_name ] . get ( key , False )

Returns cache entry parameter value by its name .


def update_entry_value(self, entry_name, key, value):
        """Updates cache entry parameter with new data.

        :param str|unicode entry_name:
        :param key:
        :param value:
        """
        if key not in self.cache[entry_name]:
            self.cache[entry_name][key] = {}

        self.cache[entry_name][key].update(value)

def update_entry_value ( self , entry_name , key , value ) : if key not in self . cache [ entry_name ] : self . cache [ entry_name ] [ key ] = { } self . cache [ entry_name ] [ key ] . update ( value )

Updates cache entry parameter with new data .


def set_entry(self, entry_name, key, value):
        """Replaces entire cache entry parameter data by its name with new data.

        :param str|unicode entry_name:
        :param key:
        :param value:
        """
        self.cache[entry_name][key] = value

def set_entry ( self , entry_name , key , value ) : self . cache [ entry_name ] [ key ] = value

Replaces entire cache entry parameter data by its name with new data .


def init(self, context):
        """Initializes sitetree to handle new request.

        :param Context|None context:
        """
        self.cache = Cache()
        self.current_page_context = context
        self.current_request = context.get('request', None) if context else None
        self.current_lang = get_language()

        self._current_app_is_admin = None
        self._current_user_permissions = _UNSET
        self._items_urls = {}  # Resolved urls are cache for a request.
        self._current_items = {}

Initializes sitetree to handle new request .


def resolve_tree_i18n_alias(self, alias):
        """Resolves internationalized tree alias.
        Verifies whether a separate sitetree is available for currently active language.
        If so, returns i18n alias. If not, returns the initial alias.

        :param str|unicode alias:
        :rtype: str|unicode
        """
        if alias not in _I18N_TREES:
            return alias

        current_language_code = self.current_lang
        i18n_tree_alias = '%s_%s' % (alias, current_language_code)
        trees_count = self.cache.get_entry('tree_aliases', i18n_tree_alias)

        if trees_count is False:
            trees_count = MODEL_TREE_CLASS.objects.filter(alias=i18n_tree_alias).count()
            self.cache.set_entry('tree_aliases', i18n_tree_alias, trees_count)

        if trees_count:
            alias = i18n_tree_alias

        return alias

def resolve_tree_i18n_alias ( self , alias ) : if alias not in _I18N_TREES : return alias current_language_code = self . current_lang i18n_tree_alias = '%s_%s' % ( alias , current_language_code ) trees_count = self . cache . get_entry ( 'tree_aliases' , i18n_tree_alias ) if trees_count is False : trees_count = MODEL_TREE_CLASS . objects . filter ( alias = i18n_tree_alias ) . count ( ) self . cache . set_entry ( 'tree_aliases' , i18n_tree_alias , trees_count ) if trees_count : alias = i18n_tree_alias return alias

Resolves internationalized tree alias . Verifies whether a separate sitetree is available for currently active language . If so returns i18n alias . If not returns the initial alias .


def current_app_is_admin(self):
        """Returns boolean whether current application is Admin contrib.

        :rtype: bool
        """
        is_admin = self._current_app_is_admin
        if is_admin is None:
            context = self.current_page_context

            current_app = getattr(
                # Try from request.resolver_match.app_name
                getattr(context.get('request', None), 'resolver_match', None), 'app_name',
                # Try from global context obj.
                getattr(context, 'current_app', None))

            if current_app is None:  # Try from global context dict.
                current_app = context.get('current_app', '')

            is_admin = current_app == ADMIN_APP_NAME
            self._current_app_is_admin = is_admin

        return is_admin

Returns boolean whether current application is Admin contrib .


def calculate_item_depth(self, tree_alias, item_id, depth=0):
        """Calculates depth of the item in the tree.

        :param str|unicode tree_alias:
        :param int item_id:
        :param int depth:
        :rtype: int
        """
        item = self.get_item_by_id(tree_alias, item_id)

        if hasattr(item, 'depth'):
            depth = item.depth + depth
        else:
            if item.parent is not None:
                depth = self.calculate_item_depth(tree_alias, item.parent.id, depth + 1)

        return depth

def calculate_item_depth ( self , tree_alias , item_id , depth = 0 ) : item = self . get_item_by_id ( tree_alias , item_id ) if hasattr ( item , 'depth' ) : depth = item . depth + depth else : if item . parent is not None : depth = self . calculate_item_depth ( tree_alias , item . parent . id , depth + 1 ) return depth

Calculates depth of the item in the tree .


def get_tree_current_item(self, tree_alias):
        """Resolves current tree item of 'tree_alias' tree matching current
        request path against URL of given tree item.

        :param str|unicode tree_alias:
        :rtype: TreeItemBase
        """
        current_item = self._current_items.get(tree_alias, _UNSET)

        if current_item is not _UNSET:

            if current_item is not None:
                current_item.is_current = True  # Could be reset by .get_sitetree()

            return current_item

        current_item = None

        if self.current_app_is_admin():
            self._current_items[tree_alias] = current_item
            return None

        # urlquote is an attempt to support non-ascii in url.
        current_url = self.current_request.path
        if isinstance(current_url, str):
            current_url = current_url.encode('UTF-8')
        if current_url:
            current_url = urlquote(current_url)

        for url_item, url in self._items_urls.items():
            # Iterate each as this dict may contains "current" items for various trees.
            if url != current_url:
                continue

            url_item.is_current = True
            if url_item.tree.alias == tree_alias:
                current_item = url_item

        if current_item is not None:
            self._current_items[tree_alias] = current_item

        return current_item

Resolves current tree item of tree_alias tree matching current request path against URL of given tree item .


def url(self, sitetree_item, context=None):
        """Resolves item's URL.

        :param TreeItemBase sitetree_item: TreeItemBase heir object, 'url' property of which
            is processed as URL pattern or simple URL.

        :param Context context:

        :rtype: str|unicode
        """
        context = context or self.current_page_context
        resolve_var = self.resolve_var

        if not isinstance(sitetree_item, MODEL_TREE_ITEM_CLASS):
            sitetree_item = resolve_var(sitetree_item, context)

        resolved_url = self._items_urls.get(sitetree_item)
        if resolved_url is not None:
            return resolved_url

        # Resolve only if item's URL is marked as pattern.
        if sitetree_item.urlaspattern:
            url = sitetree_item.url
            view_path = url
            all_arguments = []

            if ' ' in url:
                view_path = url.split(' ')
                # We should try to resolve URL parameters from site tree item.
                for view_argument in view_path[1:]:
                    resolved = resolve_var(view_argument)
                    # We enclose arg in double quotes as already resolved.
                    all_arguments.append('"%s"' % resolved)

                view_path = view_path[0].strip('"\' ')

            url_pattern = "'%s' %s" % (view_path, ' '.join(all_arguments))

        else:
            url_pattern = '%s' % sitetree_item.url

        if sitetree_item.urlaspattern:
            # Form token to pass to Django 'url' tag.
            url_token = 'url %s as item.url_resolved' % url_pattern
            url_tag(
                Parser(None),
                Token(token_type=TOKEN_BLOCK, contents=url_token)
            ).render(context)

            resolved_url = context['item.url_resolved'] or UNRESOLVED_ITEM_MARKER

        else:
            resolved_url = url_pattern

        self._items_urls[sitetree_item] = resolved_url

        return resolved_url


def init_tree(self, tree_alias, context):
        """Initializes sitetree in memory.

        Returns tuple with resolved tree alias and items on success.

        On fail returns (None, None).

        :param str|unicode tree_alias:
        :param Context context:
        :rtype: tuple
        """
        request = context.get('request', None)

        if request is None:
            raise SiteTreeError(
                'Sitetree requires "django.core.context_processors.request" template context processor to be active. '
                'If it is, check that your view pushes request data into the template.')

        if id(request) != id(self.current_request):
            self.init(context)

        # Resolve tree_alias from the context.
        tree_alias = self.resolve_var(tree_alias)
        tree_alias, sitetree_items = self.get_sitetree(tree_alias)

        if not sitetree_items:
            return None, None

        return tree_alias, sitetree_items


def get_current_page_attr(self, attr_name, tree_alias, context):
        """Returns an arbitrary attribute of a sitetree item resolved as current for current page.

        :param str|unicode attr_name:
        :param str|unicode tree_alias:
        :param Context context:
        :rtype: str|unicode
        """
        tree_alias, sitetree_items = self.init_tree(tree_alias, context)
        current_item = self.get_tree_current_item(tree_alias)

        if current_item is None:
            if settings.DEBUG and RAISE_ITEMS_ERRORS_ON_DEBUG:
                raise SiteTreeError(
                    'Unable to resolve current sitetree item to get a `%s` for current page. Check whether '
                    'there is an appropriate sitetree item defined for current URL.' % attr_name)

            return ''

        return getattr(current_item, attr_name, '')

Returns an arbitrary attribute of a sitetree item resolved as current for current page .


def get_ancestor_level(self, current_item, depth=1):
        """Returns ancestor of level `deep` recursively

        :param TreeItemBase current_item:
        :param int depth:
        :rtype: TreeItemBase
        """
        if current_item.parent is None:
            return current_item

        if depth <= 1:
            return current_item.parent

        return self.get_ancestor_level(current_item.parent, depth=depth-1)

def get_ancestor_level ( self , current_item , depth = 1 ) : if current_item . parent is None : return current_item if depth <= 1 : return current_item . parent return self . get_ancestor_level ( current_item . parent , depth = depth - 1 )

Returns ancestor of level deep recursively


def menu(self, tree_alias, tree_branches, context):
        """Builds and returns menu structure for 'sitetree_menu' tag.

        :param str|unicode tree_alias:
        :param str|unicode tree_branches:
        :param Context context:
        :rtype: list|str
        """
        tree_alias, sitetree_items = self.init_tree(tree_alias, context)

        if not sitetree_items:
            return ''

        tree_branches = self.resolve_var(tree_branches)

        parent_isnull = False
        parent_ids = []
        parent_aliases = []

        current_item = self.get_tree_current_item(tree_alias)
        self.tree_climber(tree_alias, current_item)

        # Support item addressing both through identifiers and aliases.
        for branch_id in tree_branches.split(','):
            branch_id = branch_id.strip()

            if branch_id == ALIAS_TRUNK:
                parent_isnull = True

            elif branch_id == ALIAS_THIS_CHILDREN and current_item is not None:
                branch_id = current_item.id
                parent_ids.append(branch_id)

            elif branch_id == ALIAS_THIS_ANCESTOR_CHILDREN and current_item is not None:
                branch_id = self.get_ancestor_item(tree_alias, current_item).id
                parent_ids.append(branch_id)

            elif branch_id == ALIAS_THIS_SIBLINGS and current_item is not None and current_item.parent is not None:
                branch_id = current_item.parent.id
                parent_ids.append(branch_id)

            elif branch_id == ALIAS_THIS_PARENT_SIBLINGS and current_item is not None:
                branch_id = self.get_ancestor_level(current_item, depth=2).id
                parent_ids.append(branch_id)

            elif branch_id.isdigit():
                parent_ids.append(int(branch_id))

            else:
                parent_aliases.append(branch_id)

        check_access = self.check_access

        menu_items = []
        for item in sitetree_items:
            if not item.hidden and item.inmenu and check_access(item, context):
                if item.parent is None:
                    if parent_isnull:
                        menu_items.append(item)
                else:
                    if item.parent.id in parent_ids or item.parent.alias in parent_aliases:
                        menu_items.append(item)

        menu_items = self.apply_hook(menu_items, 'menu')
        self.update_has_children(tree_alias, menu_items, 'menu')
        return menu_items

Builds and returns menu structure for sitetree_menu tag .


def check_access(self, item, context):
        """Checks whether a current user has an access to a certain item.

        :param TreeItemBase item:
        :param Context context:
        :rtype: bool
        """
        if hasattr(self.current_request.user.is_authenticated, '__call__'):
            authenticated = self.current_request.user.is_authenticated()
        else:
            authenticated = self.current_request.user.is_authenticated

        if item.access_loggedin and not authenticated:
            return False

        if item.access_guest and authenticated:
            return False

        if item.access_restricted:
            user_perms = self._current_user_permissions

            if user_perms is _UNSET:
                user_perms = set(context['user'].get_all_permissions())
                self._current_user_permissions = user_perms

            if item.access_perm_type == MODEL_TREE_ITEM_CLASS.PERM_TYPE_ALL:
                if len(item.perms) != len(item.perms.intersection(user_perms)):
                    return False
            else:
                if not len(item.perms.intersection(user_perms)):
                    return False

        return True

def check_access ( self , item , context ) : if hasattr ( self . current_request . user . is_authenticated , '__call__' ) : authenticated = self . current_request . user . is_authenticated ( ) else : authenticated = self . current_request . user . is_authenticated if item . access_loggedin and not authenticated : return False if item . access_guest and authenticated : return False if item . access_restricted : user_perms = self . _current_user_permissions if user_perms is _UNSET : user_perms = set ( context [ 'user' ] . get_all_permissions ( ) ) self . _current_user_permissions = user_perms if item . access_perm_type == MODEL_TREE_ITEM_CLASS . PERM_TYPE_ALL : if len ( item . perms ) != len ( item . perms . intersection ( user_perms ) ) : return False else : if not len ( item . perms . intersection ( user_perms ) ) : return False return True

Checks whether a current user has an access to a certain item .


def breadcrumbs(self, tree_alias, context):
        """Builds and returns breadcrumb trail structure for 'sitetree_breadcrumbs' tag.

        :param str|unicode tree_alias:
        :param Context context:
        :rtype: list|str
        """
        tree_alias, sitetree_items = self.init_tree(tree_alias, context)

        if not sitetree_items:
            return ''

        current_item = self.get_tree_current_item(tree_alias)

        breadcrumbs = []

        if current_item is not None:

            context_ = self.current_page_context
            check_access = self.check_access
            get_item_by_id = self.get_item_by_id

            def climb(base_item):
                """Climbs up the site tree to build breadcrumb path.

                :param TreeItemBase base_item:
                """
                if base_item.inbreadcrumbs and not base_item.hidden and check_access(base_item, context_):
                    breadcrumbs.append(base_item)

                if hasattr(base_item, 'parent') and base_item.parent is not None:
                    climb(get_item_by_id(tree_alias, base_item.parent.id))

            climb(current_item)
            breadcrumbs.reverse()

        items = self.apply_hook(breadcrumbs, 'breadcrumbs')
        self.update_has_children(tree_alias, items, 'breadcrumbs')

        return items

Builds and returns breadcrumb trail structure for sitetree_breadcrumbs tag .


def tree(self, tree_alias, context):
        """Builds and returns tree structure for 'sitetree_tree' tag.

        :param str|unicode tree_alias:
        :param Context context:
        :rtype: list|str
        """
        tree_alias, sitetree_items = self.init_tree(tree_alias, context)

        if not sitetree_items:
            return ''

        tree_items = self.filter_items(self.get_children(tree_alias, None), 'sitetree')
        tree_items = self.apply_hook(tree_items, 'sitetree')
        self.update_has_children(tree_alias, tree_items, 'sitetree')

        return tree_items

def tree ( self , tree_alias , context ) : tree_alias , sitetree_items = self . init_tree ( tree_alias , context ) if not sitetree_items : return '' tree_items = self . filter_items ( self . get_children ( tree_alias , None ) , 'sitetree' ) tree_items = self . apply_hook ( tree_items , 'sitetree' ) self . update_has_children ( tree_alias , tree_items , 'sitetree' ) return tree_items

Builds and returns tree structure for sitetree_tree tag .


def children(self, parent_item, navigation_type, use_template, context):
        """Builds and returns site tree item children structure for 'sitetree_children' tag.

        :param TreeItemBase parent_item:
        :param str|unicode navigation_type: menu, sitetree
        :param str|unicode use_template:
        :param Context context:
        :rtype: list
        """
        # Resolve parent item and current tree alias.
        parent_item = self.resolve_var(parent_item, context)
        tree_alias, tree_items = self.get_sitetree(parent_item.tree.alias)

        # Mark path to current item.
        self.tree_climber(tree_alias, self.get_tree_current_item(tree_alias))

        tree_items = self.get_children(tree_alias, parent_item)
        tree_items = self.filter_items(tree_items, navigation_type)
        tree_items = self.apply_hook(tree_items, '%s.children' % navigation_type)
        self.update_has_children(tree_alias, tree_items, navigation_type)

        my_template = get_template(use_template)

        context.push()
        context['sitetree_items'] = tree_items
        rendered = my_template.render(context.flatten() if _CONTEXT_FLATTEN else context)
        context.pop()

        return rendered

Builds and returns site tree item children structure for sitetree_children tag .


def get_children(self, tree_alias, item):
        """Returns item's children.

        :param str|unicode tree_alias:
        :param TreeItemBase|None item:
        :rtype: list
        """
        if not self.current_app_is_admin():
            # We do not need i18n for a tree rendered in Admin dropdown.
            tree_alias = self.resolve_tree_i18n_alias(tree_alias)

        return self.cache.get_entry('parents', tree_alias)[item]


def update_has_children(self, tree_alias, tree_items, navigation_type):
        """Updates 'has_children' attribute for tree items inplace.

        :param str|unicode tree_alias:
        :param list tree_items:
        :param str|unicode navigation_type: sitetree, breadcrumbs, menu
        """
        get_children = self.get_children
        filter_items = self.filter_items
        apply_hook = self.apply_hook

        for tree_item in tree_items:
            children = get_children(tree_alias, tree_item)
            children = filter_items(children, navigation_type)
            children = apply_hook(children, '%s.has_children' % navigation_type)
            tree_item.has_children = len(children) > 0

Updates has_children attribute for tree items inplace .


def filter_items(self, items, navigation_type=None):
        """Filters sitetree item's children if hidden and by navigation type.

        NB: We do not apply any filters to sitetree in admin app.

        :param list items:
        :param str|unicode navigation_type: sitetree, breadcrumbs, menu
        :rtype: list
        """
        if self.current_app_is_admin():
            return items

        items_filtered = []

        context = self.current_page_context
        check_access = self.check_access

        for item in items:
            if item.hidden:
                continue

            if not check_access(item, context):
                continue

            if not getattr(item, 'in%s' % navigation_type, True):  # Hidden for current nav type
                continue

            items_filtered.append(item)

        return items_filtered

def
filter_items
(
self
,
items
,
navigation_type
=
)
:
if
self
.
current_app_is_admin
(
)
:
return
items
items_filtered
=
[
]
context
=
self
.
current_page_context
check_access
=
self
.
check_access
for
item
in
items
:
if
item
.
hidden
:
continue
if
not
check_access
(
item
,
context
)
:
continue
if
not
getattr
(
item
,
'in%s'
%
navigation_type
,
True
)
:
# Hidden for current nav type
continue
items_filtered
.
append
(
item
)
return
items_filtered

Filters sitetree item s children if hidden and by navigation type .


def get_ancestor_item(self, tree_alias, base_item):
        """Climbs up the site tree to resolve root item for chosen one.

        :param str|unicode tree_alias:
        :param TreeItemBase base_item:
        :rtype: TreeItemBase
        """
        parent = None

        if hasattr(base_item, 'parent') and base_item.parent is not None:
            parent = self.get_ancestor_item(tree_alias, self.get_item_by_id(tree_alias, base_item.parent.id))

        if parent is None:
            return base_item

        return parent

def get_ancestor_item ( self , tree_alias , base_item ) : parent = None if hasattr ( base_item , 'parent' ) and base_item . parent is not None : parent = self . get_ancestor_item ( tree_alias , self . get_item_by_id ( tree_alias , base_item . parent . id ) ) if parent is None : return base_item return parent

Climbs up the site tree to resolve root item for chosen one .


def tree_climber(self, tree_alias, base_item):
        """Climbs up the site tree to mark items of current branch.

        :param str|unicode tree_alias:
        :param TreeItemBase base_item:
        """
        if base_item is not None:
            base_item.in_current_branch = True
            if hasattr(base_item, 'parent') and base_item.parent is not None:
                self.tree_climber(tree_alias, self.get_item_by_id(tree_alias, base_item.parent.id))

def tree_climber ( self , tree_alias , base_item ) : if base_item is not None : base_item . in_current_branch = True if hasattr ( base_item , 'parent' ) and base_item . parent is not None : self . tree_climber ( tree_alias , self . get_item_by_id ( tree_alias , base_item . parent . id ) )

Climbs up the site tree to mark items of current branch .


def resolve_var(self, varname, context=None):
        """Resolves name as a variable in a given context.

        If no context specified page context' is considered as context.

        :param str|unicode varname:
        :param Context context:
        :return:
        """
        context = context or self.current_page_context

        if isinstance(varname, FilterExpression):
            varname = varname.resolve(context)
        else:
            varname = varname.strip()

            try:
                varname = Variable(varname).resolve(context)
            except VariableDoesNotExist:
                varname = varname

        return varname

def resolve_var ( self , varname , context = None ) : context = context or self . current_page_context if isinstance ( varname , FilterExpression ) : varname = varname . resolve ( context ) else : varname = varname . strip ( ) try : varname = Variable ( varname ) . resolve ( context ) except VariableDoesNotExist : varname = varname return varname

Resolves name as a variable in a given context .


def sitetree_tree(parser, token):
    """Parses sitetree tag parameters.

    Two notation types are possible:
        1. Two arguments:
           {% sitetree_tree from "mytree" %}
           Used to render tree for "mytree" site tree.

        2. Four arguments:
           {% sitetree_tree from "mytree" template "sitetree/mytree.html" %}
           Used to render tree for "mytree" site tree using specific
           template "sitetree/mytree.html"

    """
    tokens = token.split_contents()
    use_template = detect_clause(parser, 'template', tokens)
    tokens_num = len(tokens)

    if tokens_num in (3, 5):
        tree_alias = parser.compile_filter(tokens[2])
        return sitetree_treeNode(tree_alias, use_template)
    else:
        raise template.TemplateSyntaxError(
            '%r tag requires two arguments. E.g. {%% sitetree_tree from "mytree" %%}.' % tokens[0])


def sitetree_children(parser, token):
    """Parses sitetree_children tag parameters.

       Six arguments:
           {% sitetree_children of someitem for menu template "sitetree/mychildren.html" %}
           Used to render child items of specific site tree 'someitem'
           using template "sitetree/mychildren.html" for menu navigation.

           Basically template argument should contain path to current template itself.

           Allowed navigation types: 1) menu; 2) sitetree.

    """
    tokens = token.split_contents()
    use_template = detect_clause(parser, 'template', tokens)
    tokens_num = len(tokens)

    clauses_in_places = (
        tokens_num == 5 and tokens[1] == 'of' and tokens[3] == 'for' and tokens[4] in ('menu', 'sitetree')
    )
    if clauses_in_places and use_template is not None:
        tree_item = tokens[2]
        navigation_type = tokens[4]
        return sitetree_childrenNode(tree_item, navigation_type, use_template)
    else:
        raise template.TemplateSyntaxError(
            '%r tag requires six arguments. '
            'E.g. {%% sitetree_children of someitem for menu template "sitetree/mychildren.html" %%}.' % tokens[0])

Parses sitetree_children tag parameters .


def sitetree_breadcrumbs(parser, token):
    """Parses sitetree_breadcrumbs tag parameters.

    Two notation types are possible:
        1. Two arguments:
           {% sitetree_breadcrumbs from "mytree" %}
           Used to render breadcrumb path for "mytree" site tree.

        2. Four arguments:
           {% sitetree_breadcrumbs from "mytree" template "sitetree/mycrumb.html" %}
           Used to render breadcrumb path for "mytree" site tree using specific
           template "sitetree/mycrumb.html"

    """
    tokens = token.split_contents()
    use_template = detect_clause(parser, 'template', tokens)
    tokens_num = len(tokens)

    if tokens_num == 3:
        tree_alias = parser.compile_filter(tokens[2])
        return sitetree_breadcrumbsNode(tree_alias, use_template)
    else:
        raise template.TemplateSyntaxError(
            '%r tag requires two arguments. E.g. {%% sitetree_breadcrumbs from "mytree" %%}.' % tokens[0])

Parses sitetree_breadcrumbs tag parameters .


def sitetree_menu(parser, token):
    """Parses sitetree_menu tag parameters.

        {% sitetree_menu from "mytree" include "trunk,1,level3" %}
        Used to render trunk, branch with id 1 and branch aliased 'level3'
        elements from "mytree" site tree as a menu.

        These are reserved aliases:
            * 'trunk' - items without parents
            * 'this-children' - items under item resolved as current for the current page
            * 'this-siblings' - items under parent of item resolved as current for
              the current page (current item included)
            * 'this-ancestor-children' - items under grandparent item (closest to root)
              for the item resolved as current for the current page

        {% sitetree_menu from "mytree" include "trunk,1,level3" template "sitetree/mymenu.html" %}

    """
    tokens = token.split_contents()
    use_template = detect_clause(parser, 'template', tokens)
    tokens_num = len(tokens)

    if tokens_num == 5 and tokens[3] == 'include':
        tree_alias = parser.compile_filter(tokens[2])
        tree_branches = parser.compile_filter(tokens[4])
        return sitetree_menuNode(tree_alias, tree_branches, use_template)
    else:
        raise template.TemplateSyntaxError(
            '%r tag requires four arguments. '
            'E.g. {%% sitetree_menu from "mytree" include "trunk,1,level3" %%}.' % tokens[0])


def render(context, tree_items, use_template):
    """Render helper is used by template node functions
    to render given template with given tree items in context.

    """
    context.push()
    context['sitetree_items'] = tree_items

    if isinstance(use_template, FilterExpression):
        use_template = use_template.resolve(context)

    content = get_template(use_template).render(context.flatten() if _CONTEXT_FLATTEN else context)
    context.pop()

    return content

def render ( context , tree_items , use_template ) : context . push ( ) context [ 'sitetree_items' ] = tree_items if isinstance ( use_template , FilterExpression ) : use_template = use_template . resolve ( context ) content = get_template ( use_template ) . render ( context . flatten ( ) if _CONTEXT_FLATTEN else context ) context . pop ( ) return content

Render helper is used by template node functions to render given template with given tree items in context .


def for_tag(cls, parser, token, preposition, error_hint):
        """Node constructor to be used in tags."""
        tokens = token.split_contents()

        if len(tokens) >= 3 and tokens[1] == preposition:
            as_var = cls.get_as_var(tokens)
            tree_alias = parser.compile_filter(tokens[2])
            return cls(tree_alias, as_var)

        raise template.TemplateSyntaxError(
            '%r tag requires at least two arguments. E.g. {%% %s %%}.' % (tokens[0], error_hint))


def get_model_url_name(model_nfo, page, with_namespace=False):
    """Returns a URL for a given Tree admin page type."""
    prefix = ''
    if with_namespace:
        prefix = 'admin:'
    return ('%s%s_%s' % (prefix, '%s_%s' % model_nfo, page)).lower()

def get_model_url_name ( model_nfo , page , with_namespace = False ) : prefix = '' if with_namespace : prefix = 'admin:' return ( '%s%s_%s' % ( prefix , '%s_%s' % model_nfo , page ) ) . lower ( )

Returns a URL for a given Tree admin page type .


def _reregister_tree_admin():
    """Forces unregistration of tree admin class with following re-registration."""
    try:
        admin.site.unregister(MODEL_TREE_CLASS)
    except NotRegistered:
        pass
    admin.site.register(MODEL_TREE_CLASS, _TREE_ADMIN())

def _reregister_tree_admin ( ) : try : admin . site . unregister ( MODEL_TREE_CLASS ) except NotRegistered : pass admin . site . register ( MODEL_TREE_CLASS , _TREE_ADMIN ( ) )

Forces unregistration of tree admin class with following re - registration .


def redirects_handler(*args, **kwargs):
    """Fixes Admin contrib redirects compatibility problems
    introduced in Django 1.4 by url handling changes.

    """
    path = args[0].path
    shift = '../'

    if 'delete' in path:
        # Weird enough 'delete' is not handled by TreeItemAdmin::response_change().
        shift += '../'
    elif 'history' in path:
        if 'item_id' not in kwargs:
            # Encountered request from history page to return to tree layout page.
            shift += '../'

    return HttpResponseRedirect(path + shift)

Fixes Admin contrib redirects compatibility problems introduced in Django 1 . 4 by url handling changes .


def _redirect(self, request, response):
        """Generic redirect for item editor."""

        if '_addanother' in request.POST:
            return HttpResponseRedirect('../item_add/')

        elif '_save' in request.POST:
            return HttpResponseRedirect('../')

        elif '_continue' in request.POST:
            return response

        return HttpResponseRedirect('')

def _redirect ( self , request , response ) : if '_addanother' in request . POST : return HttpResponseRedirect ( '../item_add/' ) elif '_save' in request . POST : return HttpResponseRedirect ( '../' ) elif '_continue' in request . POST : return response return HttpResponseRedirect ( '' )


def response_add(self, request, obj, post_url_continue=None, **kwargs):
        """Redirects to the appropriate items' 'continue' page on item add.

        As we administer tree items within tree itself, we
        should make some changes to redirection process.

        """
        if post_url_continue is None:
            post_url_continue = '../item_%s/' % obj.pk

        return self._redirect(request, super(TreeItemAdmin, self).response_add(request, obj, post_url_continue))

def response_add ( self , request , obj , post_url_continue = None , * * kwargs ) : if post_url_continue is None : post_url_continue = '../item_%s/' % obj . pk return self . _redirect ( request , super ( TreeItemAdmin , self ) . response_add ( request , obj , post_url_continue ) )

Redirects to the appropriate items continue page on item add .


def response_change(self, request, obj, **kwargs):
        """Redirects to the appropriate items' 'add' page on item change.

        As we administer tree items within tree itself, we
        should make some changes to redirection process.

        """
        return self._redirect(request, super(TreeItemAdmin, self).response_change(request, obj))

def response_change ( self , request , obj , * * kwargs ) : return self . _redirect ( request , super ( TreeItemAdmin , self ) . response_change ( request , obj ) )

Redirects to the appropriate items add page on item change .


def get_form(self, request, obj=None, **kwargs):
        """Returns modified form for TreeItem model.
        'Parent' field choices are built by sitetree itself.

        """
        if obj is not None and obj.parent is not None:
            self.previous_parent = obj.parent
            previous_parent_id = self.previous_parent.id
        else:
            previous_parent_id = None

        my_choice_field = TreeItemChoiceField(self.tree, initial=previous_parent_id)
        form = super(TreeItemAdmin, self).get_form(request, obj, **kwargs)
        my_choice_field.label = form.base_fields['parent'].label
        my_choice_field.help_text = form.base_fields['parent'].help_text
        my_choice_field.widget = form.base_fields['parent'].widget
        # Replace 'parent' TreeItem field with new appropriate one
        form.base_fields['parent'] = my_choice_field

        # Try to resolve all currently registered url names including those in namespaces.
        if not getattr(self, 'known_url_names', False):
            self.known_url_names = []
            self.known_url_rules = []
            resolver = get_resolver(get_urlconf())
            for ns, (url_prefix, ns_resolver) in resolver.namespace_dict.items():
                if ns != 'admin':
                    self._stack_known_urls(ns_resolver.reverse_dict, ns)
            self._stack_known_urls(resolver.reverse_dict)
            self.known_url_rules = sorted(self.known_url_rules)

        form.known_url_names_hint = _(
            'You are seeing this warning because "URL as Pattern" option is active and pattern entered above '
            'seems to be invalid. Currently registered URL pattern names and parameters: ')
        form.known_url_names = self.known_url_names
        form.known_url_rules = self.known_url_rules
        return form

Returns modified form for TreeItem model . Parent field choices are built by sitetree itself .


def get_tree(self, request, tree_id, item_id=None):
        """Fetches Tree for current or given TreeItem."""
        if tree_id is None:
            tree_id = self.get_object(request, item_id).tree_id
        self.tree = MODEL_TREE_CLASS._default_manager.get(pk=tree_id)
        self.tree.verbose_name_plural = self.tree._meta.verbose_name_plural
        self.tree.urls = _TREE_URLS
        return self.tree

def get_tree ( self , request , tree_id , item_id = None ) : if tree_id is None : tree_id = self . get_object ( request , item_id ) . tree_id self . tree = MODEL_TREE_CLASS . _default_manager . get ( pk = tree_id ) self . tree . verbose_name_plural = self . tree . _meta . verbose_name_plural self . tree . urls = _TREE_URLS return self . tree

Fetches Tree for current or given TreeItem .


def item_move(self, request, tree_id, item_id, direction):
        """Moves item up or down by swapping 'sort_order' field values of neighboring items."""
        current_item = MODEL_TREE_ITEM_CLASS._default_manager.get(pk=item_id)
        if direction == 'up':
            sort_order = 'sort_order'
        else:
            sort_order = '-sort_order'

        siblings = MODEL_TREE_ITEM_CLASS._default_manager.filter(
            parent=current_item.parent,
            tree=current_item.tree
        ).order_by(sort_order)

        previous_item = None
        for item in siblings:
            if item != current_item:
                previous_item = item
            else:
                break

        if previous_item is not None:
            current_item_sort_order = current_item.sort_order
            previous_item_sort_order = previous_item.sort_order

            current_item.sort_order = previous_item_sort_order
            previous_item.sort_order = current_item_sort_order

            current_item.save()
            previous_item.save()

        return HttpResponseRedirect('../../')

def item_move ( self , request , tree_id , item_id , direction ) : current_item = MODEL_TREE_ITEM_CLASS . _default_manager . get ( pk = item_id ) if direction == 'up' : sort_order = 'sort_order' else : sort_order = '-sort_order' siblings = MODEL_TREE_ITEM_CLASS . _default_manager . filter ( parent = current_item . parent , tree = current_item . tree ) . order_by ( sort_order ) previous_item = None for item in siblings : if item != current_item : previous_item = item else : break if previous_item is not None : current_item_sort_order = current_item . sort_order previous_item_sort_order = previous_item . sort_order current_item . sort_order = previous_item_sort_order previous_item . sort_order = current_item_sort_order current_item . save ( ) previous_item . save ( ) return HttpResponseRedirect ( '../../' )

Moves item up or down by swapping sort_order field values of neighboring items .


def save_model(self, request, obj, form, change):
        """Saves TreeItem model under certain Tree.
        Handles item's parent assignment exception.

        """
        if change:
            # No, you're not allowed to make item parent of itself
            if obj.parent is not None and obj.parent.id == obj.id:
                obj.parent = self.previous_parent
                messages.warning(
                    request, _("Item's parent left unchanged. Item couldn't be parent to itself."), '', True)
        obj.tree = self.tree
        obj.save()

Saves TreeItem model under certain Tree . Handles item s parent assignment exception .


def get_urls(self):
        """Manages not only TreeAdmin URLs but also TreeItemAdmin URLs."""
        urls = super(TreeAdmin, self).get_urls()

        prefix_change = 'change/' if DJANGO_POST_19 else ''

        sitetree_urls = [
            url(r'^change/$', redirects_handler, name=get_tree_item_url_name('changelist')),

            url(r'^((?P<tree_id>\d+)/)?%sitem_add/$' % prefix_change,
                self.admin_site.admin_view(self.tree_admin.item_add), name=get_tree_item_url_name('add')),

            url(r'^(?P<tree_id>\d+)/%sitem_(?P<item_id>\d+)/$' % prefix_change,
                self.admin_site.admin_view(self.tree_admin.item_edit), name=get_tree_item_url_name('change')),

            url(r'^%sitem_(?P<item_id>\d+)/$' % prefix_change,
                self.admin_site.admin_view(self.tree_admin.item_edit), name=get_tree_item_url_name('change')),

            url(r'^((?P<tree_id>\d+)/)?%sitem_(?P<item_id>\d+)/delete/$' % prefix_change,
                self.admin_site.admin_view(self.tree_admin.item_delete), name=get_tree_item_url_name('delete')),

            url(r'^((?P<tree_id>\d+)/)?%sitem_(?P<item_id>\d+)/history/$' % prefix_change,
                self.admin_site.admin_view(self.tree_admin.item_history), name=get_tree_item_url_name('history')),

            url(r'^(?P<tree_id>\d+)/%sitem_(?P<item_id>\d+)/move_(?P<direction>(up|down))/$' % prefix_change,
                self.admin_site.admin_view(self.tree_admin.item_move), name=get_tree_item_url_name('move')),
        ]

        if not DJANGO_POST_19:
            sitetree_urls = patterns_func('', *sitetree_urls)

        if SMUGGLER_INSTALLED:
            sitetree_urls += (url(r'^dump_all/$', self.admin_site.admin_view(self.dump_view), name='sitetree_dump'),)

        return sitetree_urls + urls

Manages not only TreeAdmin URLs but also TreeItemAdmin URLs .


def dump_view(cls, request):
        """Dumps sitetrees with items using django-smuggler.

        :param request:
        :return:
        """
        from smuggler.views import dump_to_response
        return dump_to_response(request, [MODEL_TREE, MODEL_TREE_ITEM], filename_prefix='sitetrees')

def dump_view ( cls , request ) : from smuggler . views import dump_to_response return dump_to_response ( request , [ MODEL_TREE , MODEL_TREE_ITEM ] , filename_prefix = 'sitetrees' )

Dumps sitetrees with items using django - smuggler .


def tree(alias, title='', items=None, **kwargs):
    """Dynamically creates and returns a sitetree.

    :param str|unicode alias:
    :param str|unicode title:
    :param iterable items: dynamic sitetree items objects created by `item` function.
    :param kwargs: Additional arguments to pass to tree item initializer.

    :rtype: TreeBase
    """
    tree_obj = get_tree_model()(alias=alias, title=title, **kwargs)
    tree_obj.id = generate_id_for(tree_obj)
    tree_obj.is_dynamic = True

    if items is not None:
        tree_obj.dynamic_items = []
        def traverse(items):
            for item in items:
                item.tree = tree_obj
                tree_obj.dynamic_items.append(item)
                if hasattr(item, 'dynamic_children'):
                    traverse(item.dynamic_children)

        traverse(items)
    return tree_obj

def tree ( alias , title = '' , items = None , * * kwargs ) : tree_obj = get_tree_model ( ) ( alias = alias , title = title , * * kwargs ) tree_obj . id = generate_id_for ( tree_obj ) tree_obj . is_dynamic = True if items is not None : tree_obj . dynamic_items = [ ] def traverse ( items ) : for item in items : item . tree = tree_obj tree_obj . dynamic_items . append ( item ) if hasattr ( item , 'dynamic_children' ) : traverse ( item . dynamic_children ) traverse ( items ) return tree_obj

Dynamically creates and returns a sitetree .


def item(
    title, url, children=None, url_as_pattern=True, hint='', alias='', description='',
    in_menu=True, in_breadcrumbs=True, in_sitetree=True,
    access_loggedin=False, access_guest=False,
    access_by_perms=None, perms_mode_all=True, **kwargs):
    """Dynamically creates and returns a sitetree item object.

    :param str|unicode title:

    :param str|unicode url:

    :param list, set children: a list of children for tree item. Children should also be created by `item` function.

    :param bool url_as_pattern: consider URL as a name of a named URL

    :param str|unicode hint: hints are usually shown to users

    :param str|unicode alias: item name to address it from templates

    :param str|unicode description: additional information on item (usually is not shown to users)

    :param bool in_menu: show this item in menus

    :param bool in_breadcrumbs: show this item in breadcrumbs

    :param bool in_sitetree: show this item in sitetrees

    :param bool access_loggedin: show item to logged in users only

    :param bool access_guest: show item to guest users only

    :param list|str||unicode|int, Permission access_by_perms: restrict access to users with these permissions.

        This can be set to one or a list of permission names, IDs or Permission instances.

        Permission names are more portable and should be in a form `<app_label>.<perm_codename>`, e.g.:
            my_app.allow_save

    :param bool perms_mode_all: permissions set interpretation rule:
                True - user should have all the permissions;
                False - user should have any of chosen permissions.

    :rtype: TreeItemBase

    """
    item_obj = get_tree_item_model()(
        title=title, url=url, urlaspattern=url_as_pattern,
        hint=hint, alias=alias, description=description, inmenu=in_menu,
        insitetree=in_sitetree, inbreadcrumbs=in_breadcrumbs,
        access_loggedin=access_loggedin, access_guest=access_guest,
        **kwargs)

    item_obj.id = generate_id_for(item_obj)
    item_obj.is_dynamic = True
    item_obj.dynamic_children = []

    cleaned_permissions = []
    if access_by_perms:
        # Make permissions a list if currently a single object
        if not isinstance(access_by_perms, list):
            access_by_perms = [access_by_perms]

        for perm in access_by_perms:
            if isinstance(perm, six.string_types):
                # Get permission object from string
                try:
                    app, codename = perm.split('.')
                except ValueError:
                    raise ValueError(
                        'Wrong permission string format: supplied - `%s`; '
                        'expected - `<app_name>.<permission_name>`.' % perm)

                try:
                    perm = Permission.objects.get(codename=codename, content_type__app_label=app)
                except Permission.DoesNotExist:
                    raise ValueError('Permission `%s.%s` does not exist.' % (app, codename))

            elif not isinstance(perm, (int, Permission)):
                raise ValueError('Permissions must be given as strings, ints, or `Permission` instances.')

            cleaned_permissions.append(perm)

    item_obj.permissions = cleaned_permissions or []
    item_obj.access_perm_type = item_obj.PERM_TYPE_ALL if perms_mode_all else item_obj.PERM_TYPE_ANY

    if item_obj.permissions:
        item_obj.access_restricted = True

    if children is not None:
        for child in children:
            child.parent = item_obj
            item_obj.dynamic_children.append(child)

    return item_obj

Dynamically creates and returns a sitetree item object .


def import_app_sitetree_module(app):
    """Imports sitetree module from a given app.

    :param str|unicode app: Application name
    :return: module|None
    """
    module_name = settings.APP_MODULE_NAME
    module = import_module(app)
    try:
        sub_module = import_module('%s.%s' % (app, module_name))
        return sub_module
    except ImportError:
        if module_has_submodule(module, module_name):
            raise
        return None

def import_app_sitetree_module ( app ) : module_name = settings . APP_MODULE_NAME module = import_module ( app ) try : sub_module = import_module ( '%s.%s' % ( app , module_name ) ) return sub_module except ImportError : if module_has_submodule ( module , module_name ) : raise return None

Imports sitetree module from a given app .


def get_model_class(settings_entry_name):
    """Returns a certain sitetree model as defined in the project settings.

    :param str|unicode settings_entry_name:
    :rtype: TreeItemBase|TreeBase
    """
    app_name, model_name = get_app_n_model(settings_entry_name)

    try:
        model = apps_get_model(app_name, model_name)
    except (LookupError, ValueError):
        model = None

    if model is None:
        raise ImproperlyConfigured(
            '`SITETREE_%s` refers to model `%s` that has not been installed.' % (settings_entry_name, model_name))

    return model

Returns a certain sitetree model as defined in the project settings .


def from_mapping(
        cls: Type["Config"], mapping: Optional[Mapping[str, Any]] = None, **kwargs: Any
    ) -> "Config":
        """Create a configuration from a mapping.

        This allows either a mapping to be directly passed or as
        keyword arguments, for example,

        .. code-block:: python

            config = {'keep_alive_timeout': 10}
            Config.from_mapping(config)
            Config.form_mapping(keep_alive_timeout=10)

        Arguments:
            mapping: Optionally a mapping object.
            kwargs: Optionally a collection of keyword arguments to
                form a mapping.
        """
        mappings: Dict[str, Any] = {}
        if mapping is not None:
            mappings.update(mapping)
        mappings.update(kwargs)
        config = cls()
        for key, value in mappings.items():
            try:
                setattr(config, key, value)
            except AttributeError:
                pass

        return config

def from_mapping ( cls : Type [ "Config" ] , mapping : Optional [ Mapping [ str , Any ] ] = None , * * kwargs : Any ) -> "Config" : mappings : Dict [ str , Any ] = { } if mapping is not None : mappings . update ( mapping ) mappings . update ( kwargs ) config = cls ( ) for key , value in mappings . items ( ) : try : setattr ( config , key , value ) except AttributeError : pass return config


def from_pyfile(cls: Type["Config"], filename: FilePath) -> "Config":
        """Create a configuration from a Python file.

        .. code-block:: python

            Config.from_pyfile('hypercorn_config.py')

        Arguments:
            filename: The filename which gives the path to the file.
        """
        file_path = os.fspath(filename)
        spec = importlib.util.spec_from_file_location("module.name", file_path)
        module = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(module)  # type: ignore
        return cls.from_object(module)

def
from_pyfile
(
cls
:
Type
[
"Config"
]
,
filename
:
FilePath
)
->
"Config"
:
file_path
=
os
.
fspath
(
filename
)
spec
=
importlib
.
util
.
spec_from_file_location
(
"module.name"
,
file_path
)
module
=
importlib
.
util
.
module_from_spec
(
spec
)
spec
.
loader
.
exec_module
(
module
)
# type: ignore
return
cls
.
from_object
(
module
)

Create a configuration from a Python file .


def from_toml(cls: Type["Config"], filename: FilePath) -> "Config":
        """Load the configuration values from a TOML formatted file.

        This allows configuration to be loaded as so

        .. code-block:: python

            Config.from_toml('config.toml')

        Arguments:
            filename: The filename which gives the path to the file.
        """
        file_path = os.fspath(filename)
        with open(file_path) as file_:
            data = toml.load(file_)
        return cls.from_mapping(data)

def from_toml ( cls : Type [ "Config" ] , filename : FilePath ) -> "Config" : file_path = os . fspath ( filename ) with open ( file_path ) as file_ : data = toml . load ( file_ ) return cls . from_mapping ( data )

Load the configuration values from a TOML formatted file .


def from_object(cls: Type["Config"], instance: Union[object, str]) -> "Config":
        """Create a configuration from a Python object.

        This can be used to reference modules or objects within
        modules for example,

        .. code-block:: python

            Config.from_object('module')
            Config.from_object('module.instance')
            from module import instance
            Config.from_object(instance)

        are valid.

        Arguments:
            instance: Either a str referencing a python object or the
                object itself.

        """
        if isinstance(instance, str):
            try:
                path, config = instance.rsplit(".", 1)
            except ValueError:
                path = instance
                instance = importlib.import_module(instance)
            else:
                module = importlib.import_module(path)
                instance = getattr(module, config)

        mapping = {
            key: getattr(instance, key)
            for key in dir(instance)
            if not isinstance(getattr(instance, key), types.ModuleType)
        }
        return cls.from_mapping(mapping)

def from_object ( cls : Type [ "Config" ] , instance : Union [ object , str ] ) -> "Config" : if isinstance ( instance , str ) : try : path , config = instance . rsplit ( "." , 1 ) except ValueError : path = instance instance = importlib . import_module ( instance ) else : module = importlib . import_module ( path ) instance = getattr ( module , config ) mapping = { key : getattr ( instance , key ) for key in dir ( instance ) if not isinstance ( getattr ( instance , key ) , types . ModuleType ) } return cls . from_mapping ( mapping )

Create a configuration from a Python object .


def create_attrs_for_span(
    sample_rate=100.0,
    trace_id=None,
    span_id=None,
    use_128bit_trace_id=False,
):
    """Creates a set of zipkin attributes for a span.

    :param sample_rate: Float between 0.0 and 100.0 to determine sampling rate
    :type sample_rate: float
    :param trace_id: Optional 16-character hex string representing a trace_id.
                    If this is None, a random trace_id will be generated.
    :type trace_id: str
    :param span_id: Optional 16-character hex string representing a span_id.
                    If this is None, a random span_id will be generated.
    :type span_id: str
    :param use_128bit_trace_id: If true, generate 128-bit trace_ids
    :type use_128bit_trace_id: boolean
    """
    # Calculate if this trace is sampled based on the sample rate
    if trace_id is None:
        if use_128bit_trace_id:
            trace_id = generate_random_128bit_string()
        else:
            trace_id = generate_random_64bit_string()
    if span_id is None:
        span_id = generate_random_64bit_string()
    if sample_rate == 0.0:
        is_sampled = False
    else:
        is_sampled = (random.random() * 100) < sample_rate

    return ZipkinAttrs(
        trace_id=trace_id,
        span_id=span_id,
        parent_span_id=None,
        flags='0',
        is_sampled=is_sampled,
    )

Creates a set of zipkin attributes for a span .


def create_http_headers_for_new_span(context_stack=None, tracer=None):
    """
    Generate the headers for a new zipkin span.

    .. note::

        If the method is not called from within a zipkin_trace context,
        empty dict will be returned back.

    :returns: dict containing (X-B3-TraceId, X-B3-SpanId, X-B3-ParentSpanId,
                X-B3-Flags and X-B3-Sampled) keys OR an empty dict.
    """
    if tracer:
        zipkin_attrs = tracer.get_zipkin_attrs()
    elif context_stack:
        zipkin_attrs = context_stack.get()
    else:
        zipkin_attrs = get_default_tracer().get_zipkin_attrs()

    if not zipkin_attrs:
        return {}

    return {
        'X-B3-TraceId': zipkin_attrs.trace_id,
        'X-B3-SpanId': generate_random_64bit_string(),
        'X-B3-ParentSpanId': zipkin_attrs.span_id,
        'X-B3-Flags': '0',
        'X-B3-Sampled': '1' if zipkin_attrs.is_sampled else '0',
    }

def create_http_headers_for_new_span ( context_stack = None , tracer = None ) : if tracer : zipkin_attrs = tracer . get_zipkin_attrs ( ) elif context_stack : zipkin_attrs = context_stack . get ( ) else : zipkin_attrs = get_default_tracer ( ) . get_zipkin_attrs ( ) if not zipkin_attrs : return { } return { 'X-B3-TraceId' : zipkin_attrs . trace_id , 'X-B3-SpanId' : generate_random_64bit_string ( ) , 'X-B3-ParentSpanId' : zipkin_attrs . span_id , 'X-B3-Flags' : '0' , 'X-B3-Sampled' : '1' if zipkin_attrs . is_sampled else '0' , }

Generate the headers for a new zipkin span .


def _get_current_context(self):
        """Returns the current ZipkinAttrs and generates new ones if needed.

        :returns: (report_root_timestamp, zipkin_attrs)
        :rtype: (bool, ZipkinAttrs)
        """
        # This check is technically not necessary since only root spans will have
        # sample_rate, zipkin_attrs or a transport set. But it helps making the
        # code clearer by separating the logic for a root span from the one for a
        # child span.
        if self._is_local_root_span:

            # If sample_rate is set, we need to (re)generate a trace context.
            # If zipkin_attrs (trace context) were passed in as argument there are
            # 2 possibilities:
            # is_sampled = False --> we keep the same trace_id but re-roll the dice
            #                        for is_sampled.
            # is_sampled = True  --> we don't want to stop sampling halfway through
            #                        a sampled trace, so we do nothing.
            # If no zipkin_attrs were passed in, we generate new ones and start a
            # new trace.
            if self.sample_rate is not None:

                # If this trace is not sampled, we re-roll the dice.
                if self.zipkin_attrs_override and \
                        not self.zipkin_attrs_override.is_sampled:
                    # This will be the root span of the trace, so we should
                    # set timestamp and duration.
                    return True, create_attrs_for_span(
                        sample_rate=self.sample_rate,
                        trace_id=self.zipkin_attrs_override.trace_id,
                    )

                # If zipkin_attrs_override was not passed in, we simply generate
                # new zipkin_attrs to start a new trace.
                elif not self.zipkin_attrs_override:
                    return True, create_attrs_for_span(
                        sample_rate=self.sample_rate,
                        use_128bit_trace_id=self.use_128bit_trace_id,
                    )

            if self.firehose_handler and not self.zipkin_attrs_override:
                # If it has gotten here, the only thing that is
                # causing a trace is the firehose. So we force a trace
                # with sample rate of 0
                return True, create_attrs_for_span(
                    sample_rate=0.0,
                    use_128bit_trace_id=self.use_128bit_trace_id,
                )

            # If we arrive here it means the sample_rate was not set while
            # zipkin_attrs_override was, so let's simply return that.
            return False, self.zipkin_attrs_override

        else:
            # Check if there's already a trace context in _context_stack.
            existing_zipkin_attrs = self.get_tracer().get_zipkin_attrs()
            # If there's an existing context, let's create new zipkin_attrs
            # with that context as parent.
            if existing_zipkin_attrs:
                return False, ZipkinAttrs(
                    trace_id=existing_zipkin_attrs.trace_id,
                    span_id=generate_random_64bit_string(),
                    parent_span_id=existing_zipkin_attrs.span_id,
                    flags=existing_zipkin_attrs.flags,
                    is_sampled=existing_zipkin_attrs.is_sampled,
                )

        return False, None

#                        for is_sampled.

#                        a sampled trace, so we do nothing.

Returns the current ZipkinAttrs and generates new ones if needed .


def start(self):
        """Enter the new span context. All annotations logged inside this
        context will be attributed to this span. All new spans generated
        inside this context will have this span as their parent.

        In the unsampled case, this context still generates new span IDs and
        pushes them onto the threadlocal stack, so downstream services calls
        made will pass the correct headers. However, the logging handler is
        never attached in the unsampled case, so the spans are never logged.
        """
        self.do_pop_attrs = False

        report_root_timestamp, self.zipkin_attrs = self._get_current_context()

        # If zipkin_attrs are not set up by now, that means this span is not
        # configured to perform logging itself, and it's not in an existing
        # Zipkin trace. That means there's nothing else to do and it can exit
        # early.
        if not self.zipkin_attrs:
            return self

        self.get_tracer().push_zipkin_attrs(self.zipkin_attrs)
        self.do_pop_attrs = True

        self.start_timestamp = time.time()

        if self._is_local_root_span:
            # Don't set up any logging if we're not sampling
            if not self.zipkin_attrs.is_sampled and not self.firehose_handler:
                return self
            # If transport is already configured don't override it. Doing so would
            # cause all previously recorded spans to never be emitted as exiting
            # the inner logging context will reset transport_configured to False.
            if self.get_tracer().is_transport_configured():
                log.info('Transport was already configured, ignoring override'
                         'from span {}'.format(self.span_name))
                return self
            endpoint = create_endpoint(self.port, self.service_name, self.host)
            self.logging_context = ZipkinLoggingContext(
                self.zipkin_attrs,
                endpoint,
                self.span_name,
                self.transport_handler,
                report_root_timestamp or self.report_root_timestamp_override,
                self.get_tracer,
                self.service_name,
                binary_annotations=self.binary_annotations,
                add_logging_annotation=self.add_logging_annotation,
                client_context=self.kind == Kind.CLIENT,
                max_span_batch_size=self.max_span_batch_size,
                firehose_handler=self.firehose_handler,
                encoding=self.encoding,
            )
            self.logging_context.start()
            self.get_tracer().set_transport_configured(configured=True)

        return self

Enter the new span context . All annotations logged inside this context will be attributed to this span . All new spans generated inside this context will have this span as their parent .


def stop(self, _exc_type=None, _exc_value=None, _exc_traceback=None):
        """Exit the span context. Zipkin attrs are pushed onto the
        threadlocal stack regardless of sampling, so they always need to be
        popped off. The actual logging of spans depends on sampling and that
        the logging was correctly set up.
        """

        if self.do_pop_attrs:
            self.get_tracer().pop_zipkin_attrs()

        # If no transport is configured, there's no reason to create a new Span.
        # This also helps avoiding memory leaks since without a transport nothing
        # would pull spans out of get_tracer().
        if not self.get_tracer().is_transport_configured():
            return

        # Add the error annotation if an exception occurred
        if any((_exc_type, _exc_value, _exc_traceback)):
            error_msg = u'{0}: {1}'.format(_exc_type.__name__, _exc_value)
            self.update_binary_annotations({
                ERROR_KEY: error_msg,
            })

        # Logging context is only initialized for "root" spans of the local
        # process (i.e. this zipkin_span not inside of any other local
        # zipkin_spans)
        if self.logging_context:
            try:
                self.logging_context.stop()
            except Exception as ex:
                err_msg = 'Error emitting zipkin trace. {}'.format(
                    repr(ex),
                )
                log.error(err_msg)
            finally:
                self.logging_context = None
                self.get_tracer().clear()
                self.get_tracer().set_transport_configured(configured=False)
                return

        # If we've gotten here, that means that this span is a child span of
        # this context's root span (i.e. it's a zipkin_span inside another
        # zipkin_span).
        end_timestamp = time.time()
        # If self.duration is set, it means the user wants to override it
        if self.duration:
            duration = self.duration
        else:
            duration = end_timestamp - self.start_timestamp

        endpoint = create_endpoint(self.port, self.service_name, self.host)
        self.get_tracer().add_span(Span(
            trace_id=self.zipkin_attrs.trace_id,
            name=self.span_name,
            parent_id=self.zipkin_attrs.parent_span_id,
            span_id=self.zipkin_attrs.span_id,
            kind=self.kind,
            timestamp=self.timestamp if self.timestamp else self.start_timestamp,
            duration=duration,
            annotations=self.annotations,
            local_endpoint=endpoint,
            remote_endpoint=self.remote_endpoint,
            tags=self.binary_annotations,
        ))

Exit the span context . Zipkin attrs are pushed onto the threadlocal stack regardless of sampling so they always need to be popped off . The actual logging of spans depends on sampling and that the logging was correctly set up .


def update_binary_annotations(self, extra_annotations):
        """Updates the binary annotations for the current span."""
        if not self.logging_context:
            # This is not the root span, so binary annotations will be added
            # to the log handler when this span context exits.
            self.binary_annotations.update(extra_annotations)
        else:
            # Otherwise, we're in the context of the root span, so just update
            # the binary annotations for the logging context directly.
            self.logging_context.tags.update(extra_annotations)

Updates the binary annotations for the current span .


def add_sa_binary_annotation(
        self,
        port=0,
        service_name='unknown',
        host='127.0.0.1',
    ):
        """Adds a 'sa' binary annotation to the current span.

        'sa' binary annotations are useful for situations where you need to log
        where a request is going but the destination doesn't support zipkin.

        Note that the span must have 'cs'/'cr' annotations.

        :param port: The port number of the destination
        :type port: int
        :param service_name: The name of the destination service
        :type service_name: str
        :param host: Host address of the destination
        :type host: str
        """
        if self.kind != Kind.CLIENT:
            # TODO: trying to set a sa binary annotation for a non-client span
            # should result in a logged error
            return

        remote_endpoint = create_endpoint(
            port=port,
            service_name=service_name,
            host=host,
        )
        if not self.logging_context:
            if self.remote_endpoint is not None:
                raise ValueError('SA annotation already set.')
            self.remote_endpoint = remote_endpoint
        else:
            if self.logging_context.remote_endpoint is not None:
                raise ValueError('SA annotation already set.')
            self.logging_context.remote_endpoint = remote_endpoint

Adds a sa binary annotation to the current span .


def override_span_name(self, name):
        """Overrides the current span name.

        This is useful if you don't know the span name yet when you create the
        zipkin_span object. i.e. pyramid_zipkin doesn't know which route the
        request matched until the function wrapped by the context manager
        completes.

        :param name: New span name
        :type name: str
        """
        self.span_name = name
        if self.logging_context:
            self.logging_context.span_name = name

def override_span_name ( self , name ) : self . span_name = name if self . logging_context : self . logging_context . span_name = name