def generate_controller(args):
    """Generate controller, include the controller file, template & css & js directories."""
    controller_template = os.path.join(dirname(abspath(__file__)), 'templates/controller.py')
    test_template = os.path.join(dirname(abspath(__file__)), 'templates/unittest.py')
    controller_name = args.get('<controller>')
    current_path = os.getcwd()

    logger.info('Start generating controller.')

    if not controller_name:
        logger.warning('Controller name cannot be empty.')
        return

    # controller file
    with open(controller_template, 'r') as template_file:
        controller_file_path = os.path.join(current_path, 'application/controllers',
                                            controller_name + '.py')
        with open(controller_file_path, 'w+') as controller_file:
            for line in template_file:
                new_line = line.replace('#{controller}', controller_name)
                controller_file.write(new_line)
    logger.info("New: %s" % _relative_path(controller_file_path))

    # test file
    with open(test_template, 'r') as template_file:
        test_file_path = os.path.join(current_path, 'tests',
                                      'test_%s.py' % controller_name)
        with open(test_file_path, 'w+') as test_file:
            for line in template_file:
                new_line = line.replace('#{controller}', controller_name) \
                    .replace('#{controller|title}', controller_name.title())
                test_file.write(new_line)
    logger.info("New: %s" % _relative_path(test_file_path))

    # assets dir
    assets_dir_path = os.path.join(current_path, 'application/pages/%s' % controller_name)
    _mkdir_p(assets_dir_path)

    # form file
    _generate_form(controller_name)

    logger.info('Finish generating controller.')

def
generate_controller
(
args
)
:
controller_template
=
os
.
path
.
join
(
dirname
(
abspath
(
__file__
)
)
,
'templates/controller.py'
)
test_template
=
os
.
path
.
join
(
dirname
(
abspath
(
__file__
)
)
,
'templates/unittest.py'
)
controller_name
=
args
.
get
(
'<controller>'
)
current_path
=
os
.
getcwd
(
)
logger
.
info
(
'Start generating controller.'
)
if
not
controller_name
:
logger
.
warning
(
'Controller name cannot be empty.'
)
return
with
open
(
controller_template
,
'r'
)
as
template_file
:
controller_file_path
=
os
.
path
.
join
(
current_path
,
'application/controllers'
,
controller_name
+
'.py'
)
with
open
(
controller_file_path
,
'w+'
)
as
controller_file
:
for
line
in
template_file
:
new_line
=
line
.
replace
(
'#{controller}'
,
controller_name
)
controller_file
.
write
(
new_line
)
logger
.
info
(
"New: %s"
%
_relative_path
(
controller_file_path
)
)
with
open
(
test_template
,
'r'
)
as
template_file
:
test_file_path
=
os
.
path
.
join
(
current_path
,
'tests'
,
'test_%s.py'
%
controller_name
)
with
open
(
test_file_path
,
'w+'
)
as
test_file
:
for
line
in
template_file
:
new_line
=
line
.
replace
(
'#{controller}'
,
controller_name
)
.
replace
(
'#{controller|title}'
,
controller_name
.
title
(
)
)
test_file
.
write
(
new_line
)
logger
.
info
(
"New: %s"
%
_relative_path
(
test_file_path
)
)
assets_dir_path
=
os
.
path
.
join
(
current_path
,
'application/pages/%s'
%
controller_name
)
_mkdir_p
(
assets_dir_path
)
_generate_form
(
controller_name
)
logger
.
info
(
'Finish generating controller.'
)

Generate controller include the controller file template & css & js directories .


def generate_action(args):
    """Generate action."""
    controller = args.get('<controller>')
    action = args.get('<action>')
    with_template = args.get('-t')
    current_path = os.getcwd()

    logger.info('Start generating action.')

    controller_file_path = os.path.join(current_path, 'application/controllers', controller + '.py')
    if not os.path.exists(controller_file_path):
        logger.warning("The controller %s does't exist." % controller)
        return

    if with_template:
        action_source_path = os.path.join(dirname(abspath(__file__)), 'templates/action.py')
    else:
        action_source_path = os.path.join(dirname(abspath(__file__)), 'templates/action_without_template.py')

    # Add action source codes
    with open(action_source_path, 'r') as action_source_file:
        with open(controller_file_path, 'a') as controller_file:
            for action_line in action_source_file:
                new_line = action_line.replace('#{controller}', controller). \
                    replace('#{action}', action)
                controller_file.write(new_line)
    logger.info("Updated: %s" % _relative_path(controller_file_path))

    if with_template:
        # assets dir
        assets_dir_path = os.path.join(current_path, 'application/pages/%s/%s' % (controller, action))
        _mkdir_p(assets_dir_path)

        # html
        action_html_template_path = os.path.join(dirname(abspath(__file__)), 'templates/action.html')
        action_html_path = os.path.join(assets_dir_path, '%s.html' % action)
        with open(action_html_template_path, 'r') as action_html_template_file:
            with open(action_html_path, 'w') as action_html_file:
                for line in action_html_template_file:
                    new_line = line.replace('#{action}', action) \
                        .replace('#{action|title}', action.title()) \
                        .replace('#{controller}', controller)
                    action_html_file.write(new_line)
        logger.info("New: %s" % _relative_path(action_html_path))

        # js
        action_js_template_path = os.path.join(dirname(abspath(__file__)), 'templates/action.js')
        action_js_path = os.path.join(assets_dir_path, '%s.js' % action)
        shutil.copy(action_js_template_path, action_js_path)
        logger.info("New: %s" % _relative_path(action_js_path))

        # less
        action_less_template_path = os.path.join(dirname(abspath(__file__)), 'templates/action.less')
        action_less_path = os.path.join(assets_dir_path, '%s.less' % action)
        shutil.copy(action_less_template_path, action_less_path)
        logger.info("New: %s" % _relative_path(action_less_path))

    logger.info('Finish generating action.')

def
generate_action
(
args
)
:
controller
=
args
.
get
(
'<controller>'
)
action
=
args
.
get
(
'<action>'
)
with_template
=
args
.
get
(
'-t'
)
current_path
=
os
.
getcwd
(
)
logger
.
info
(
'Start generating action.'
)
controller_file_path
=
os
.
path
.
join
(
current_path
,
'application/controllers'
,
controller
+
'.py'
)
if
not
os
.
path
.
exists
(
controller_file_path
)
:
logger
.
warning
(
"The controller %s does't exist."
%
controller
)
return
if
with_template
:
action_source_path
=
os
.
path
.
join
(
dirname
(
abspath
(
__file__
)
)
,
'templates/action.py'
)
else
:
action_source_path
=
os
.
path
.
join
(
dirname
(
abspath
(
__file__
)
)
,
'templates/action_without_template.py'
)
with
open
(
action_source_path
,
'r'
)
as
action_source_file
:
with
open
(
controller_file_path
,
'a'
)
as
controller_file
:
for
action_line
in
action_source_file
:
new_line
=
action_line
.
replace
(
'#{controller}'
,
controller
)
.
replace
(
'#{action}'
,
action
)
controller_file
.
write
(
new_line
)
logger
.
info
(
"Updated: %s"
%
_relative_path
(
controller_file_path
)
)
if
with_template
:
assets_dir_path
=
os
.
path
.
join
(
current_path
,
'application/pages/%s/%s'
%
(
controller
,
action
)
)
_mkdir_p
(
assets_dir_path
)
action_html_template_path
=
os
.
path
.
join
(
dirname
(
abspath
(
__file__
)
)
,
'templates/action.html'
)
action_html_path
=
os
.
path
.
join
(
assets_dir_path
,
'%s.html'
%
action
)
with
open
(
action_html_template_path
,
'r'
)
as
action_html_template_file
:
with
open
(
action_html_path
,
'w'
)
as
action_html_file
:
for
line
in
action_html_template_file
:
new_line
=
line
.
replace
(
'#{action}'
,
action
)
.
replace
(
'#{action|title}'
,
action
.
title
(
)
)
.
replace
(
'#{controller}'
,
controller
)
action_html_file
.
write
(
new_line
)
logger
.
info
(
"New: %s"
%
_relative_path
(
action_html_path
)
)
action_js_template_path
=
os
.
path
.
join
(
dirname
(
abspath
(
__file__
)
)
,
'templates/action.js'
)
action_js_path
=
os
.
path
.
join
(
assets_dir_path
,
'%s.js'
%
action
)
shutil
.
copy
(
action_js_template_path
,
action_js_path
)
logger
.
info
(
"New: %s"
%
_relative_path
(
action_js_path
)
)
action_less_template_path
=
os
.
path
.
join
(
dirname
(
abspath
(
__file__
)
)
,
'templates/action.less'
)
action_less_path
=
os
.
path
.
join
(
assets_dir_path
,
'%s.less'
%
action
)
shutil
.
copy
(
action_less_template_path
,
action_less_path
)
logger
.
info
(
"New: %s"
%
_relative_path
(
action_less_path
)
)
logger
.
info
(
'Finish generating action.'
)


def generate_form(args):
    """Generate form."""
    form_name = args.get('<form>')
    logger.info('Start generating form.')
    _generate_form(form_name)
    logger.info('Finish generating form.')

def
generate_form
(
args
)
:
form_name
=
args
.
get
(
'<form>'
)
logger
.
info
(
'Start generating form.'
)
_generate_form
(
form_name
)
logger
.
info
(
'Finish generating form.'
)


def generate_model(args):
    """Generate model."""
    model_name = args.get('<model>')
    if not model_name:
        logger.warning('Model name cannot be empty.')
        return

    logger.info('Start generating model.')

    model_template = os.path.join(dirname(abspath(__file__)), 'templates/model.py')
    current_path = os.getcwd()

    with open(model_template, 'r') as template_file:
        model_file_path = os.path.join(current_path, 'application/models',
                                       model_name + '.py')
        with open(model_file_path, 'w+') as model_file:
            for line in template_file:
                new_line = line.replace('#{model|title}', model_name.title())
                model_file.write(new_line)
    logger.info("New: %s" % _relative_path(model_file_path))

    with open(os.path.join(current_path, 'application/models/__init__.py'), 'a') as package_file:
        package_file.write('\nfrom .%s import *' % model_name)

    logger.info('Finish generating model.')

def
generate_model
(
args
)
:
model_name
=
args
.
get
(
'<model>'
)
if
not
model_name
:
logger
.
warning
(
'Model name cannot be empty.'
)
return
logger
.
info
(
'Start generating model.'
)
model_template
=
os
.
path
.
join
(
dirname
(
abspath
(
__file__
)
)
,
'templates/model.py'
)
current_path
=
os
.
getcwd
(
)
with
open
(
model_template
,
'r'
)
as
template_file
:
model_file_path
=
os
.
path
.
join
(
current_path
,
'application/models'
,
model_name
+
'.py'
)
with
open
(
model_file_path
,
'w+'
)
as
model_file
:
for
line
in
template_file
:
new_line
=
line
.
replace
(
'#{model|title}'
,
model_name
.
title
(
)
)
model_file
.
write
(
new_line
)
logger
.
info
(
"New: %s"
%
_relative_path
(
model_file_path
)
)
with
open
(
os
.
path
.
join
(
current_path
,
'application/models/__init__.py'
)
,
'a'
)
as
package_file
:
package_file
.
write
(
'\nfrom .%s import *'
%
model_name
)
logger
.
info
(
'Finish generating model.'
)


def generate_macro(args):
    """Genarate macro."""
    macro = args.get('<macro>').replace('-', '_')
    category = args.get('<category>')

    if not macro:
        logger.warning('Macro name cannot be empty.')
        return

    logger.info('Start generating macro.')

    current_path = os.getcwd()

    if category:
        macro_root_path = os.path.join(current_path, 'application/macros', category, macro)
    else:
        macro_root_path = os.path.join(current_path, 'application/macros', macro)

    _mkdir_p(macro_root_path)

    macro_html_path = os.path.join(macro_root_path, '_%s.html' % macro)
    macro_css_path = os.path.join(macro_root_path, '_%s.less' % macro)
    macro_js_path = os.path.join(macro_root_path, '_%s.js' % macro)

    # html
    macro_html_template_path = os.path.join(dirname(abspath(__file__)), 'templates/macro.html')
    with open(macro_html_template_path, 'r') as template_file:
        with open(macro_html_path, 'w+') as html_file:
            for line in template_file:
                new_line = line.replace('#{macro}', macro)
                html_file.write(new_line)
    logger.info("New: %s" % _relative_path(macro_html_path))

    # css
    open(macro_css_path, 'a').close()
    logger.info("New: %s" % _relative_path(macro_css_path))

    # js
    open(macro_js_path, 'a').close()
    logger.info("New: %s" % _relative_path(macro_js_path))

    logger.info('Finish generating macro.')

def
generate_macro
(
args
)
:
macro
=
args
.
get
(
'<macro>'
)
.
replace
(
'-'
,
'_'
)
category
=
args
.
get
(
'<category>'
)
if
not
macro
:
logger
.
warning
(
'Macro name cannot be empty.'
)
return
logger
.
info
(
'Start generating macro.'
)
current_path
=
os
.
getcwd
(
)
if
category
:
macro_root_path
=
os
.
path
.
join
(
current_path
,
'application/macros'
,
category
,
macro
)
else
:
macro_root_path
=
os
.
path
.
join
(
current_path
,
'application/macros'
,
macro
)
_mkdir_p
(
macro_root_path
)
macro_html_path
=
os
.
path
.
join
(
macro_root_path
,
'_%s.html'
%
macro
)
macro_css_path
=
os
.
path
.
join
(
macro_root_path
,
'_%s.less'
%
macro
)
macro_js_path
=
os
.
path
.
join
(
macro_root_path
,
'_%s.js'
%
macro
)
macro_html_template_path
=
os
.
path
.
join
(
dirname
(
abspath
(
__file__
)
)
,
'templates/macro.html'
)
with
open
(
macro_html_template_path
,
'r'
)
as
template_file
:
with
open
(
macro_html_path
,
'w+'
)
as
html_file
:
for
line
in
template_file
:
new_line
=
line
.
replace
(
'#{macro}'
,
macro
)
html_file
.
write
(
new_line
)
logger
.
info
(
"New: %s"
%
_relative_path
(
macro_html_path
)
)
open
(
macro_css_path
,
'a'
)
.
close
(
)
logger
.
info
(
"New: %s"
%
_relative_path
(
macro_css_path
)
)
open
(
macro_js_path
,
'a'
)
.
close
(
)
logger
.
info
(
"New: %s"
%
_relative_path
(
macro_js_path
)
)
logger
.
info
(
'Finish generating macro.'
)


def _mkdir_p(path):
    """mkdir -p path"""
    try:
        os.makedirs(path)
    except OSError as exc:
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise
    else:
        logger.info("New: %s%s", path, os.path.sep)

def
_mkdir_p
(
path
)
:
try
:
os
.
makedirs
(
path
)
except
OSError
as
exc
:
if
exc
.
errno
==
errno
.
EEXIST
and
os
.
path
.
isdir
(
path
)
:
pass
else
:
raise
else
:
logger
.
info
(
"New: %s%s"
,
path
,
os
.
path
.
sep
)


def _rewrite_and_copy(src_file, dst_file, project_name):
    """Replace vars and copy."""
    # Create temp file
    fh, abs_path = mkstemp()

    with io.open(abs_path, 'w', encoding='utf-8') as new_file:
        with io.open(src_file, 'r', encoding='utf-8') as old_file:
            for line in old_file:
                new_line = line.replace('#{project}', project_name). \
                    replace('#{project|title}', project_name.title())
                new_file.write(new_line)

    # Copy to new file
    shutil.copy(abs_path, dst_file)
    os.close(fh)

def _rewrite_and_copy ( src_file , dst_file , project_name ) : fh , abs_path = mkstemp ( ) with io . open ( abs_path , 'w' , encoding = 'utf-8' ) as new_file : with io . open ( src_file , 'r' , encoding = 'utf-8' ) as old_file : for line in old_file : new_line = line . replace ( '#{project}' , project_name ) . replace ( '#{project|title}' , project_name . title ( ) ) new_file . write ( new_line ) shutil . copy ( abs_path , dst_file ) os . close ( fh )


def timesince(value):
    """Friendly time gap"""
    if not value:
        return ""

    if not isinstance(value, datetime.date):
        return value

    now = datetime.datetime.now()
    delta = now - value

    if value > now:
        return "right now"
    elif delta.days > 365:
        return '%d years ago' % (delta.days / 365)
    elif delta.days > 30:
        return '%d months ago' % (delta.days / 30)
    elif delta.days > 0:
        return '%d days ago' % delta.days
    elif delta.seconds > 3600:
        return '%d hours ago' % (delta.seconds / 3600)
    elif delta.seconds > 60:
        return '%d minutes ago' % (delta.seconds / 60)
    else:
        return 'right now'

def
timesince
(
value
)
:
if
not
value
:
return
""
if
not
isinstance
(
value
,
datetime
.
date
)
:
return
value
now
=
datetime
.
datetime
.
now
(
)
delta
=
now
value
if
value
>
now
:
return
"right now"
elif
delta
.
days
>
365
:
return
'%d years ago'
%
(
delta
.
days
/
365
)
elif
delta
.
days
>
30
:
return
'%d months ago'
%
(
delta
.
days
/
30
)
elif
delta
.
days
>
0
:
return
'%d days ago'
%
delta
.
days
elif
delta
.
seconds
>
3600
:
return
'%d hours ago'
%
(
delta
.
seconds
/
3600
)
elif
delta
.
seconds
>
60
:
return
'%d minutes ago'
%
(
delta
.
seconds
/
60
)
else
:
return
'right now'


def check_url(form, field):
    """Check url schema."""
    url = field.data.strip()
    if not url:
        return
    result = urlparse(url)
    if result.scheme == "":
        field.data = "http://%s" % re.sub(r'^:?/*', '', url)

def check_url ( form , field ) : url = field . data . strip ( ) if not url : return result = urlparse ( url ) if result . scheme == "" : field . data = "http://%s" % re . sub ( r'^:?/*' , '' , url )


def encode(something):
    """Encode something with SECRET_KEY."""
    secret_key = current_app.config.get('SECRET_KEY')
    s = URLSafeSerializer(secret_key)
    return s.dumps(something)

def encode ( something ) : secret_key = current_app . config . get ( 'SECRET_KEY' ) s = URLSafeSerializer ( secret_key ) return s . dumps ( something )


def decode(something):
    """Decode something with SECRET_KEY."""
    secret_key = current_app.config.get('SECRET_KEY')
    s = URLSafeSerializer(secret_key)
    try:
        return s.loads(something)
    except BadSignature:
        return None

def decode ( something ) : secret_key = current_app . config . get ( 'SECRET_KEY' ) s = URLSafeSerializer ( secret_key ) try : return s . loads ( something ) except BadSignature : return None


def jsonify(func):
    """JSON decorator."""

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        r = func(*args, **kwargs)
        if isinstance(r, tuple):
            code, data = r
        else:
            code, data = 200, r
        return Response(json.dumps(data), status=code, mimetype='application/json')

    return wrapper

def jsonify ( func ) : @ functools . wraps ( func ) def wrapper ( * args , ** kwargs ) : r = func ( * args , ** kwargs ) if isinstance ( r , tuple ) : code , data = r else : code , data = 200 , r return Response ( json . dumps ( data ) , status = code , mimetype = 'application/json' ) return wrapper


def absolute_url_for(endpoint, **values):
    """Absolute url for endpoint."""
    config = current_app.config
    site_domain = config.get('SITE_DOMAIN')
    relative_url = url_for(endpoint, **values)
    return join_url(site_domain, relative_url)

def absolute_url_for ( endpoint , ** values ) : config = current_app . config site_domain = config . get ( 'SITE_DOMAIN' ) relative_url = url_for ( endpoint , ** values ) return join_url ( site_domain , relative_url )


def load_config():
    """Load config."""
    mode = os.environ.get('MODE')
    try:
        if mode == 'PRODUCTION':
            from .production import ProductionConfig
            return ProductionConfig
        elif mode == 'TESTING':
            from .testing import TestingConfig
            return TestingConfig
        else:
            from .development import DevelopmentConfig
            return DevelopmentConfig
    except ImportError:
        from .default import Config
        return Config

def load_config ( ) : mode = os . environ . get ( 'MODE' ) try : if mode == 'PRODUCTION' : from . production import ProductionConfig return ProductionConfig elif mode == 'TESTING' : from . testing import TestingConfig return TestingConfig else : from . development import DevelopmentConfig return DevelopmentConfig except ImportError : from . default import Config return Config


def signin_user(user, permenent=True):
    """Sign in user."""
    session.permanent = permenent
    session['user_id'] = user.id

def signin_user ( user , permenent = True ) : session . permanent = permenent session [ 'user_id' ] = user . id


def get_current_user():
    """Get current user."""
    if not 'user_id' in session:
        return None
    user = User.query.filter(User.id == session['user_id']).first()
    if not user:
        signout_user()
        return None
    return user

def get_current_user ( ) : if not 'user_id' in session : return None user = User . query . filter ( User . id == session [ 'user_id' ] ) . first ( ) if not user : signout_user ( ) return None return user


def create_app():
    """Create Flask app."""
    config = load_config()

    app = Flask(__name__)
    app.config.from_object(config)

    # Proxy fix
    app.wsgi_app = ProxyFix(app.wsgi_app)

    # CSRF protect
    CsrfProtect(app)

    if app.debug or app.testing:
        DebugToolbarExtension(app)

        # Serve static files
        app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
            '/pages': os.path.join(app.config.get('PROJECT_PATH'), 'application/pages')
        })
    else:
        # Log errors to stderr in production mode
        app.logger.addHandler(logging.StreamHandler())
        app.logger.setLevel(logging.ERROR)

        # Enable Sentry
        if app.config.get('SENTRY_DSN'):
            from .utils.sentry import sentry

            sentry.init_app(app, dsn=app.config.get('SENTRY_DSN'))

        # Serve static files
        app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
            '/static': os.path.join(app.config.get('PROJECT_PATH'), 'output/static'),
            '/pkg': os.path.join(app.config.get('PROJECT_PATH'), 'output/pkg'),
            '/pages': os.path.join(app.config.get('PROJECT_PATH'), 'output/pages')
        })

    # Register components
    register_db(app)
    register_routes(app)
    register_jinja(app)
    register_error_handle(app)
    register_hooks(app)

    return app

def create_app ( ) : config = load_config ( ) app = Flask ( __name__ ) app . config . from_object ( config ) app . wsgi_app = ProxyFix ( app . wsgi_app ) CsrfProtect ( app ) if app . debug or app . testing : DebugToolbarExtension ( app ) app . wsgi_app = SharedDataMiddleware ( app . wsgi_app , { '/pages' : os . path . join ( app . config . get ( 'PROJECT_PATH' ) , 'application/pages' ) } ) else : app . logger . addHandler ( logging . StreamHandler ( ) ) app . logger . setLevel ( logging . ERROR ) if app . config . get ( 'SENTRY_DSN' ) : from . utils . sentry import sentry sentry . init_app ( app , dsn = app . config . get ( 'SENTRY_DSN' ) ) app . wsgi_app = SharedDataMiddleware ( app . wsgi_app , { '/static' : os . path . join ( app . config . get ( 'PROJECT_PATH' ) , 'output/static' ) , '/pkg' : os . path . join ( app . config . get ( 'PROJECT_PATH' ) , 'output/pkg' ) , '/pages' : os . path . join ( app . config . get ( 'PROJECT_PATH' ) , 'output/pages' ) } ) register_db ( app ) register_routes ( app ) register_jinja ( app ) register_error_handle ( app ) register_hooks ( app ) return app


def register_jinja(app):
    """Register jinja filters, vars, functions."""
    import jinja2
    from .utils import filters, permissions, helpers

    if app.debug or app.testing:
        my_loader = jinja2.ChoiceLoader([
            app.jinja_loader,
            jinja2.FileSystemLoader([
                os.path.join(app.config.get('PROJECT_PATH'), 'application/macros'),
                os.path.join(app.config.get('PROJECT_PATH'), 'application/pages')
            ])
        ])
    else:
        my_loader = jinja2.ChoiceLoader([
            app.jinja_loader,
            jinja2.FileSystemLoader([
                os.path.join(app.config.get('PROJECT_PATH'), 'output/macros'),
                os.path.join(app.config.get('PROJECT_PATH'), 'output/pages')
            ])
        ])
    app.jinja_loader = my_loader

    app.jinja_env.filters.update({
        'timesince': filters.timesince
    })

    def url_for_other_page(page):
        """Generate url for pagination."""
        view_args = request.view_args.copy()
        args = request.args.copy().to_dict()
        combined_args = dict(view_args.items() + args.items())
        combined_args['page'] = page
        return url_for(request.endpoint, **combined_args)

    rules = {}
    for endpoint, _rules in iteritems(app.url_map._rules_by_endpoint):
        if any(item in endpoint for item in ['_debug_toolbar', 'debugtoolbar', 'static']):
            continue
        rules[endpoint] = [{'rule': rule.rule} for rule in _rules]

    app.jinja_env.globals.update({
        'absolute_url_for': helpers.absolute_url_for,
        'url_for_other_page': url_for_other_page,
        'rules': rules,
        'permissions': permissions
    })

def register_jinja ( app ) : import jinja2 from . utils import filters , permissions , helpers if app . debug or app . testing : my_loader = jinja2 . ChoiceLoader ( [ app . jinja_loader , jinja2 . FileSystemLoader ( [ os . path . join ( app . config . get ( 'PROJECT_PATH' ) , 'application/macros' ) , os . path . join ( app . config . get ( 'PROJECT_PATH' ) , 'application/pages' ) ] ) ] ) else : my_loader = jinja2 . ChoiceLoader ( [ app . jinja_loader , jinja2 . FileSystemLoader ( [ os . path . join ( app . config . get ( 'PROJECT_PATH' ) , 'output/macros' ) , os . path . join ( app . config . get ( 'PROJECT_PATH' ) , 'output/pages' ) ] ) ] ) app . jinja_loader = my_loader app . jinja_env . filters . update ( { 'timesince' : filters . timesince } ) def url_for_other_page ( page ) : view_args = request . view_args . copy ( ) args = request . args . copy ( ) . to_dict ( ) combined_args = dict ( view_args . items ( ) + args . items ( ) ) combined_args [ 'page' ] = page return url_for ( request . endpoint , ** combined_args ) rules = { } for endpoint , _rules in iteritems ( app . url_map . _rules_by_endpoint ) : if any ( item in endpoint for item in [ '_debug_toolbar' , 'debugtoolbar' , 'static' ] ) : continue rules [ endpoint ] = [ { 'rule' : rule . rule } for rule in _rules ] app . jinja_env . globals . update ( { 'absolute_url_for' : helpers . absolute_url_for , 'url_for_other_page' : url_for_other_page , 'rules' : rules , 'permissions' : permissions } )


def register_routes(app):
    """Register routes."""
    from . import controllers
    from flask.blueprints import Blueprint

    for module in _import_submodules_from_package(controllers):
        bp = getattr(module, 'bp')
        if bp and isinstance(bp, Blueprint):
            app.register_blueprint(bp)

def register_routes ( app ) : from . import controllers from flask . blueprints import Blueprint for module in _import_submodules_from_package ( controllers ) : bp = getattr ( module , 'bp' ) if bp and isinstance ( bp , Blueprint ) : app . register_blueprint ( bp )


def register_error_handle(app):
    """Register HTTP error pages."""

    @app.errorhandler(403)
    def page_403(error):
        return render_template('site/403/403.html'), 403

    @app.errorhandler(404)
    def page_404(error):
        return render_template('site/404/404.html'), 404

    @app.errorhandler(500)
    def page_500(error):
        return render_template('site/500/500.html'), 500

def register_error_handle ( app ) : @ app . errorhandler ( 403 ) def page_403 ( error ) : return render_template ( 'site/403/403.html' ) , 403 @ app . errorhandler ( 404 ) def page_404 ( error ) : return render_template ( 'site/404/404.html' ) , 404 @ app . errorhandler ( 500 ) def page_500 ( error ) : return render_template ( 'site/500/500.html' ) , 500


def register_hooks(app):
    """Register hooks."""

    @app.before_request
    def before_request():
        g.user = get_current_user()
        if g.user and g.user.is_admin:
            g._before_request_time = time.time()

    @app.after_request
    def after_request(response):
        if hasattr(g, '_before_request_time'):
            delta = time.time() - g._before_request_time
            response.headers['X-Render-Time'] = delta * 1000
        return response

def register_hooks ( app ) : @ app . before_request def before_request ( ) : g . user = get_current_user ( ) if g . user and g . user . is_admin : g . _before_request_time = time . time ( ) @ app . after_request def after_request ( response ) : if hasattr ( g , '_before_request_time' ) : delta = time . time ( ) - g . _before_request_time response . headers [ 'X-Render-Time' ] = delta * 1000 return response


def _dataframe_to_csv(writer, dataframe, delimiter, with_header):
    """serialize the dataframe with different delimiters"""
    encoding_writer = codecs.getwriter('utf-8')(writer)
    dataframe.to_csv(
        path_or_buf=encoding_writer,
        sep=delimiter,
        header=with_header,
        index=False
    )

def _dataframe_to_csv ( writer , dataframe , delimiter , with_header ) : encoding_writer = codecs . getwriter ( 'utf-8' ) ( writer ) dataframe . to_csv ( path_or_buf = encoding_writer , sep = delimiter , header = with_header , index = False )


def _dataframe_from_csv(reader, delimiter, with_header, skipspace):
    """Returns csv data as a pandas Dataframe object"""
    sep = delimiter
    header = 0
    if not with_header:
        header = None

    return pd.read_csv(
        reader,
        header=header,
        sep=sep,
        skipinitialspace=skipspace,
        encoding='utf-8-sig'
    )

def _dataframe_from_csv ( reader , delimiter , with_header , skipspace ) : sep = delimiter header = 0 if not with_header : header = None return pd . read_csv ( reader , header = header , sep = sep , skipinitialspace = skipspace , encoding = 'utf-8-sig' )


def serialize_dataframe(writer, data_type_id, dataframe):
    """
    Serialize a dataframe.

    Parameters
    ----------
    writer : file
        File-like object to write to. Must be opened in binary mode.
    data_type_id : dict
        Serialization format to use.
        See the azureml.DataTypeIds class for constants.
    dataframe: pandas.DataFrame
        Dataframe to serialize.
    """
    _not_none('writer', writer)
    _not_none_or_empty('data_type_id', data_type_id)
    _not_none('dataframe', dataframe)

    serializer = _SERIALIZERS.get(data_type_id)
    if serializer is None:
        raise UnsupportedDatasetTypeError(data_type_id)
    serializer[0](writer=writer, dataframe=dataframe)

def serialize_dataframe ( writer , data_type_id , dataframe ) : _not_none ( 'writer' , writer ) _not_none_or_empty ( 'data_type_id' , data_type_id ) _not_none ( 'dataframe' , dataframe ) serializer = _SERIALIZERS . get ( data_type_id ) if serializer is None : raise UnsupportedDatasetTypeError ( data_type_id ) serializer [ 0 ] ( writer = writer , dataframe = dataframe )


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

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

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

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

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


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

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

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

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

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

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

Serialize the specified DataFrame and replace the existing dataset .


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

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

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

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

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

Upload already serialized raw data and replace the existing dataset .


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

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


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

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

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

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

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

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

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


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

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

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

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

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

Upload already serialized raw data as a new dataset .


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

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

Open and return a stream for the dataset contents .


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

Read and return the dataset contents as binary .


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

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

Read and return the dataset contents as text .


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

def _to_dataframe ( self ) : data = self . read_as_binary ( ) reader = BytesIO ( data ) return deserialize_dataframe ( reader , self . data_type_id )

Read and return the dataset contents as a pandas DataFrame .


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

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

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

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


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

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

Runs HTTP GET request to retrieve the list of experiments .


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

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

Runs HTTP GET request to retrieve the list of datasets .


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

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

Runs HTTP GET request to retrieve a single dataset .


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

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

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

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

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

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

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

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

The returned result will be the published service.

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

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

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

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

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


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

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

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

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


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

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

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

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


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

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

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

Specifies the return type for a published service .


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

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

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

attaches a file to the payload to be uploaded .


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

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

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

                cur_byte += 2
            cur_byte += 1

        return names

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


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

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


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

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

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

    from gi.repository import Gdk

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

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

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

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


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

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


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

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

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

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

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

def _cubic_bernstein_extrema ( p0 , p1 , p2 , p3 ) : a = 3. * ( p3 - p0 + 3. * ( p1 - p2 ) ) b = 6. * ( p0 + p2 - 2. * p1 ) c = 3. * ( p1 - p0 ) if a == 0 : if b == 0 : return ( ) return ( - c / b , ) d = b * b - 4. * a * c if d < 0 : return ( ) k = - 2. * a if d == 0 : return ( b / k , ) r = math . sqrt ( d ) return ( ( b + r ) / k , ( b - r ) / k )

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


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

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


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

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

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

        tree_choices = [(ITEMS_FIELD_ROOT_ID, self.root_title)]

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

        return tree_choices

Build choices list runtime using sitetree_tree tag


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

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

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

        func = option_func or make_option

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

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

        else:
            result = options

        return result

    return get_options

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

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


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

    Callable should be able to:

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

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

    Example::

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

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

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

        # And we register items processor.
        register_items_hook(my_items_processor)

    :param func:
    """
    global _ITEMS_PROCESSOR
    global _ITEMS_PROCESSOR_ARGS_LEN

    _ITEMS_PROCESSOR = func

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

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


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

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

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

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

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

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

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

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

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

    return result()

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


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

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

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

def init ( self ) : cache . get ( 'sitetrees_reset' ) and self . empty ( init = False ) self . cache = cache . get ( 'sitetrees' , { 'sitetrees' : { } , 'parents' : { } , 'items_by_ids' : { } , 'tree_aliases' : { } } )

Initializes local cache from Django cache .


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

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

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


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

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

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

Returns cache entry parameter value by its name .


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

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

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

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

Updates cache entry parameter with new data .


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

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

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

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


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

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

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

def init ( self , context ) : self . cache = Cache ( ) self . current_page_context = context self . current_request = context . get ( 'request' , None ) if context else None self . current_lang = get_language ( ) self . _current_app_is_admin = None self . _current_user_permissions = _UNSET self . _items_urls = { } self . _current_items = { }

Initializes sitetree to handle new request .


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

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

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

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

        if trees_count:
            alias = i18n_tree_alias

        return alias

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

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


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

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

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

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

            is_admin = current_app == ADMIN_APP_NAME
            self._current_app_is_admin = is_admin

        return is_admin

def current_app_is_admin ( self ) : is_admin = self . _current_app_is_admin if is_admin is None : context = self . current_page_context current_app = getattr ( getattr ( context . get ( 'request' , None ) , 'resolver_match' , None ) , 'app_name' , getattr ( context , 'current_app' , None ) ) if current_app is None : current_app = context . get ( 'current_app' , '' ) is_admin = current_app == ADMIN_APP_NAME self . _current_app_is_admin = is_admin return is_admin

Returns boolean whether current application is Admin contrib .


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

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

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

        return depth

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

Calculates depth of the item in the tree .


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

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

        if current_item is not _UNSET:

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

            return current_item

        current_item = None

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

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

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

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

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

        return current_item

def get_tree_current_item ( self , tree_alias ) : current_item = self . _current_items . get ( tree_alias , _UNSET ) if current_item is not _UNSET : if current_item is not None : current_item . is_current = True return current_item current_item = None if self . current_app_is_admin ( ) : self . _current_items [ tree_alias ] = current_item return None current_url = self . current_request . path if isinstance ( current_url , str ) : current_url = current_url . encode ( 'UTF-8' ) if current_url : current_url = urlquote ( current_url ) for url_item , url in self . _items_urls . items ( ) : if url != current_url : continue url_item . is_current = True if url_item . tree . alias == tree_alias : current_item = url_item if current_item is not None : self . _current_items [ tree_alias ] = current_item return current_item

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


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

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

        :param Context context:

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

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

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

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

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

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

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

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

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

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

        else:
            resolved_url = url_pattern

        self._items_urls[sitetree_item] = resolved_url

        return resolved_url

def
url
(
self
,
sitetree_item
,
context
=
)
:
context
=
context
or
self
.
current_page_context
resolve_var
=
self
.
resolve_var
if
not
isinstance
(
sitetree_item
,
MODEL_TREE_ITEM_CLASS
)
:
sitetree_item
=
resolve_var
(
sitetree_item
,
context
)
resolved_url
=
self
.
_items_urls
.
get
(
sitetree_item
)
if
resolved_url
is
not
:
return
resolved_url
if
sitetree_item
.
urlaspattern
:
url
=
sitetree_item
.
url
view_path
=
url
all_arguments
=
[
]
if
' '
in
url
:
view_path
=
url
.
split
(
' '
)
for
view_argument
in
view_path
[
1
:
]
:
resolved
=
resolve_var
(
view_argument
)
all_arguments
.
append
(
'"%s"'
%
resolved
)
view_path
=
view_path
[
0
]
.
strip
(
'"\' '
)
url_pattern
=
"'%s' %s"
%
(
view_path
,
' '
.
join
(
all_arguments
)
)
else
:
url_pattern
=
'%s'
%
sitetree_item
.
url
if
sitetree_item
.
urlaspattern
:
url_token
=
'url %s as item.url_resolved'
%
url_pattern
url_tag
(
Parser
(
)
,
Token
(
token_type
=
TOKEN_BLOCK
,
contents
=
url_token
)
)
.
render
(
context
)
resolved_url
=
context
[
'item.url_resolved'
]
or
UNRESOLVED_ITEM_MARKER
else
:
resolved_url
=
url_pattern
self
.
_items_urls
[
sitetree_item
]
=
resolved_url
return
resolved_url


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

        Returns tuple with resolved tree alias and items on success.

        On fail returns (None, None).

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

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

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

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

        if not sitetree_items:
            return None, None

        return tree_alias, sitetree_items


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

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

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

            return ''

        return getattr(current_item, attr_name, '')

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


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

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

        if depth <= 1:
            return current_item.parent

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

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

Returns ancestor of level deep recursively


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

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

        if not sitetree_items:
            return ''

        tree_branches = self.resolve_var(tree_branches)

        parent_isnull = False
        parent_ids = []
        parent_aliases = []

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

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

            if branch_id == ALIAS_TRUNK:
                parent_isnull = True

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

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

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

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

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

            else:
                parent_aliases.append(branch_id)

        check_access = self.check_access

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

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

def menu ( self , tree_alias , tree_branches , context ) : tree_alias , sitetree_items = self . init_tree ( tree_alias , context ) if not sitetree_items : return '' tree_branches = self . resolve_var ( tree_branches ) parent_isnull = False parent_ids = [ ] parent_aliases = [ ] current_item = self . get_tree_current_item ( tree_alias ) self . tree_climber ( tree_alias , current_item ) for branch_id in tree_branches . split ( ',' ) : branch_id = branch_id . strip ( ) if branch_id == ALIAS_TRUNK : parent_isnull = True elif branch_id == ALIAS_THIS_CHILDREN and current_item is not None : branch_id = current_item . id parent_ids . append ( branch_id ) elif branch_id == ALIAS_THIS_ANCESTOR_CHILDREN and current_item is not None : branch_id = self . get_ancestor_item ( tree_alias , current_item ) . id parent_ids . append ( branch_id ) elif branch_id == ALIAS_THIS_SIBLINGS and current_item is not None and current_item . parent is not None : branch_id = current_item . parent . id parent_ids . append ( branch_id ) elif branch_id == ALIAS_THIS_PARENT_SIBLINGS and current_item is not None : branch_id = self . get_ancestor_level ( current_item , depth = 2 ) . id parent_ids . append ( branch_id ) elif branch_id . isdigit ( ) : parent_ids . append ( int ( branch_id ) ) else : parent_aliases . append ( branch_id ) check_access = self . check_access menu_items = [ ] for item in sitetree_items : if not item . hidden and item . inmenu and check_access ( item , context ) : if item . parent is None : if parent_isnull : menu_items . append ( item ) else : if item . parent . id in parent_ids or item . parent . alias in parent_aliases : menu_items . append ( item ) menu_items = self . apply_hook ( menu_items , 'menu' ) self . update_has_children ( tree_alias , menu_items , 'menu' ) return menu_items

Builds and returns menu structure for sitetree_menu tag .


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

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

        if item.access_loggedin and not authenticated:
            return False

        if item.access_guest and authenticated:
            return False

        if item.access_restricted:
            user_perms = self._current_user_permissions

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

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

        return True

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

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


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

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

        if not sitetree_items:
            return ''

        current_item = self.get_tree_current_item(tree_alias)

        breadcrumbs = []

        if current_item is not None:

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

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

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

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

            climb(current_item)
            breadcrumbs.reverse()

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

        return items

def breadcrumbs ( self , tree_alias , context ) : tree_alias , sitetree_items = self . init_tree ( tree_alias , context ) if not sitetree_items : return '' current_item = self . get_tree_current_item ( tree_alias ) breadcrumbs = [ ] if current_item is not None : context_ = self . current_page_context check_access = self . check_access get_item_by_id = self . get_item_by_id def climb ( base_item ) : if base_item . inbreadcrumbs and not base_item . hidden and check_access ( base_item , context_ ) : breadcrumbs . append ( base_item ) if hasattr ( base_item , 'parent' ) and base_item . parent is not None : climb ( get_item_by_id ( tree_alias , base_item . parent . id ) ) climb ( current_item ) breadcrumbs . reverse ( ) items = self . apply_hook ( breadcrumbs , 'breadcrumbs' ) self . update_has_children ( tree_alias , items , 'breadcrumbs' ) return items

Builds and returns breadcrumb trail structure for sitetree_breadcrumbs tag .


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

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

        if not sitetree_items:
            return ''

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

        return tree_items

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

Builds and returns tree structure for sitetree_tree tag .


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

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

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

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

        my_template = get_template(use_template)

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

        return rendered

def children ( self , parent_item , navigation_type , use_template , context ) : parent_item = self . resolve_var ( parent_item , context ) tree_alias , tree_items = self . get_sitetree ( parent_item . tree . alias ) self . tree_climber ( tree_alias , self . get_tree_current_item ( tree_alias ) ) tree_items = self . get_children ( tree_alias , parent_item ) tree_items = self . filter_items ( tree_items , navigation_type ) tree_items = self . apply_hook ( tree_items , '%s.children' % navigation_type ) self . update_has_children ( tree_alias , tree_items , navigation_type ) my_template = get_template ( use_template ) context . push ( ) context [ 'sitetree_items' ] = tree_items rendered = my_template . render ( context . flatten ( ) if _CONTEXT_FLATTEN else context ) context . pop ( ) return rendered

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


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

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

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

def get_children ( self , tree_alias , item ) : if not self . current_app_is_admin ( ) : tree_alias = self . resolve_tree_i18n_alias ( tree_alias ) return self . cache . get_entry ( 'parents' , tree_alias ) [ item ]


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

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

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

Updates has_children attribute for tree items inplace .


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

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

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

        items_filtered = []

        context = self.current_page_context
        check_access = self.check_access

        for item in items:
            if item.hidden:
                continue

            if not check_access(item, context):
                continue

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

            items_filtered.append(item)

        return items_filtered

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

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


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

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

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

        if parent is None:
            return base_item

        return parent

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

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


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

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

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

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


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

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

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

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

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

        return varname

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

Resolves name as a variable in a given context .


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

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

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

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

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


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

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

           Basically template argument should contain path to current template itself.

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

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

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

Parses sitetree_children tag parameters .


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

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

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

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

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

Parses sitetree_breadcrumbs tag parameters .


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

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

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

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

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

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


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

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

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

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

    return content

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

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


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

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

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


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

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

Returns a URL for a given Tree admin page type .


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

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

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