def constraint_matrices(model, array_type='dense', include_vars=False,
                        zero_tol=1e-6):
    """Create a matrix representation of the problem.

    This is used for alternative solution approaches that do not use optlang.
    The function will construct the equality matrix, inequality matrix and
    bounds for the complete problem.

    Notes
    -----
    To accomodate non-zero equalities the problem will add the variable
    "const_one" which is a variable that equals one.

    Arguments
    ---------
    model : cobra.Model
        The model from which to obtain the LP problem.
    array_type : string
        The type of array to construct. if 'dense', return a standard
        numpy.array, 'dok', or 'lil' will construct a sparse array using
        scipy of the corresponding type and 'DataFrame' will give a
        pandas `DataFrame` with metabolite indices and reaction columns.
    zero_tol : float
        The zero tolerance used to judge whether two bounds are the same.

    Returns
    -------
    collections.namedtuple
        A named tuple consisting of 6 matrices and 2 vectors:
        - "equalities" is a matrix S such that S*vars = b. It includes a row
          for each constraint and one column for each variable.
        - "b" the right side of the equality equation such that S*vars = b.
        - "inequalities" is a matrix M such that lb <= M*vars <= ub.
          It contains a row for each inequality and as many columns as
          variables.
        - "bounds" is a compound matrix [lb ub] containing the lower and
          upper bounds for the inequality constraints in M.
        - "variable_fixed" is a boolean vector indicating whether the variable
          at that index is fixed (lower bound == upper_bound) and
          is thus bounded by an equality constraint.
        - "variable_bounds" is a compound matrix [lb ub] containing the
          lower and upper bounds for all variables.
    """
    if array_type not in ('DataFrame', 'dense') and not dok_matrix:
        raise ValueError('Sparse matrices require scipy')

    array_builder = {
        'dense': np.array, 'dok': dok_matrix, 'lil': lil_matrix,
        'DataFrame': pd.DataFrame,
    }[array_type]

    Problem = namedtuple("Problem",
                         ["equalities", "b", "inequalities", "bounds",
                          "variable_fixed", "variable_bounds"])
    equality_rows = []
    inequality_rows = []
    inequality_bounds = []
    b = []

    for const in model.constraints:
        lb = -np.inf if const.lb is None else const.lb
        ub = np.inf if const.ub is None else const.ub
        equality = (ub - lb) < zero_tol
        coefs = const.get_linear_coefficients(model.variables)
        coefs = [coefs[v] for v in model.variables]
        if equality:
            b.append(lb if abs(lb) > zero_tol else 0.0)
            equality_rows.append(coefs)
        else:
            inequality_rows.append(coefs)
            inequality_bounds.append([lb, ub])

    var_bounds = np.array([[v.lb, v.ub] for v in model.variables])
    fixed = var_bounds[:, 1] - var_bounds[:, 0] < zero_tol

    results = Problem(
        equalities=array_builder(equality_rows),
        b=np.array(b),
        inequalities=array_builder(inequality_rows),
        bounds=array_builder(inequality_bounds),
        variable_fixed=np.array(fixed),
        variable_bounds=array_builder(var_bounds))

    return results

def
constraint_matrices
(
model
,
array_type
=
'dense'
,
include_vars
=
False
,
zero_tol
=
1e-6
)
:
if
array_type
not
in
(
'DataFrame'
,
'dense'
)
and
not
dok_matrix
:
raise
ValueError
(
'Sparse matrices require scipy'
)
array_builder
=
{
'dense'
:
np
.
array
,
'dok'
:
dok_matrix
,
'lil'
:
lil_matrix
,
'DataFrame'
:
pd
.
DataFrame
,
}
[
array_type
]
Problem
=
namedtuple
(
"Problem"
,
[
"equalities"
,
"b"
,
"inequalities"
,
"bounds"
,
"variable_fixed"
,
"variable_bounds"
]
)
equality_rows
=
[
]
inequality_rows
=
[
]
inequality_bounds
=
[
]
b
=
[
]
for
const
in
model
.
constraints
:
lb
=
np
.
inf
if
const
.
lb
is
else
const
.
lb
ub
=
np
.
inf
if
const
.
ub
is
else
const
.
ub
equality
=
(
ub
lb
)
<
zero_tol
coefs
=
const
.
get_linear_coefficients
(
model
.
variables
)
coefs
=
[
coefs
[
v
]
for
v
in
model
.
variables
]
if
equality
:
b
.
append
(
lb
if
abs
(
lb
)
>
zero_tol
else
0.0
)
equality_rows
.
append
(
coefs
)
else
:
inequality_rows
.
append
(
coefs
)
inequality_bounds
.
append
(
[
lb
,
ub
]
)
var_bounds
=
np
.
array
(
[
[
v
.
lb
,
v
.
ub
]
for
v
in
model
.
variables
]
)
fixed
=
var_bounds
[
:
,
1
]
var_bounds
[
:
,
0
]
<
zero_tol
results
=
Problem
(
equalities
=
array_builder
(
equality_rows
)
,
b
=
np
.
array
(
b
)
,
inequalities
=
array_builder
(
inequality_rows
)
,
bounds
=
array_builder
(
inequality_bounds
)
,
variable_fixed
=
np
.
array
(
fixed
)
,
variable_bounds
=
array_builder
(
var_bounds
)
)
return
results

Create a matrix representation of the problem .


def add_room(model, solution=None, linear=False, delta=0.03, epsilon=1E-03):
    r"""
    Add constraints and objective for ROOM.

    This function adds variables and constraints for applying regulatory
    on/off minimization (ROOM) to the model.

    Parameters
    ----------
    model : cobra.Model
        The model to add ROOM constraints and objective to.
    solution : cobra.Solution, optional
        A previous solution to use as a reference. If no solution is given,
        one will be computed using pFBA.
    linear : bool, optional
        Whether to use the linear ROOM formulation or not (default False).
    delta: float, optional
        The relative tolerance range which is additive in nature
        (default 0.03).
    epsilon: float, optional
        The absolute range of tolerance which is multiplicative
        (default 0.001).

    Notes
    -----
    The formulation used here is the same as stated in the original paper [1]_.
    The mathematical expression is given below:

    minimize \sum_{i=1}^m y^i
    s.t. Sv = 0
         v_min <= v <= v_max
         v_j = 0
         j ∈ A
         for 1 <= i <= m
         v_i - y_i(v_{max,i} - w_i^u) <= w_i^u      (1)
         v_i - y_i(v_{min,i} - w_i^l) <= w_i^l      (2)
         y_i ∈ {0,1}                                (3)
         w_i^u = w_i + \delta|w_i| + \epsilon
         w_i^l = w_i - \delta|w_i| - \epsilon

    So, for the linear version of the ROOM , constraint (3) is relaxed to
    0 <= y_i <= 1.

    See Also
    --------
    pfba : parsimonious FBA

    References
    ----------
    .. [1] Tomer Shlomi, Omer Berkman and Eytan Ruppin, "Regulatory on/off
     minimization of metabolic flux changes after genetic perturbations",
     PNAS 2005 102 (21) 7695-7700; doi:10.1073/pnas.0406346102

    """

    if 'room_old_objective' in model.solver.variables:
        raise ValueError('model is already adjusted for ROOM')

    # optimizes if no reference solution is provided
    if solution is None:
        solution = pfba(model)

    prob = model.problem
    variable = prob.Variable("room_old_objective", ub=solution.objective_value)
    constraint = prob.Constraint(
        model.solver.objective.expression - variable,
        ub=0.0,
        lb=0.0,
        name="room_old_objective_constraint"
    )
    model.objective = prob.Objective(Zero, direction="min", sloppy=True)
    vars_and_cons = [variable, constraint]
    obj_vars = []

    for rxn in model.reactions:
        flux = solution.fluxes[rxn.id]

        if linear:
            y = prob.Variable("y_" + rxn.id, lb=0, ub=1)
            delta = epsilon = 0.0
        else:
            y = prob.Variable("y_" + rxn.id, type="binary")

        # upper constraint
        w_u = flux + (delta * abs(flux)) + epsilon
        upper_const = prob.Constraint(
            rxn.flux_expression - y * (rxn.upper_bound - w_u),
            ub=w_u, name="room_constraint_upper_" + rxn.id)
        # lower constraint
        w_l = flux - (delta * abs(flux)) - epsilon
        lower_const = prob.Constraint(
            rxn.flux_expression - y * (rxn.lower_bound - w_l),
            lb=w_l, name="room_constraint_lower_" + rxn.id)
        vars_and_cons.extend([y, upper_const, lower_const])
        obj_vars.append(y)

    model.add_cons_vars(vars_and_cons)
    model.objective.set_linear_coefficients({v: 1.0 for v in obj_vars})

r Add constraints and objective for ROOM .


def sample(model, n, method="optgp", thinning=100, processes=1, seed=None):
    """Sample valid flux distributions from a cobra model.

    The function samples valid flux distributions from a cobra model.
    Currently we support two methods:

    1. 'optgp' (default) which uses the OptGPSampler that supports parallel
        sampling [1]_. Requires large numbers of samples to be performant
        (n < 1000). For smaller samples 'achr' might be better suited.

    or

    2. 'achr' which uses artificial centering hit-and-run. This is a single
       process method with good convergence [2]_.

    Parameters
    ----------
    model : cobra.Model
        The model from which to sample flux distributions.
    n : int
        The number of samples to obtain. When using 'optgp' this must be a
        multiple of `processes`, otherwise a larger number of samples will be
        returned.
    method : str, optional
        The sampling algorithm to use.
    thinning : int, optional
        The thinning factor of the generated sampling chain. A thinning of 10
        means samples are returned every 10 steps. Defaults to 100 which in
        benchmarks gives approximately uncorrelated samples. If set to one
        will return all iterates.
    processes : int, optional
        Only used for 'optgp'. The number of processes used to generate
        samples.
    seed : int > 0, optional
        The random number seed to be used. Initialized to current time stamp
        if None.

    Returns
    -------
    pandas.DataFrame
        The generated flux samples. Each row corresponds to a sample of the
        fluxes and the columns are the reactions.

    Notes
    -----
    The samplers have a correction method to ensure equality feasibility for
    long-running chains, however this will only work for homogeneous models,
    meaning models with no non-zero fixed variables or constraints (
    right-hand side of the equalities are zero).

    References
    ----------
    .. [1] Megchelenbrink W, Huynen M, Marchiori E (2014)
       optGpSampler: An Improved Tool for Uniformly Sampling the Solution-Space
       of Genome-Scale Metabolic Networks.
       PLoS ONE 9(2): e86587.
    .. [2] Direction Choice for Accelerated Convergence in Hit-and-Run Sampling
       David E. Kaufman Robert L. Smith
       Operations Research 199846:1 , 84-95

    """

    if method == "optgp":
        sampler = OptGPSampler(model, processes, thinning=thinning, seed=seed)
    elif method == "achr":
        sampler = ACHRSampler(model, thinning=thinning, seed=seed)
    else:
        raise ValueError("method must be 'optgp' or 'achr'!")

    return pandas.DataFrame(columns=[rxn.id for rxn in model.reactions],
                            data=sampler.sample(n))

def
sample
(
model
,
n
,
method
=
"optgp"
,
thinning
=
100
,
processes
=
1
,
seed
=
)
:
if
method
==
"optgp"
:
sampler
=
OptGPSampler
(
model
,
processes
,
thinning
=
thinning
,
seed
=
seed
)
elif
method
==
"achr"
:
sampler
=
ACHRSampler
(
model
,
thinning
=
thinning
,
seed
=
seed
)
else
:
raise
ValueError
(
"method must be 'optgp' or 'achr'!"
)
return
pandas
.
DataFrame
(
columns
=
[
rxn
.
id
for
rxn
in
model
.
reactions
]
,
data
=
sampler
.
sample
(
n
)
)

Sample valid flux distributions from a cobra model .


def optimizely(parser, token):
    """
    Optimizely template tag.

    Renders Javascript code to set-up A/B testing.  You must supply
    your Optimizely account number in the ``OPTIMIZELY_ACCOUNT_NUMBER``
    setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return OptimizelyNode()

def
optimizely
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
OptimizelyNode
(
)


def clicky(parser, token):
    """
    Clicky tracking template tag.

    Renders Javascript code to track page visits.  You must supply
    your Clicky Site ID (as a string) in the ``CLICKY_SITE_ID``
    setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return ClickyNode()

def
clicky
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
ClickyNode
(
)


def chartbeat_top(parser, token):
    """
    Top Chartbeat template tag.

    Render the top Javascript code for Chartbeat.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return ChartbeatTopNode()

def
chartbeat_top
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
ChartbeatTopNode
(
)


def chartbeat_bottom(parser, token):
    """
    Bottom Chartbeat template tag.

    Render the bottom Javascript code for Chartbeat.  You must supply
    your Chartbeat User ID (as a string) in the ``CHARTBEAT_USER_ID``
    setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return ChartbeatBottomNode()

def
chartbeat_bottom
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
ChartbeatBottomNode
(
)


def woopra(parser, token):
    """
    Woopra tracking template tag.

    Renders Javascript code to track page visits.  You must supply
    your Woopra domain in the ``WOOPRA_DOMAIN`` setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return WoopraNode()

def
woopra
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
WoopraNode
(
)


def spring_metrics(parser, token):
    """
    Spring Metrics tracking template tag.

    Renders Javascript code to track page visits.  You must supply
    your Spring Metrics Tracking ID in the
    ``SPRING_METRICS_TRACKING_ID`` setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return SpringMetricsNode()

def
spring_metrics
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
SpringMetricsNode
(
)


def kiss_insights(parser, token):
    """
    KISSinsights set-up template tag.

    Renders Javascript code to set-up surveys.  You must supply
    your account number and site code in the
    ``KISS_INSIGHTS_ACCOUNT_NUMBER`` and ``KISS_INSIGHTS_SITE_CODE``
    settings.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return KissInsightsNode()

def
kiss_insights
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
KissInsightsNode
(
)


def matomo(parser, token):
    """
    Matomo tracking template tag.

    Renders Javascript code to track page visits.  You must supply
    your Matomo domain (plus optional URI path), and tracked site ID
    in the ``MATOMO_DOMAIN_PATH`` and the ``MATOMO_SITE_ID`` setting.

    Custom variables can be passed in the ``matomo_vars`` context
    variable.  It is an iterable of custom variables as tuples like:
    ``(index, name, value[, scope])`` where scope may be ``'page'``
    (default) or ``'visit'``.  Index should be an integer and the
    other parameters should be strings.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return MatomoNode()

def
matomo
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
MatomoNode
(
)


def snapengage(parser, token):
    """
    SnapEngage set-up template tag.

    Renders Javascript code to set-up SnapEngage chat.  You must supply
    your widget ID in the ``SNAPENGAGE_WIDGET_ID`` setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return SnapEngageNode()

def
snapengage
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
SnapEngageNode
(
)


def performable(parser, token):
    """
    Performable template tag.

    Renders Javascript code to set-up Performable tracking.  You must
    supply your Performable API key in the ``PERFORMABLE_API_KEY``
    setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return PerformableNode()

def
performable
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
PerformableNode
(
)


def _hashable_bytes(data):
    """
    Coerce strings to hashable bytes.
    """
    if isinstance(data, bytes):
        return data
    elif isinstance(data, str):
        return data.encode('ascii')  # Fail on anything non-ASCII.
    else:
        raise TypeError(data)

def
_hashable_bytes
(
data
)
:
if
isinstance
(
data
,
bytes
)
:
return
data
elif
isinstance
(
data
,
str
)
:
return
data
.
encode
(
'ascii'
)
# Fail on anything non-ASCII.
else
:
raise
TypeError
(
data
)


def intercom_user_hash(data):
    """
    Return a SHA-256 HMAC `user_hash` as expected by Intercom, if configured.

    Return None if the `INTERCOM_HMAC_SECRET_KEY` setting is not configured.
    """
    if getattr(settings, 'INTERCOM_HMAC_SECRET_KEY', None):
        return hmac.new(
            key=_hashable_bytes(settings.INTERCOM_HMAC_SECRET_KEY),
            msg=_hashable_bytes(data),
            digestmod=hashlib.sha256,
        ).hexdigest()
    else:
        return None

def intercom_user_hash ( data ) : if getattr ( settings , 'INTERCOM_HMAC_SECRET_KEY' , None ) : return hmac . new ( key = _hashable_bytes ( settings . INTERCOM_HMAC_SECRET_KEY ) , msg = _hashable_bytes ( data ) , digestmod = hashlib . sha256 , ) . hexdigest ( ) else : return None

Return a SHA - 256 HMAC user_hash as expected by Intercom if configured .


def intercom(parser, token):
    """
    Intercom.io template tag.

    Renders Javascript code to intercom.io testing.  You must supply
    your APP ID account number in the ``INTERCOM_APP_ID``
    setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return IntercomNode()

def
intercom
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
IntercomNode
(
)


def uservoice(parser, token):
    """
    UserVoice tracking template tag.

    Renders Javascript code to track page visits.  You must supply
    your UserVoice Widget Key in the ``USERVOICE_WIDGET_KEY``
    setting or the ``uservoice_widget_key`` template context variable.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return UserVoiceNode()

def
uservoice
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
UserVoiceNode
(
)


def kiss_metrics(parser, token):
    """
    KISSinsights tracking template tag.

    Renders Javascript code to track page visits.  You must supply
    your KISSmetrics API key in the ``KISS_METRICS_API_KEY``
    setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return KissMetricsNode()

def
kiss_metrics
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
KissMetricsNode
(
)


def piwik(parser, token):
    """
    Piwik tracking template tag.

    Renders Javascript code to track page visits.  You must supply
    your Piwik domain (plus optional URI path), and tracked site ID
    in the ``PIWIK_DOMAIN_PATH`` and the ``PIWIK_SITE_ID`` setting.

    Custom variables can be passed in the ``piwik_vars`` context
    variable.  It is an iterable of custom variables as tuples like:
    ``(index, name, value[, scope])`` where scope may be ``'page'``
    (default) or ``'visit'``.  Index should be an integer and the
    other parameters should be strings.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return PiwikNode()

def
piwik
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
PiwikNode
(
)


def get_required_setting(setting, value_re, invalid_msg):
    """
    Return a constant from ``django.conf.settings``.  The `setting`
    argument is the constant name, the `value_re` argument is a regular
    expression used to validate the setting value and the `invalid_msg`
    argument is used as exception message if the value is not valid.
    """
    try:
        value = getattr(settings, setting)
    except AttributeError:
        raise AnalyticalException("%s setting: not found" % setting)
    if not value:
        raise AnalyticalException("%s setting is not set" % setting)
    value = str(value)
    if not value_re.search(value):
        raise AnalyticalException("%s setting: %s: '%s'"
                                  % (setting, invalid_msg, value))
    return value

def
get_required_setting
(
setting
,
value_re
,
invalid_msg
)
:
try
:
value
=
getattr
(
settings
,
setting
)
except
AttributeError
:
raise
AnalyticalException
(
"%s setting: not found"
%
setting
)
if
not
value
:
raise
AnalyticalException
(
"%s setting is not set"
%
setting
)
value
=
str
(
value
)
if
not
value_re
.
search
(
value
)
:
raise
AnalyticalException
(
"%s setting: %s: '%s'"
%
(
setting
,
invalid_msg
,
value
)
)
return
value

Return a constant from django . conf . settings . The setting argument is the constant name the value_re argument is a regular expression used to validate the setting value and the invalid_msg argument is used as exception message if the value is not valid .


def get_user_from_context(context):
    """
    Get the user instance from the template context, if possible.

    If the context does not contain a `request` or `user` attribute,
    `None` is returned.
    """
    try:
        return context['user']
    except KeyError:
        pass
    try:
        request = context['request']
        return request.user
    except (KeyError, AttributeError):
        pass
    return None

def get_user_from_context ( context ) : try : return context [ 'user' ] except KeyError : pass try : request = context [ 'request' ] return request . user except ( KeyError , AttributeError ) : pass return None

Get the user instance from the template context if possible .


def get_identity(context, prefix=None, identity_func=None, user=None):
    """
    Get the identity of a logged in user from a template context.

    The `prefix` argument is used to provide different identities to
    different analytics services.  The `identity_func` argument is a
    function that returns the identity of the user; by default the
    identity is the username.
    """
    if prefix is not None:
        try:
            return context['%s_identity' % prefix]
        except KeyError:
            pass
    try:
        return context['analytical_identity']
    except KeyError:
        pass
    if getattr(settings, 'ANALYTICAL_AUTO_IDENTIFY', True):
        try:
            if user is None:
                user = get_user_from_context(context)
            if get_user_is_authenticated(user):
                if identity_func is not None:
                    return identity_func(user)
                else:
                    return user.get_username()
        except (KeyError, AttributeError):
            pass
    return None

def get_identity ( context , prefix = None , identity_func = None , user = None ) : if prefix is not None : try : return context [ '%s_identity' % prefix ] except KeyError : pass try : return context [ 'analytical_identity' ] except KeyError : pass if getattr ( settings , 'ANALYTICAL_AUTO_IDENTIFY' , True ) : try : if user is None : user = get_user_from_context ( context ) if get_user_is_authenticated ( user ) : if identity_func is not None : return identity_func ( user ) else : return user . get_username ( ) except ( KeyError , AttributeError ) : pass return None

Get the identity of a logged in user from a template context .


def is_internal_ip(context, prefix=None):
    """
    Return whether the visitor is coming from an internal IP address,
    based on information from the template context.

    The prefix is used to allow different analytics services to have
    different notions of internal addresses.
    """
    try:
        request = context['request']
        remote_ip = request.META.get('HTTP_X_FORWARDED_FOR', '')
        if not remote_ip:
            remote_ip = request.META.get('REMOTE_ADDR', '')
        if not remote_ip:
            return False

        internal_ips = None
        if prefix is not None:
            internal_ips = getattr(settings, '%s_INTERNAL_IPS' % prefix, None)
        if internal_ips is None:
            internal_ips = getattr(settings, 'ANALYTICAL_INTERNAL_IPS', None)
        if internal_ips is None:
            internal_ips = getattr(settings, 'INTERNAL_IPS', None)

        return remote_ip in (internal_ips or [])
    except (KeyError, AttributeError):
        return False

def is_internal_ip ( context , prefix = None ) : try : request = context [ 'request' ] remote_ip = request . META . get ( 'HTTP_X_FORWARDED_FOR' , '' ) if not remote_ip : remote_ip = request . META . get ( 'REMOTE_ADDR' , '' ) if not remote_ip : return False internal_ips = None if prefix is not None : internal_ips = getattr ( settings , '%s_INTERNAL_IPS' % prefix , None ) if internal_ips is None : internal_ips = getattr ( settings , 'ANALYTICAL_INTERNAL_IPS' , None ) if internal_ips is None : internal_ips = getattr ( settings , 'INTERNAL_IPS' , None ) return remote_ip in ( internal_ips or [ ] ) except ( KeyError , AttributeError ) : return False

Return whether the visitor is coming from an internal IP address based on information from the template context .


def mixpanel(parser, token):
    """
    Mixpanel tracking template tag.

    Renders Javascript code to track page visits.  You must supply
    your Mixpanel token in the ``MIXPANEL_API_TOKEN`` setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return MixpanelNode()

def
mixpanel
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
MixpanelNode
(
)


def gosquared(parser, token):
    """
    GoSquared tracking template tag.

    Renders Javascript code to track page visits.  You must supply
    your GoSquared site token in the ``GOSQUARED_SITE_TOKEN`` setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return GoSquaredNode()

def
gosquared
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
GoSquaredNode
(
)


def olark(parser, token):
    """
    Olark set-up template tag.

    Renders Javascript code to set-up Olark chat.  You must supply
    your site ID in the ``OLARK_SITE_ID`` setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return OlarkNode()

def
olark
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
OlarkNode
(
)


def clickmap(parser, token):
    """
    Clickmap tracker template tag.

    Renders Javascript code to track page visits.  You must supply
    your clickmap tracker ID (as a string) in the ``CLICKMAP_TRACKER_ID``
    setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return ClickmapNode()

def
clickmap
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
ClickmapNode
(
)


def gauges(parser, token):
    """
    Gaug.es template tag.

    Renders Javascript code to gaug.es testing.  You must supply
    your Site ID account number in the ``GAUGES_SITE_ID``
    setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return GaugesNode()

def
gauges
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
GaugesNode
(
)


def crazy_egg(parser, token):
    """
    Crazy Egg tracking template tag.

    Renders Javascript code to track page clicks.  You must supply
    your Crazy Egg account number (as a string) in the
    ``CRAZY_EGG_ACCOUNT_NUMBER`` setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return CrazyEggNode()

def
crazy_egg
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
CrazyEggNode
(
)


def yandex_metrica(parser, token):
    """
    Yandex.Metrica counter template tag.

    Renders Javascript code to track page visits. You must supply
    your website counter ID (as a string) in the
    ``YANDEX_METRICA_COUNTER_ID`` setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return YandexMetricaNode()

def
yandex_metrica
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
YandexMetricaNode
(
)


def hubspot(parser, token):
    """
    HubSpot tracking template tag.

    Renders Javascript code to track page visits.  You must supply
    your portal ID (as a string) in the ``HUBSPOT_PORTAL_ID`` setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return HubSpotNode()

def
hubspot
(
parser
,
token
)
:
bits
=
token
.
split_contents
(
)
if
len
(
bits
)
>
1
:
raise
TemplateSyntaxError
(
"'%s' takes no arguments"
%
bits
[
0
]
)
return
HubSpotNode
(
)


def status_printer():
    """Manage the printing and in-place updating of a line of characters

    .. note::
        If the string is longer than a line, then in-place updating may not
        work (it will print a new line at each refresh).
    """
    last_len = [0]

    def p(s):
        s = next(spinner) + ' ' + s
        len_s = len(s)
        output = '\r' + s + (' ' * max(last_len[0] - len_s, 0))
        sys.stdout.write(output)
        sys.stdout.flush()
        last_len[0] = len_s
    return p

def
status_printer
(
)
:
last_len
=
[
0
]
def
p
(
s
)
:
s
=
next
(
spinner
)
+
' '
+
s
len_s
=
len
(
s
)
output
=
'\r'
+
s
+
(
' '
*
max
(
last_len
[
0
]
len_s
,
0
)
)
sys
.
stdout
.
write
(
output
)
sys
.
stdout
.
flush
(
)
last_len
[
0
]
=
len_s
return
p

Manage the printing and in - place updating of a line of characters


def do_apply(mutation_pk, dict_synonyms, backup):
    """Apply a specified mutant to the source code

    :param mutation_pk: mutmut cache primary key of the mutant to apply
    :type mutation_pk: str

    :param dict_synonyms: list of synonym keywords for a python dictionary
    :type dict_synonyms: list[str]

    :param backup: if :obj:`True` create a backup of the source file
        before applying the mutation
    :type backup: bool
    """
    filename, mutation_id = filename_and_mutation_id_from_pk(int(mutation_pk))

    update_line_numbers(filename)

    context = Context(
        mutation_id=mutation_id,
        filename=filename,
        dict_synonyms=dict_synonyms,
    )
    mutate_file(
        backup=backup,
        context=context,
    )
    if context.number_of_performed_mutations == 0:
        raise RuntimeError('No mutations performed.')

def
do_apply
(
mutation_pk
,
dict_synonyms
,
backup
)
:
filename
,
mutation_id
=
filename_and_mutation_id_from_pk
(
int
(
mutation_pk
)
)
update_line_numbers
(
filename
)
context
=
Context
(
mutation_id
=
mutation_id
,
filename
=
filename
,
dict_synonyms
=
dict_synonyms
,
)
mutate_file
(
backup
=
backup
,
context
=
context
,
)
if
context
.
number_of_performed_mutations
==
0
:
raise
RuntimeError
(
'No mutations performed.'
)


def popen_streaming_output(cmd, callback, timeout=None):
    """Open a subprocess and stream its output without hard-blocking.

    :param cmd: the command to execute within the subprocess
    :type cmd: str

    :param callback: function that intakes the subprocess' stdout line by line.
        It is called for each line received from the subprocess' stdout stream.
    :type callback: Callable[[Context], bool]

    :param timeout: the timeout time of the subprocess
    :type timeout: float

    :raises TimeoutError: if the subprocess' execution time exceeds
        the timeout time

    :return: the return code of the executed subprocess
    :rtype: int
    """
    if os.name == 'nt':  # pragma: no cover
        process = subprocess.Popen(
            shlex.split(cmd),
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE
        )
        stdout = process.stdout
    else:
        master, slave = os.openpty()
        process = subprocess.Popen(
            shlex.split(cmd, posix=True),
            stdout=slave,
            stderr=slave
        )
        stdout = os.fdopen(master)
        os.close(slave)

    def kill(process_):
        """Kill the specified process on Timer completion"""
        try:
            process_.kill()
        except OSError:
            pass

    # python 2-3 agnostic process timer
    timer = Timer(timeout, kill, [process])
    timer.setDaemon(True)
    timer.start()

    while process.returncode is None:
        try:
            if os.name == 'nt':  # pragma: no cover
                line = stdout.readline()
                # windows gives readline() raw stdout as a b''
                # need to decode it
                line = line.decode("utf-8")
                if line:  # ignore empty strings and None
                    callback(line.rstrip())
            else:
                while True:
                    line = stdout.readline()
                    if not line:
                        break
                    callback(line.rstrip())
        except (IOError, OSError):
            # This seems to happen on some platforms, including TravisCI.
            # It seems like it's ok to just let this pass here, you just
            # won't get as nice feedback.
            pass
        if not timer.is_alive():
            raise TimeoutError("subprocess running command '{}' timed out after {} seconds".format(cmd, timeout))
        process.poll()

    # we have returned from the subprocess cancel the timer if it is running
    timer.cancel()

    return process.returncode

Open a subprocess and stream its output without hard - blocking .


def python_source_files(path, tests_dirs):
    """Attempt to guess where the python source files to mutate are and yield
    their paths

    :param path: path to a python source file or package directory
    :type path: str

    :param tests_dirs: list of directory paths containing test files
        (we do not want to mutate these!)
    :type tests_dirs: list[str]

    :return: generator listing the paths to the python source files to mutate
    :rtype: Generator[str, None, None]
    """
    if isdir(path):
        for root, dirs, files in os.walk(path):
            dirs[:] = [d for d in dirs if os.path.join(root, d) not in tests_dirs]
            for filename in files:
                if filename.endswith('.py'):
                    yield os.path.join(root, filename)
    else:
        yield path

def python_source_files ( path , tests_dirs ) : if isdir ( path ) : for root , dirs , files in os . walk ( path ) : dirs [ : ] = [ d for d in dirs if os . path . join ( root , d ) not in tests_dirs ] for filename in files : if filename . endswith ( '.py' ) : yield os . path . join ( root , filename ) else : yield path


def compute_exit_code(config, exception=None):
    """Compute an exit code for mutmut mutation testing

    The following exit codes are available for mutmut:
     * 0 if all mutants were killed (OK_KILLED)
     * 1 if a fatal error occurred
     * 2 if one or more mutants survived (BAD_SURVIVED)
     * 4 if one or more mutants timed out (BAD_TIMEOUT)
     * 8 if one or more mutants caused tests to take twice as long (OK_SUSPICIOUS)

     Exit codes 1 to 8 will be bit-ORed so that it is possible to know what
     different mutant statuses occurred during mutation testing.

    :param exception:
    :type exception: Exception
    :param config:
    :type config: Config

    :return: integer noting the exit code of the mutation tests.
    :rtype: int
    """
    code = 0
    if exception is not None:
        code = code | 1
    if config.surviving_mutants > 0:
        code = code | 2
    if config.surviving_mutants_timeout > 0:
        code = code | 4
    if config.suspicious_mutants > 0:
        code = code | 8
    return code

def compute_exit_code ( config , exception = None ) : code = 0 if exception is not None : code = code | 1 if config . surviving_mutants > 0 : code = code | 2 if config . surviving_mutants_timeout > 0 : code = code | 4 if config . suspicious_mutants > 0 : code = code | 8 return code


def _update_advertised(self, advertised):
        """Called when advertisement data is received."""
        # Advertisement data was received, pull out advertised service UUIDs and
        # name from advertisement data.
        if 'kCBAdvDataServiceUUIDs' in advertised:
            self._advertised = self._advertised + map(cbuuid_to_uuid, advertised['kCBAdvDataServiceUUIDs'])

Called when advertisement data is received .


def _characteristics_discovered(self, service):
        """Called when GATT characteristics have been discovered."""
        # Characteristics for the specified service were discovered.  Update
        # set of discovered services and signal when all have been discovered.
        self._discovered_services.add(service)
        if self._discovered_services >= set(self._peripheral.services()):
            # Found all the services characteristics, finally time to fire the
            # service discovery complete event.
            self._discovered.set()

Called when GATT characteristics have been discovered .


def _characteristic_changed(self, characteristic):
        """Called when the specified characteristic has changed its value."""
        # Called when a characteristic is changed.  Get the on_changed handler
        # for this characteristic (if it exists) and call it.
        on_changed = self._char_on_changed.get(characteristic, None)
        if on_changed is not None:
            on_changed(characteristic.value().bytes().tobytes())
        # Also tell the characteristic that it has a new value.
        # First get the service that is associated with this characteristic.
        char = characteristic_list().get(characteristic)
        if char is not None:
            char._value_read.set()

Called when the specified characteristic has changed its value .


def _descriptor_changed(self, descriptor):
        """Called when the specified descriptor has changed its value."""
        # Tell the descriptor it has a new value to read.
        desc = descriptor_list().get(descriptor)
        if desc is not None:
            desc._value_read.set()

Called when the specified descriptor has changed its value .


def rssi(self, timeout_sec=TIMEOUT_SEC):
        """Return the RSSI signal strength in decibels."""
        # Kick off query to get RSSI, then wait for it to return asyncronously
        # when the _rssi_changed() function is called.
        self._rssi_read.clear()
        self._peripheral.readRSSI()
        if not self._rssi_read.wait(timeout_sec):
            raise RuntimeError('Exceeded timeout waiting for RSSI value!')
        return self._rssi

Return the RSSI signal strength in decibels .


def list_characteristics(self):
        """Return list of GATT characteristics that have been discovered for this
        service.
        """
        paths = self._props.Get(_SERVICE_INTERFACE, 'Characteristics')
        return map(BluezGattCharacteristic,
                   get_provider()._get_objects_by_path(paths))

def list_characteristics ( self ) : paths = self . _props . Get ( _SERVICE_INTERFACE , 'Characteristics' ) return map ( BluezGattCharacteristic , get_provider ( ) . _get_objects_by_path ( paths ) )

Return list of GATT characteristics that have been discovered for this service .


def list_descriptors(self):
        """Return list of GATT descriptors that have been discovered for this
        characteristic.
        """
        paths = self._props.Get(_CHARACTERISTIC_INTERFACE, 'Descriptors')
        return map(BluezGattDescriptor,
                   get_provider()._get_objects_by_path(paths))

def list_descriptors ( self ) : paths = self . _props . Get ( _CHARACTERISTIC_INTERFACE , 'Descriptors' ) return map ( BluezGattDescriptor , get_provider ( ) . _get_objects_by_path ( paths ) )

Return list of GATT descriptors that have been discovered for this characteristic .


def _state_changed(self, state):
        """Called when the power state changes."""
        logger.debug('Adapter state change: {0}'.format(state))
        # Handle when powered on.
        if state == 5:
            self._powered_off.clear()
            self._powered_on.set()
        # Handle when powered off.
        elif state == 4:
            self._powered_on.clear()
            self._powered_off.set()

def
_state_changed
(
self
,
state
)
:
logger
.
debug
(
'Adapter state change: {0}'
.
format
(
state
)
)
# Handle when powered on.
if
state
==
5
:
self
.
_powered_off
.
clear
(
)
self
.
_powered_on
.
set
(
)
# Handle when powered off.
elif
state
==
4
:
self
.
_powered_on
.
clear
(
)
self
.
_powered_off
.
set
(
)


def start_scan(self, timeout_sec=TIMEOUT_SEC):
        """Start scanning for BLE devices."""
        get_provider()._central_manager.scanForPeripheralsWithServices_options_(None, None)
        self._is_scanning = True

def start_scan ( self , timeout_sec = TIMEOUT_SEC ) : get_provider ( ) . _central_manager . scanForPeripheralsWithServices_options_ ( None , None ) self . _is_scanning = True


def stop_scan(self, timeout_sec=TIMEOUT_SEC):
        """Stop scanning for BLE devices."""
        get_provider()._central_manager.stopScan()
        self._is_scanning = False

def stop_scan ( self , timeout_sec = TIMEOUT_SEC ) : get_provider ( ) . _central_manager . stopScan ( ) self . _is_scanning = False


def power_on(self, timeout_sec=TIMEOUT_SEC):
        """Power on Bluetooth."""
        # Turn on bluetooth and wait for powered on event to be set.
        self._powered_on.clear()
        IOBluetoothPreferenceSetControllerPowerState(1)
        if not self._powered_on.wait(timeout_sec):
            raise RuntimeError('Exceeded timeout waiting for adapter to power on!')


def power_off(self, timeout_sec=TIMEOUT_SEC):
        """Power off Bluetooth."""
        # Turn off bluetooth.
        self._powered_off.clear()
        IOBluetoothPreferenceSetControllerPowerState(0)
        if not self._powered_off.wait(timeout_sec):
            raise RuntimeError('Exceeded timeout waiting for adapter to power off!')


def find_device(cls, timeout_sec=TIMEOUT_SEC):
        """Find the first available device that supports this service and return
        it, or None if no device is found.  Will wait for up to timeout_sec
        seconds to find the device.
        """
        return get_provider().find_device(service_uuids=cls.ADVERTISED, timeout_sec=timeout_sec)

def find_device ( cls , timeout_sec = TIMEOUT_SEC ) : return get_provider ( ) . find_device ( service_uuids = cls . ADVERTISED , timeout_sec = timeout_sec )

Find the first available device that supports this service and return it or None if no device is found . Will wait for up to timeout_sec seconds to find the device .


def discover(cls, device, timeout_sec=TIMEOUT_SEC):
        """Wait until the specified device has discovered the expected services
        and characteristics for this service.  Should be called once before other
        calls are made on the service.  Returns true if the service has been
        discovered in the specified timeout, or false if not discovered.
        """
        device.discover(cls.SERVICES, cls.CHARACTERISTICS, timeout_sec)

def discover ( cls , device , timeout_sec = TIMEOUT_SEC ) : device . discover ( cls . SERVICES , cls . CHARACTERISTICS , timeout_sec )

Wait until the specified device has discovered the expected services and characteristics for this service . Should be called once before other calls are made on the service . Returns true if the service has been discovered in the specified timeout or false if not discovered .


def find_service(self, uuid):
        """Return the first child service found that has the specified
        UUID.  Will return None if no service that matches is found.
        """
        for service in self.list_services():
            if service.uuid == uuid:
                return service
        return None

def find_service ( self , uuid ) : for service in self . list_services ( ) : if service . uuid == uuid : return service return None

Return the first child service found that has the specified UUID . Will return None if no service that matches is found .


def list_services(self):
        """Return a list of GattService objects that have been discovered for
        this device.
        """
        return map(BluezGattService,
                   get_provider()._get_objects(_SERVICE_INTERFACE,
                                               self._device.object_path))

def list_services ( self ) : return map ( BluezGattService , get_provider ( ) . _get_objects ( _SERVICE_INTERFACE , self . _device . object_path ) )

Return a list of GattService objects that have been discovered for this device .


def advertised(self):
        """Return a list of UUIDs for services that are advertised by this
        device.
        """
        uuids = []
        # Get UUIDs property but wrap it in a try/except to catch if the property
        # doesn't exist as it is optional.
        try:
            uuids = self._props.Get(_INTERFACE, 'UUIDs')
        except dbus.exceptions.DBusException as ex:
            # Ignore error if device has no UUIDs property (i.e. might not be
            # a BLE device).
            if ex.get_dbus_name() != 'org.freedesktop.DBus.Error.InvalidArgs':
                raise ex
        return [uuid.UUID(str(x)) for x in uuids]

Return a list of UUIDs for services that are advertised by this device .


def find_characteristic(self, uuid):
        """Return the first child characteristic found that has the specified
        UUID.  Will return None if no characteristic that matches is found.
        """
        for char in self.list_characteristics():
            if char.uuid == uuid:
                return char
        return None

def find_characteristic ( self , uuid ) : for char in self . list_characteristics ( ) : if char . uuid == uuid : return char return None

Return the first child characteristic found that has the specified UUID . Will return None if no characteristic that matches is found .


def find_descriptor(self, uuid):
        """Return the first child descriptor found that has the specified
        UUID.  Will return None if no descriptor that matches is found.
        """
        for desc in self.list_descriptors():
            if desc.uuid == uuid:
                return desc
        return None

def find_descriptor ( self , uuid ) : for desc in self . list_descriptors ( ) : if desc . uuid == uuid : return desc return None

Return the first child descriptor found that has the specified UUID . Will return None if no descriptor that matches is found .


def read_value(self, timeout_sec=TIMEOUT_SEC):
        """Read the value of this characteristic."""
        # Kick off a query to read the value of the characteristic, then wait
        # for the result to return asyncronously.
        self._value_read.clear()
        self._device._peripheral.readValueForCharacteristic_(self._characteristic)
        if not self._value_read.wait(timeout_sec):
            raise RuntimeError('Exceeded timeout waiting to read characteristic value!')
        return self._characteristic.value()


def write_value(self, value, write_type=0):
        """Write the specified value to this characteristic."""
        data = NSData.dataWithBytes_length_(value, len(value))
        self._device._peripheral.writeValue_forCharacteristic_type_(data,
            self._characteristic,
            write_type)

def write_value ( self , value , write_type = 0 ) : data = NSData . dataWithBytes_length_ ( value , len ( value ) ) self . _device . _peripheral . writeValue_forCharacteristic_type_ ( data , self . _characteristic , write_type )

Write the specified value to this characteristic .


def read_value(self):
        """Read the value of this descriptor."""
        pass
        # Kick off a query to read the value of the descriptor, then wait
        # for the result to return asyncronously.
        self._value_read.clear()
        self._device._peripheral.readValueForDescriptor(self._descriptor)
        if not self._value_read.wait(timeout_sec):
            raise RuntimeError('Exceeded timeout waiting to read characteristic value!')
        return self._value


def start_scan(self, timeout_sec=TIMEOUT_SEC):
        """Start scanning for BLE devices with this adapter."""
        self._scan_started.clear()
        self._adapter.StartDiscovery()
        if not self._scan_started.wait(timeout_sec):
            raise RuntimeError('Exceeded timeout waiting for adapter to start scanning!')

Start scanning for BLE devices with this adapter .


def stop_scan(self, timeout_sec=TIMEOUT_SEC):
        """Stop scanning for BLE devices with this adapter."""
        self._scan_stopped.clear()
        self._adapter.StopDiscovery()
        if not self._scan_stopped.wait(timeout_sec):
            raise RuntimeError('Exceeded timeout waiting for adapter to stop scanning!')

Stop scanning for BLE devices with this adapter .


def centralManager_didDiscoverPeripheral_advertisementData_RSSI_(self, manager, peripheral, data, rssi):
        """Called when the BLE adapter found a device while scanning, or has
        new advertisement data for a device.
        """
        logger.debug('centralManager_didDiscoverPeripheral_advertisementData_RSSI called')
        # Log name of device found while scanning.
        #logger.debug('Saw device advertised with name: {0}'.format(peripheral.name()))
        # Make sure the device is added to the list of devices and then update
        # its advertisement state.
        device = device_list().get(peripheral)
        if device is None:
            device = device_list().add(peripheral, CoreBluetoothDevice(peripheral))
        device._update_advertised(data)

Called when the BLE adapter found a device while scanning or has new advertisement data for a device .


def centralManager_didConnectPeripheral_(self, manager, peripheral):
        """Called when a device is connected."""
        logger.debug('centralManager_didConnectPeripheral called')
        # Setup peripheral delegate and kick off service discovery.  For now just
        # assume all services need to be discovered.
        peripheral.setDelegate_(self)
        peripheral.discoverServices_(None)
        # Fire connected event for device.
        device = device_list().get(peripheral)
        if device is not None:
            device._set_connected()


def centralManager_didDisconnectPeripheral_error_(self, manager, peripheral, error):
        """Called when a device is disconnected."""
        logger.debug('centralManager_didDisconnectPeripheral called')
        # Get the device and remove it from the device list, then fire its
        # disconnected event.
        device = device_list().get(peripheral)
        if device is not None:
            # Fire disconnected event and remove device from device list.
            device._set_disconnected()
            device_list().remove(peripheral)


def peripheral_didDiscoverServices_(self, peripheral, services):
        """Called when services are discovered for a device."""
        logger.debug('peripheral_didDiscoverServices called')
        # Make sure the discovered services are added to the list of known
        # services, and kick off characteristic discovery for each one.
        # NOTE: For some reason the services parameter is never set to a good
        # value, instead you must query peripheral.services() to enumerate the
        # discovered services.
        for service in peripheral.services():
            if service_list().get(service) is None:
                service_list().add(service, CoreBluetoothGattService(service))
            # Kick off characteristic discovery for this service.  Just discover
            # all characteristics for now.
            peripheral.discoverCharacteristics_forService_(None, service)

Called when services are discovered for a device .


def peripheral_didUpdateValueForCharacteristic_error_(self, peripheral, characteristic, error):
        """Called when characteristic value was read or updated."""
        logger.debug('peripheral_didUpdateValueForCharacteristic_error called')
        # Stop if there was some kind of error.
        if error is not None:
            return
        # Notify the device about the updated characteristic value.
        device = device_list().get(peripheral)
        if device is not None:
            device._characteristic_changed(characteristic)

Called when characteristic value was read or updated .


def peripheral_didUpdateValueForDescriptor_error_(self, peripheral, descriptor, error):
        """Called when descriptor value was read or updated."""
        logger.debug('peripheral_didUpdateValueForDescriptor_error called')
        # Stop if there was some kind of error.
        if error is not None:
            return
        # Notify the device about the updated descriptor value.
        device = device_list().get(peripheral)
        if device is not None:
            device._descriptor_changed(descriptor)

Called when descriptor value was read or updated .


def peripheral_didReadRSSI_error_(self, peripheral, rssi, error):
        """Called when a new RSSI value for the peripheral is available."""
        logger.debug('peripheral_didReadRSSI_error called')
        # Note this appears to be completely undocumented at the time of this
        # writing.  Can see more details at:
        #  http://stackoverflow.com/questions/25952218/ios-8-corebluetooth-deprecated-rssi-methods
        # Stop if there was some kind of error.
        if error is not None:
            return
        # Notify the device about the updated RSSI value.
        device = device_list().get(peripheral)
        if device is not None:
            device._rssi_changed(rssi)

Called when a new RSSI value for the peripheral is available .


def initialize(self):
        """Initialize the BLE provider.  Must be called once before any other
        calls are made to the provider.
        """
        # Setup the central manager and its delegate.
        self._central_manager = CBCentralManager.alloc()
        self._central_manager.initWithDelegate_queue_options_(self._central_delegate,
                                                              None, None)

Initialize the BLE provider . Must be called once before any other calls are made to the provider .


def disconnect_devices(self, service_uuids):
        """Disconnect any connected devices that have any of the specified
        service UUIDs.
        """
        # Get list of connected devices with specified services.
        cbuuids = map(uuid_to_cbuuid, service_uuids)
        for device in self._central_manager.retrieveConnectedPeripheralsWithServices_(cbuuids):
            self._central_manager.cancelPeripheralConnection_(device)

Disconnect any connected devices that have any of the specified service UUIDs .


def initialize(self):
        """Initialize bluez DBus communication.  Must be called before any other
        calls are made!
        """
        # Ensure GLib's threading is initialized to support python threads, and
        # make a default mainloop that all DBus objects will inherit.  These
        # commands MUST execute before any other DBus commands!
        GObject.threads_init()
        dbus.mainloop.glib.threads_init()
        # Set the default main loop, this also MUST happen before other DBus calls.
        self._mainloop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
        # Get the main DBus system bus and root bluez object.
        self._bus = dbus.SystemBus()
        self._bluez = dbus.Interface(self._bus.get_object('org.bluez', '/'),
                                     'org.freedesktop.DBus.ObjectManager')

Initialize bluez DBus communication . Must be called before any other calls are made!


def clear_cached_data(self):
        """Clear any internally cached BLE device data.  Necessary in some cases
        to prevent issues with stale device data getting cached by the OS.
        """
        # Go through and remove any device that isn't currently connected.
        for device in self.list_devices():
            # Skip any connected device.
            if device.is_connected:
                continue
            # Remove this device.  First get the adapter associated with the device.
            adapter = dbus.Interface(self._bus.get_object('org.bluez', device._adapter),
                                     _ADAPTER_INTERFACE)
            # Now call RemoveDevice on the adapter to remove the device from
            # bluez's DBus hierarchy.
            adapter.RemoveDevice(device._device.object_path)

Clear any internally cached BLE device data . Necessary in some cases to prevent issues with stale device data getting cached by the OS .


def disconnect_devices(self, service_uuids=[]):
        """Disconnect any connected devices that have the specified list of
        service UUIDs.  The default is an empty list which means all devices
        are disconnected.
        """
        service_uuids = set(service_uuids)
        for device in self.list_devices():
            # Skip devices that aren't connected.
            if not device.is_connected:
                continue
            device_uuids = set(map(lambda x: x.uuid, device.list_services()))
            if device_uuids >= service_uuids:
                # Found a device that has at least the requested services, now
                # disconnect from it.
                device.disconnect()

Disconnect any connected devices that have the specified list of service UUIDs . The default is an empty list which means all devices are disconnected .


def _get_objects(self, interface, parent_path='/org/bluez'):
        """Return a list of all bluez DBus objects that implement the requested
        interface name and are under the specified path.  The default is to
        search devices under the root of all bluez objects.
        """
        # Iterate through all the objects in bluez's DBus hierarchy and return
        # any that implement the requested interface under the specified path.
        parent_path = parent_path.lower()
        objects = []
        for opath, interfaces in iteritems(self._bluez.GetManagedObjects()):
            if interface in interfaces.keys() and opath.lower().startswith(parent_path):
                objects.append(self._bus.get_object('org.bluez', opath))
        return objects

Return a list of all bluez DBus objects that implement the requested interface name and are under the specified path . The default is to search devices under the root of all bluez objects .


def _get_objects_by_path(self, paths):
        """Return a list of all bluez DBus objects from the provided list of paths.
        """
        return map(lambda x: self._bus.get_object('org.bluez', x), paths)

def _get_objects_by_path ( self , paths ) : return map ( lambda x : self . _bus . get_object ( 'org.bluez' , x ) , paths )

Return a list of all bluez DBus objects from the provided list of paths .


def _print_tree(self):
        """Print tree of all bluez objects, useful for debugging."""
        # This is based on the bluez sample code get-managed-objects.py.
        objects = self._bluez.GetManagedObjects()
        for path in objects.keys():
            print("[ %s ]" % (path))
            interfaces = objects[path]
            for interface in interfaces.keys():
                if interface in ["org.freedesktop.DBus.Introspectable",
                            "org.freedesktop.DBus.Properties"]:
                    continue
                print("    %s" % (interface))
                properties = interfaces[interface]
                for key in properties.keys():
                    print("      %s = %s" % (key, properties[key]))

Print tree of all bluez objects useful for debugging .


def find_device(self, service_uuids=[], name=None, timeout_sec=TIMEOUT_SEC):
        """Return the first device that advertises the specified service UUIDs or
        has the specified name. Will wait up to timeout_sec seconds for the device
        to be found, and if the timeout is zero then it will not wait at all and
        immediately return a result.  When no device is found a value of None is
        returned.
        """
        start = time.time()
        while True:
            # Call find_devices and grab the first result if any are found.
            found = self.find_devices(service_uuids, name)
            if len(found) > 0:
                return found[0]
            # No device was found.  Check if the timeout is exceeded and wait to
            # try again.
            if time.time()-start >= timeout_sec:
                # Failed to find a device within the timeout.
                return None
            time.sleep(1)

Return the first device that advertises the specified service UUIDs or has the specified name . Will wait up to timeout_sec seconds for the device to be found and if the timeout is zero then it will not wait at all and immediately return a result . When no device is found a value of None is returned .


def get_all(self, cbobjects):
        """Retrieve a list of metadata objects associated with the specified
        list of CoreBluetooth objects.  If an object cannot be found then an
        exception is thrown.
        """
        try:
            with self._lock:
                return [self._metadata[x] for x in cbobjects]
        except KeyError:
            # Note that if this error gets thrown then the assumption that OSX
            # will pass back to callbacks the exact CoreBluetooth objects that
            # were used previously is broken! (i.e. the CoreBluetooth objects
            # are not stateless)
            raise RuntimeError('Failed to find expected metadata for CoreBluetooth object!')

Retrieve a list of metadata objects associated with the specified list of CoreBluetooth objects . If an object cannot be found then an exception is thrown .


def add(self, cbobject, metadata):
        """Add the specified CoreBluetooth item with the associated metadata if
        it doesn't already exist.  Returns the newly created or preexisting
        metadata item.
        """
        with self._lock:
            if cbobject not in self._metadata:
                self._metadata[cbobject] = metadata
            return self._metadata[cbobject]

def add ( self , cbobject , metadata ) : with self . _lock : if cbobject not in self . _metadata : self . _metadata [ cbobject ] = metadata return self . _metadata [ cbobject ]

Add the specified CoreBluetooth item with the associated metadata if it doesn t already exist . Returns the newly created or preexisting metadata item .


def remove(self, cbobject):
        """Remove any metadata associated with the provided CoreBluetooth object.
        """
        with self._lock:
            if cbobject in self._metadata:
                del self._metadata[cbobject]

def remove ( self , cbobject ) : with self . _lock : if cbobject in self . _metadata : del self . _metadata [ cbobject ]

Remove any metadata associated with the provided CoreBluetooth object .


def cbuuid_to_uuid(cbuuid):
    """Convert Objective-C CBUUID type to native Python UUID type."""
    data = cbuuid.data().bytes()

    template = '{:0>8}-0000-1000-8000-00805f9b34fb' if len(data) <= 4 else '{:0>32}'
    value = template.format(hexlify(data.tobytes()[:16]).decode('ascii'))
    return uuid.UUID(hex=value)

def cbuuid_to_uuid ( cbuuid ) : data = cbuuid . data ( ) . bytes ( ) template = '{:0>8}-0000-1000-8000-00805f9b34fb' if len ( data ) <= 4 else '{:0>32}' value = template . format ( hexlify ( data . tobytes ( ) [ : 16 ] ) . decode ( 'ascii' ) ) return uuid . UUID ( hex = value )

Convert Objective - C CBUUID type to native Python UUID type .


def set_color(self, r, g, b):
        """Set the red, green, blue color of the bulb."""
        # See more details on the bulb's protocol from this guide:
        #   https://learn.adafruit.com/reverse-engineering-a-bluetooth-low-energy-light-bulb/overview
        command = '\x58\x01\x03\x01\xFF\x00{0}{1}{2}'.format(chr(r & 0xFF),
                                                             chr(g & 0xFF),
                                                             chr(b & 0xFF))
        self._color.write_value(command)

Set the red green blue color of the bulb .


def get_provider():
    """Return an instance of the BLE provider for the current platform."""
    global _provider
    # Set the provider based on the current platform.
    if _provider is None:
        if sys.platform.startswith('linux'):
            # Linux platform
            from .bluez_dbus.provider import BluezProvider
            _provider = BluezProvider()
        elif sys.platform == 'darwin':
            # Mac OSX platform
            from .corebluetooth.provider import CoreBluetoothProvider
            _provider = CoreBluetoothProvider()
        else:
            # Unsupported platform
            raise RuntimeError('Sorry the {0} platform is not supported by the BLE library!'.format(sys.platform))
    return _provider

Return an instance of the BLE provider for the current platform .


def toBigInt(byteArray):
    """Convert the byte array to a BigInteger"""
    array = byteArray[::-1]  # reverse array
    out = 0
    for key, value in enumerate(array):
        decoded = struct.unpack("B", bytes([value]))[0]
        out = out | decoded << key * 8
    return out

def
toBigInt
(
byteArray
)
:
array
=
byteArray
[
:
:
1
]
# reverse array
out
=
0
for
key
,
value
in
enumerate
(
array
)
:
decoded
=
struct
.
unpack
(
"B"
,
bytes
(
[
value
]
)
)
[
0
]
out
=
out
|
decoded
<<
key
*
8
return
out


def encryptPassword(self, login, passwd):
        """Encrypt credentials using the google publickey, with the
        RSA algorithm"""

        # structure of the binary key:
        #
        # *-------------------------------------------------------*
        # | modulus_length | modulus | exponent_length | exponent |
        # *-------------------------------------------------------*
        #
        # modulus_length and exponent_length are uint32
        binaryKey = b64decode(config.GOOGLE_PUBKEY)
        # modulus
        i = utils.readInt(binaryKey, 0)
        modulus = utils.toBigInt(binaryKey[4:][0:i])
        # exponent
        j = utils.readInt(binaryKey, i + 4)
        exponent = utils.toBigInt(binaryKey[i + 8:][0:j])

        # calculate SHA1 of the pub key
        digest = hashes.Hash(hashes.SHA1(), backend=default_backend())
        digest.update(binaryKey)
        h = b'\x00' + digest.finalize()[0:4]

        # generate a public key
        der_data = encode_dss_signature(modulus, exponent)
        publicKey = load_der_public_key(der_data, backend=default_backend())

        # encrypt email and password using pubkey
        to_be_encrypted = login.encode() + b'\x00' + passwd.encode()
        ciphertext = publicKey.encrypt(
            to_be_encrypted,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA1()),
                algorithm=hashes.SHA1(),
                label=None
            )
        )

        return urlsafe_b64encode(h + ciphertext)

Encrypt credentials using the google publickey with the RSA algorithm


def getHeaders(self, upload_fields=False):
        """Return the default set of request headers, which
        can later be expanded, based on the request type"""

        if upload_fields:
            headers = self.deviceBuilder.getDeviceUploadHeaders()
        else:
            headers = self.deviceBuilder.getBaseHeaders()
        if self.gsfId is not None:
            headers["X-DFE-Device-Id"] = "{0:x}".format(self.gsfId)
        if self.authSubToken is not None:
            headers["Authorization"] = "GoogleLogin auth=%s" % self.authSubToken
        if self.device_config_token is not None:
            headers["X-DFE-Device-Config-Token"] = self.device_config_token
        if self.deviceCheckinConsistencyToken is not None:
            headers["X-DFE-Device-Checkin-Consistency-Token"] = self.deviceCheckinConsistencyToken
        if self.dfeCookie is not None:
            headers["X-DFE-Cookie"] = self.dfeCookie
        return headers

Return the default set of request headers which can later be expanded based on the request type


def search(self, query):
        """ Search the play store for an app.

        nb_result (int): is the maximum number of result to be returned

        offset (int): is used to take result starting from an index.
        """
        if self.authSubToken is None:
            raise LoginError("You need to login before executing any request")

        path = SEARCH_URL + "?c=3&q={}".format(requests.utils.quote(query))
        # FIXME: not sure if this toc call should be here
        self.toc()
        data = self.executeRequestApi2(path)
        if utils.hasPrefetch(data):
            response = data.preFetch[0].response
        else:
            response = data
        resIterator = response.payload.listResponse.doc
        return list(map(utils.parseProtobufObj, resIterator))


def details(self, packageName):
        """Get app details from a package name.

        packageName is the app unique ID (usually starting with 'com.')."""
        path = DETAILS_URL + "?doc={}".format(requests.utils.quote(packageName))
        data = self.executeRequestApi2(path)
        return utils.parseProtobufObj(data.payload.detailsResponse.docV2)

def details ( self , packageName ) : path = DETAILS_URL + "?doc={}" . format ( requests . utils . quote ( packageName ) ) data = self . executeRequestApi2 ( path ) return utils . parseProtobufObj ( data . payload . detailsResponse . docV2 )


def bulkDetails(self, packageNames):
        """Get several apps details from a list of package names.

        This is much more efficient than calling N times details() since it
        requires only one request. If an item is not found it returns an empty object
        instead of throwing a RequestError('Item not found') like the details() function

        Args:
            packageNames (list): a list of app IDs (usually starting with 'com.').

        Returns:
            a list of dictionaries containing docv2 data, or None
            if the app doesn't exist"""

        params = {'au': '1'}
        req = googleplay_pb2.BulkDetailsRequest()
        req.docid.extend(packageNames)
        data = req.SerializeToString()
        message = self.executeRequestApi2(BULK_URL,
                                          post_data=data.decode("utf-8"),
                                          content_type=CONTENT_TYPE_PROTO,
                                          params=params)
        response = message.payload.bulkDetailsResponse
        return [None if not utils.hasDoc(entry) else
                utils.parseProtobufObj(entry.doc)
                for entry in response.entry]

def bulkDetails ( self , packageNames ) : params = { 'au' : '1' } req = googleplay_pb2 . BulkDetailsRequest ( ) req . docid . extend ( packageNames ) data = req . SerializeToString ( ) message = self . executeRequestApi2 ( BULK_URL , post_data = data . decode ( "utf-8" ) , content_type = CONTENT_TYPE_PROTO , params = params ) response = message . payload . bulkDetailsResponse return [ None if not utils . hasDoc ( entry ) else utils . parseProtobufObj ( entry . doc ) for entry in response . entry ]

Get several apps details from a list of package names .


def list(self, cat, ctr=None, nb_results=None, offset=None):
        """List all possible subcategories for a specific category. If
        also a subcategory is provided, list apps from this category.

        Args:
            cat (str): category id
            ctr (str): subcategory id
            nb_results (int): if a subcategory is specified, limit number
                of results to this number
            offset (int): if a subcategory is specified, start counting from this
                result
        Returns:
            A list of categories. If subcategory is specified, a list of apps in this
            category.
        """
        path = LIST_URL + "?c=3&cat={}".format(requests.utils.quote(cat))
        if ctr is not None:
            path += "&ctr={}".format(requests.utils.quote(ctr))
        if nb_results is not None:
            path += "&n={}".format(requests.utils.quote(str(nb_results)))
        if offset is not None:
            path += "&o={}".format(requests.utils.quote(str(offset)))
        data = self.executeRequestApi2(path)
        clusters = []
        docs = []
        if ctr is None:
            # list subcategories
            for pf in data.preFetch:
                for cluster in pf.response.payload.listResponse.doc:
                    clusters.extend(cluster.child)
            return [c.docid for c in clusters]
        else:
            apps = []
            for d in data.payload.listResponse.doc: # categories
                for c in d.child: # sub-category
                    for a in c.child: # app
                        apps.append(utils.parseProtobufObj(a))
            return apps

def
list
(
self
,
cat
,
ctr
=
,
nb_results
=
,
offset
=
)
:
path
=
LIST_URL
+
"?c=3&cat={}"
.
format
(
requests
.
utils
.
quote
(
cat
)
)
if
ctr
is
not
:
path
+=
"&ctr={}"
.
format
(
requests
.
utils
.
quote
(
ctr
)
)
if
nb_results
is
not
:
path
+=
"&n={}"
.
format
(
requests
.
utils
.
quote
(
str
(
nb_results
)
)
)
if
offset
is
not
:
path
+=
"&o={}"
.
format
(
requests
.
utils
.
quote
(
str
(
offset
)
)
)
data
=
self
.
executeRequestApi2
(
path
)
clusters
=
[
]
docs
=
[
]
if
ctr
is
:
# list subcategories
for
pf
in
data
.
preFetch
:
for
cluster
in
pf
.
response
.
payload
.
listResponse
.
doc
:
clusters
.
extend
(
cluster
.
child
)
return
[
c
.
docid
for
c
in
clusters
]
else
:
apps
=
[
]
for
d
in
data
.
payload
.
listResponse
.
doc
:
# categories
for
c
in
d
.
child
:
# sub-category
for
a
in
c
.
child
:
# app
apps
.
append
(
utils
.
parseProtobufObj
(
a
)
)
return
apps

List all possible subcategories for a specific category . If also a subcategory is provided list apps from this category .


def reviews(self, packageName, filterByDevice=False, sort=2,
                nb_results=None, offset=None):
        """Browse reviews for an application

        Args:
            packageName (str): app unique ID.
            filterByDevice (bool): filter results for current device
            sort (int): sorting criteria (values are unknown)
            nb_results (int): max number of reviews to return
            offset (int): return reviews starting from an offset value

        Returns:
            dict object containing all the protobuf data returned from
            the api
        """
        # TODO: select the number of reviews to return
        path = REVIEWS_URL + "?doc={}&sort={}".format(requests.utils.quote(packageName), sort)
        if nb_results is not None:
            path += "&n={}".format(nb_results)
        if offset is not None:
            path += "&o={}".format(offset)
        if filterByDevice:
            path += "&dfil=1"
        data = self.executeRequestApi2(path)
        output = []
        for review in data.payload.reviewResponse.getResponse.review:
            output.append(utils.parseProtobufObj(review))
        return output


def delivery(self, packageName, versionCode=None, offerType=1,
                 downloadToken=None, expansion_files=False):
        """Download an already purchased app.

        Args:
            packageName (str): app unique ID (usually starting with 'com.')
            versionCode (int): version to download
            offerType (int): different type of downloads (mostly unused for apks)
            downloadToken (str): download token returned by 'purchase' API
            progress_bar (bool): wether or not to print a progress bar to stdout

        Returns:
            Dictionary containing apk data and a list of expansion files. As stated
            in android documentation, there can be at most 2 expansion files, one with
            main content, and one for patching the main content. Their names should
            follow this format:

            [main|patch].<expansion-version>.<package-name>.obb

            Data to build this name string is provided in the dict object. For more
            info check https://developer.android.com/google/play/expansion-files.html
        """

        if versionCode is None:
            # pick up latest version
            versionCode = self.details(packageName).get('versionCode')

        params = {'ot': str(offerType),
                  'doc': packageName,
                  'vc': str(versionCode)}
        headers = self.getHeaders()
        if downloadToken is not None:
            params['dtok'] = downloadToken
        response = requests.get(DELIVERY_URL, headers=headers,
                                params=params, verify=ssl_verify,
                                timeout=60,
                                proxies=self.proxies_config)
        response = googleplay_pb2.ResponseWrapper.FromString(response.content)
        if response.commands.displayErrorMessage != "":
            raise RequestError(response.commands.displayErrorMessage)
        elif response.payload.deliveryResponse.appDeliveryData.downloadUrl == "":
            raise RequestError('App not purchased')
        else:
            result = {}
            result['docId'] = packageName
            result['additionalData'] = []
            downloadUrl = response.payload.deliveryResponse.appDeliveryData.downloadUrl
            cookie = response.payload.deliveryResponse.appDeliveryData.downloadAuthCookie[0]
            cookies = {
                str(cookie.name): str(cookie.value)
            }
            result['file'] = self._deliver_data(downloadUrl, cookies)
            if not expansion_files:
                return result
            for obb in response.payload.deliveryResponse.appDeliveryData.additionalFile:
                a = {}
                # fileType == 0 -> main
                # fileType == 1 -> patch
                if obb.fileType == 0:
                    obbType = 'main'
                else:
                    obbType = 'patch'
                a['type'] = obbType
                a['versionCode'] = obb.versionCode
                a['file'] = self._deliver_data(obb.downloadUrl, None)
                result['additionalData'].append(a)
            return result

def
delivery
(
self
,
packageName
,
versionCode
=
,
offerType
=
1
,
downloadToken
=
,
expansion_files
=
False
)
:
if
versionCode
is
:
# pick up latest version
versionCode
=
self
.
details
(
packageName
)
.
get
(
'versionCode'
)
params
=
{
'ot'
:
str
(
offerType
)
,
'doc'
:
packageName
,
'vc'
:
str
(
versionCode
)
}
headers
=
self
.
getHeaders
(
)
if
downloadToken
is
not
:
params
[
'dtok'
]
=
downloadToken
response
=
requests
.
get
(
DELIVERY_URL
,
headers
=
headers
,
params
=
params
,
verify
=
ssl_verify
,
timeout
=
60
,
proxies
=
self
.
proxies_config
)
response
=
googleplay_pb2
.
ResponseWrapper
.
FromString
(
response
.
content
)
if
response
.
commands
.
displayErrorMessage
!=
""
:
raise
RequestError
(
response
.
commands
.
displayErrorMessage
)
elif
response
.
payload
.
deliveryResponse
.
appDeliveryData
.
downloadUrl
==
""
:
raise
RequestError
(
'App not purchased'
)
else
:
result
=
{
}
result
[
'docId'
]
=
packageName
result
[
'additionalData'
]
=
[
]
downloadUrl
=
response
.
payload
.
deliveryResponse
.
appDeliveryData
.
downloadUrl
cookie
=
response
.
payload
.
deliveryResponse
.
appDeliveryData
.
downloadAuthCookie
[
0
]
cookies
=
{
str
(
cookie
.
name
)
:
str
(
cookie
.
value
)
}
result
[
'file'
]
=
self
.
_deliver_data
(
downloadUrl
,
cookies
)
if
not
expansion_files
:
return
result
for
obb
in
response
.
payload
.
deliveryResponse
.
appDeliveryData
.
additionalFile
:
a
=
{
}
# fileType == 0 -> main
# fileType == 1 -> patch
if
obb
.
fileType
==
0
:
obbType
=
'main'
else
:
obbType
=
'patch'
a
[
'type'
]
=
obbType
a
[
'versionCode'
]
=
obb
.
versionCode
a
[
'file'
]
=
self
.
_deliver_data
(
obb
.
downloadUrl
,
)
result
[
'additionalData'
]
.
append
(
a
)
return
result


def http_connection(timeout):
    """
    Decorator function that injects a requests.Session instance into
    the decorated function's actual parameters if not given.
    """
    def wrapper(f):
        def wrapped(*args, **kwargs):
            if not ('connection' in kwargs) or not kwargs['connection']:
                connection = requests.Session()
                kwargs['connection'] = connection
            else:
                connection = kwargs['connection']

            if not getattr(connection, 'timeout', False):
                connection.timeout = timeout
            connection.headers.update({'Content-type': 'application/json'})
            return f(*args, **kwargs)
        return wraps(f)(wrapped)
    return wrapper

def http_connection ( timeout ) : def wrapper ( f ) : def wrapped ( * args , * * kwargs ) : if not ( 'connection' in kwargs ) or not kwargs [ 'connection' ] : connection = requests . Session ( ) kwargs [ 'connection' ] = connection else : connection = kwargs [ 'connection' ] if not getattr ( connection , 'timeout' , False ) : connection . timeout = timeout connection . headers . update ( { 'Content-type' : 'application/json' } ) return f ( * args , * * kwargs ) return wraps ( f ) ( wrapped ) return wrapper

Decorator function that injects a requests . Session instance into the decorated function s actual parameters if not given .


def create_token(self, data, options=None):
        """
        Generates a secure authentication token.

        Our token format follows the JSON Web Token (JWT) standard:
        header.claims.signature

        Where:
        1) 'header' is a stringified, base64-encoded JSON object containing version and algorithm information.
        2) 'claims' is a stringified, base64-encoded JSON object containing a set of claims:
            Library-generated claims:
            'iat' -> The issued at time in seconds since the epoch as a number
            'd' -> The arbitrary JSON object supplied by the user.
            User-supplied claims (these are all optional):
            'exp' (optional) -> The expiration time of this token, as a number of seconds since the epoch.
            'nbf' (optional) -> The 'not before' time before which the token should be rejected (seconds since the epoch)
            'admin' (optional) -> If set to true, this client will bypass all security rules (use this to authenticate servers)
            'debug' (optional) -> 'set to true to make this client receive debug information about security rule execution.
            'simulate' (optional, internal-only for now) -> Set to true to neuter all API operations (listens / puts
                       will run security rules but not actually write or return data).
        3) A signature that proves the validity of this token (see: http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-07)

        For base64-encoding we use URL-safe base64 encoding. This ensures that the entire token is URL-safe
        and could, for instance, be placed as a query argument without any encoding (and this is what the JWT spec requires).

        Args:
            data - a json serializable object of data to be included in the token
            options - An optional dictionary of additional claims for the token. Possible keys include:
                a) 'expires' -- A timestamp (as a number of seconds since the epoch) denoting a time after which
                    this token should no longer be valid.
                b) 'notBefore' -- A timestamp (as a number of seconds since the epoch) denoting a time before
                    which this token should be rejected by the server.
                c) 'admin' -- Set to true to bypass all security rules (use this for your trusted servers).
                d) 'debug' -- Set to true to enable debug mode (so you can see the results of Rules API operations)
                e) 'simulate' -- (internal-only for now) Set to true to neuter all API operations (listens / puts
                                will run security rules but not actually write or return data)
        Returns:
            A signed Firebase Authentication Token
        Raises:
            ValueError: if an invalid key is specified in options
        """
        if not options:
            options = {}
        options.update({'admin': self.admin, 'debug': self.debug})
        claims = self._create_options_claims(options)
        claims['v'] = self.TOKEN_VERSION
        claims['iat'] = int(time.mktime(time.gmtime()))
        claims['d'] = data
        return self._encode_token(self.secret, claims)

def create_token ( self , data , options = None ) : if not options : options = { } options . update ( { 'admin' : self . admin , 'debug' : self . debug } ) claims = self . _create_options_claims ( options ) claims [ 'v' ] = self . TOKEN_VERSION claims [ 'iat' ] = int ( time . mktime ( time . gmtime ( ) ) ) claims [ 'd' ] = data return self . _encode_token ( self . secret , claims )

Generates a secure authentication token .


def get_user(self):
        """
        Method that gets the authenticated user. The returning user has
        the token, email and the provider data.
        """
        token = self.authenticator.create_token(self.extra)
        user_id = self.extra.get('id')
        return FirebaseUser(self.email, token, self.provider, user_id)

def get_user ( self ) : token = self . authenticator . create_token ( self . extra ) user_id = self . extra . get ( 'id' ) return FirebaseUser ( self . email , token , self . provider , user_id )

Method that gets the authenticated user . The returning user has the token email and the provider data .


def _build_endpoint_url(self, url, name=None):
        """
        Method that constructs a full url with the given url and the
        snapshot name.

        Example:
        full_url = _build_endpoint_url('/users', '1')
        full_url => 'http://firebase.localhost/users/1.json'
        """
        if not url.endswith(self.URL_SEPERATOR):
            url = url + self.URL_SEPERATOR
        if name is None:
            name = ''
        return '%s%s%s' % (urlparse.urljoin(self.dsn, url), name,
                           self.NAME_EXTENSION)

def _build_endpoint_url ( self , url , name = None ) : if not url . endswith ( self . URL_SEPERATOR ) : url = url + self . URL_SEPERATOR if name is None : name = '' return '%s%s%s' % ( urlparse . urljoin ( self . dsn , url ) , name , self . NAME_EXTENSION )

Method that constructs a full url with the given url and the snapshot name .


def _authenticate(self, params, headers):
        """
        Method that simply adjusts authentication credentials for the
        request.
        `params` is the querystring of the request.
        `headers` is the header of the request.

        If auth instance is not provided to this class, this method simply
        returns without doing anything.
        """
        if self.authentication:
            user = self.authentication.get_user()
            params.update({'auth': user.firebase_auth_token})
            headers.update(self.authentication.authenticator.HEADERS)

def _authenticate ( self , params , headers ) : if self . authentication : user = self . authentication . get_user ( ) params . update ( { 'auth' : user . firebase_auth_token } ) headers . update ( self . authentication . authenticator . HEADERS )

Method that simply adjusts authentication credentials for the request . params is the querystring of the request . headers is the header of the request .


def get(self, url, name, params=None, headers=None, connection=None):
        """
        Synchronous GET request.
        """
        if name is None: name = ''
        params = params or {}
        headers = headers or {}
        endpoint = self._build_endpoint_url(url, name)
        self._authenticate(params, headers)
        return make_get_request(endpoint, params, headers, connection=connection)

def get ( self , url , name , params = None , headers = None , connection = None ) : if name is None : name = '' params = params or { } headers = headers or { } endpoint = self . _build_endpoint_url ( url , name ) self . _authenticate ( params , headers ) return make_get_request ( endpoint , params , headers , connection = connection )


def get_async(self, url, name, callback=None, params=None, headers=None):
        """
        Asynchronous GET request with the process pool.
        """
        if name is None: name = ''
        params = params or {}
        headers = headers or {}
        endpoint = self._build_endpoint_url(url, name)
        self._authenticate(params, headers)
        process_pool.apply_async(make_get_request,
            args=(endpoint, params, headers), callback=callback)

def get_async ( self , url , name , callback = None , params = None , headers = None ) : if name is None : name = '' params = params or { } headers = headers or { } endpoint = self . _build_endpoint_url ( url , name ) self . _authenticate ( params , headers ) process_pool . apply_async ( make_get_request , args = ( endpoint , params , headers ) , callback = callback )

Asynchronous GET request with the process pool .


def put(self, url, name, data, params=None, headers=None, connection=None):
        """
        Synchronous PUT request. There will be no returning output from
        the server, because the request will be made with ``silent``
        parameter. ``data`` must be a JSONable value.
        """
        assert name, 'Snapshot name must be specified'
        params = params or {}
        headers = headers or {}
        endpoint = self._build_endpoint_url(url, name)
        self._authenticate(params, headers)
        data = json.dumps(data, cls=JSONEncoder)
        return make_put_request(endpoint, data, params, headers,
                                connection=connection)

def
put
(
self
,
url
,
name
,
data
,
params
=
,
headers
=
,
connection
=
)
:
assert
name
,
'Snapshot name must be specified'
params
=
params
or
{
}
headers
=
headers
or
{
}
endpoint
=
self
.
_build_endpoint_url
(
url
,
name
)
self
.
_authenticate
(
params
,
headers
)
data
=
json
.
dumps
(
data
,
cls
=
JSONEncoder
)
return
make_put_request
(
endpoint
,
data
,
params
,
headers
,
connection
=
connection
)

Synchronous PUT request . There will be no returning output from the server because the request will be made with silent parameter . data must be a JSONable value .


def put_async(self, url, name, data, callback=None, params=None, headers=None):
        """
        Asynchronous PUT request with the process pool.
        """
        if name is None: name = ''
        params = params or {}
        headers = headers or {}
        endpoint = self._build_endpoint_url(url, name)
        self._authenticate(params, headers)
        data = json.dumps(data, cls=JSONEncoder)
        process_pool.apply_async(make_put_request,
                                 args=(endpoint, data, params, headers),
                                 callback=callback)

def put_async ( self , url , name , data , callback = None , params = None , headers = None ) : if name is None : name = '' params = params or { } headers = headers or { } endpoint = self . _build_endpoint_url ( url , name ) self . _authenticate ( params , headers ) data = json . dumps ( data , cls = JSONEncoder ) process_pool . apply_async ( make_put_request , args = ( endpoint , data , params , headers ) , callback = callback )

Asynchronous PUT request with the process pool .


def post_async(self, url, data, callback=None, params=None, headers=None):
        """
        Asynchronous POST request with the process pool.
        """
        params = params or {}
        headers = headers or {}
        endpoint = self._build_endpoint_url(url, None)
        self._authenticate(params, headers)
        data = json.dumps(data, cls=JSONEncoder)
        process_pool.apply_async(make_post_request,
                                 args=(endpoint, data, params, headers),
                                 callback=callback)

def post_async ( self , url , data , callback = None , params = None , headers = None ) : params = params or { } headers = headers or { } endpoint = self . _build_endpoint_url ( url , None ) self . _authenticate ( params , headers ) data = json . dumps ( data , cls = JSONEncoder ) process_pool . apply_async ( make_post_request , args = ( endpoint , data , params , headers ) , callback = callback )

Asynchronous POST request with the process pool .


def delete(self, url, name, params=None, headers=None, connection=None):
        """
        Synchronous DELETE request. ``data`` must be a JSONable value.
        """
        if not name: name = ''
        params = params or {}
        headers = headers or {}
        endpoint = self._build_endpoint_url(url, name)
        self._authenticate(params, headers)
        return make_delete_request(endpoint, params, headers, connection=connection)

def delete ( self , url , name , params = None , headers = None , connection = None ) : if not name : name = '' params = params or { } headers = headers or { } endpoint = self . _build_endpoint_url ( url , name ) self . _authenticate ( params , headers ) return make_delete_request ( endpoint , params , headers , connection = connection )

Synchronous DELETE request . data must be a JSONable value .


def delete_async(self, url, name, callback=None, params=None, headers=None):
        """
        Asynchronous DELETE request with the process pool.
        """
        if not name: name = ''
        params = params or {}
        headers = headers or {}
        endpoint = self._build_endpoint_url(url, name)
        self._authenticate(params, headers)
        process_pool.apply_async(make_delete_request,
                    args=(endpoint, params, headers), callback=callback)

def delete_async ( self , url , name , callback = None , params = None , headers = None ) : if not name : name = '' params = params or { } headers = headers or { } endpoint = self . _build_endpoint_url ( url , name ) self . _authenticate ( params , headers ) process_pool . apply_async ( make_delete_request , args = ( endpoint , params , headers ) , callback = callback )

Asynchronous DELETE request with the process pool .


def do_filter(qs, keywords, exclude=False):
    """
    Filter queryset based on keywords.
    Support for multiple-selected parent values.
    """
    and_q = Q()
    for keyword, value in iteritems(keywords):
        try:
            values = value.split(",")
            if len(values) > 0:
                or_q = Q()
                for value in values:
                    or_q |= Q(**{keyword: value})
                and_q &= or_q
        except AttributeError:
            # value can be a bool
            and_q &= Q(**{keyword: value})
    if exclude:
        qs = qs.exclude(and_q)
    else:
        qs = qs.filter(and_q)
    return qs

def
do_filter
(
qs
,
keywords
,
exclude
=
False
)
:
and_q
=
Q
(
)
for
keyword
,
value
in
iteritems
(
keywords
)
:
try
:
values
=
value
.
split
(
","
)
if
len
(
values
)
>
0
:
or_q
=
Q
(
)
for
value
in
values
:
or_q
|=
Q
(
*
*
{
keyword
:
value
}
)
and_q
&=
or_q
except
AttributeError
:
# value can be a bool
and_q
&=
Q
(
*
*
{
keyword
:
value
}
)
if
exclude
:
qs
=
qs
.
exclude
(
and_q
)
else
:
qs
=
qs
.
filter
(
and_q
)
return
qs

Filter queryset based on keywords . Support for multiple - selected parent values .