<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2010 Santhosh Thottingal <santhosh.thottingal@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import cgitb
import os
import cgi
import sys
from common import *

class Webfonts(SilpaModule):
    def __init__(self):
        self.template = os.path.join(os.path.dirname(__file__), 'index.html')
        self.font=None
        self.available_fonts=['Meera','Rachana', 'Suruma', 'AnjaliOldLipi', 'Kalyani','RaghuMalayalam','Lohit Malayalam','Dyuthi','Mallige-n','Kedage-n','lohith_kn']

    def set_request(self,request):
        self.request=request
        self.font = self.request.get('font')

    def is_self_serve(self) :
        if self.font:
            return True
        else:
            return False

    def get_mimetype(self):
        return "text/css"

    def serve(self,font=None):
        """
        Provide the css for the given font. CSS will differ for IE and Other browsers
        """
        http_host =self.request.get('HTTP_HOST')

        if self.font not in self.available_fonts:
            return "Error!, Font not available"
        user_agent= self.request.get('HTTP_USER_AGENT')
        if user_agent.find("MSIE")<0:
            css = "@font-face {font-family: '$$FONTFAMILY$$';font-style: normal;font-weight: normal;src: local('$$FONTFAMILY$$'), url('$$FONTURL$$') format('truetype');}"
            css=css.replace('$$FONTURL$$','http://'+ http_host +'/webfonts/font/' + self.font + '.ttf')
        else:
            css = "@font-face {font-family: '$$FONTFAMILY$$';font-style: normal;font-weight: normal;src:local('$$FONTFAMILY$$'), url('$$FONTURL$$');}"
            css=css.replace('$$FONTURL$$','http://'+ http_host +'/webfonts/font/' + self.font + '.eot')

        css=css.replace('$$FONTFAMILY$$',self.font)
        return css

    @ServiceMethod
    def get_fonts_list(self, language=None):
        """
        return a list of available fonts names for the given Language
        If the language is not given, return all the available fonts
        """
        return self.available_fonts

    def get_module_name(self):
        return "Webfonts"

    def get_info(self):
        return  "Indic Webfonts"

def getInstance():
    return Webfonts()

<commit_msg>Lohith font name was mis-spelled as lohith_kn changed to lohit_kn<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2010 Santhosh Thottingal <santhosh.thottingal@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import cgitb
import os
import cgi
import sys
from common import *

class Webfonts(SilpaModule):
    def __init__(self):
        self.template = os.path.join(os.path.dirname(__file__), 'index.html')
        self.font=None
        self.available_fonts=['Meera','Rachana', 'Suruma', 'AnjaliOldLipi', 'Kalyani','RaghuMalayalam','Lohit Malayalam','Dyuthi','Mallige-n','Kedage-n','lohit_kn']

    def set_request(self,request):
        self.request=request
        self.font = self.request.get('font')

    def is_self_serve(self) :
        if self.font:
            return True
        else:
            return False

    def get_mimetype(self):
        return "text/css"

    def serve(self,font=None):
        """
        Provide the css for the given font. CSS will differ for IE and Other browsers
        """
        http_host =self.request.get('HTTP_HOST')

        if self.font not in self.available_fonts:
            return "Error!, Font not available"
        user_agent= self.request.get('HTTP_USER_AGENT')
        if user_agent.find("MSIE")<0:
            css = "@font-face {font-family: '$$FONTFAMILY$$';font-style: normal;font-weight: normal;src: local('$$FONTFAMILY$$'), url('$$FONTURL$$') format('truetype');}"
            css=css.replace('$$FONTURL$$','http://'+ http_host +'/webfonts/font/' + self.font + '.ttf')
        else:
            css = "@font-face {font-family: '$$FONTFAMILY$$';font-style: normal;font-weight: normal;src:local('$$FONTFAMILY$$'), url('$$FONTURL$$');}"
            css=css.replace('$$FONTURL$$','http://'+ http_host +'/webfonts/font/' + self.font + '.eot')

        css=css.replace('$$FONTFAMILY$$',self.font)
        return css

    @ServiceMethod
    def get_fonts_list(self, language=None):
        """
        return a list of available fonts names for the given Language
        If the language is not given, return all the available fonts
        """
        return self.available_fonts

    def get_module_name(self):
        return "Webfonts"

    def get_info(self):
        return  "Indic Webfonts"

def getInstance():
    return Webfonts()

<|endoftext|>


<commit_before>from django.utils.importlib import import_module
from django.conf.urls.defaults import include as urlconf_include

class Application(object):
    def __init__(self, application_name, local_name, title, **kwargs):
        self.application_name, self.local_name = application_name, local_name
        self.title = title

        self.authentication = kwargs.pop('authentication', None)
        self.secure = kwargs.pop('secure', False)
        self.extra_bases = kwargs.pop('extra_bases', ())
        self.urlconf = kwargs.pop('urlconf', application_name+'.urls')
        self.kwargs = kwargs
        self.batches = []
        self.conf = None

        kwargs['display_to_user'] = kwargs.get('display_to_user', True)

        self.providers = kwargs.pop('providers', ())
        if 'provider' in kwargs:
            self.providers += (kwargs.pop('provider'),)

    def get(self):
        if self.conf:
            return self.conf

        from molly.utils.views import BaseView, SecureView

        providers = []
        for provider in self.providers:
            if isinstance(provider, SimpleProvider):
                providers.append(provider())
            else:
                providers.append(SimpleProvider(provider)())
        try:
            import_module(self.urlconf)
        except ImportError, e:
            urls = type('Missing'+self.local_name.capitalize()+'URLConf', (object,), {'__nonzero__':(lambda self: False)})()
        else:
            urls = urlconf_include(self.urlconf, self.application_name.split('.')[-1], self.local_name)

        self.kwargs.update({
            'application_name': self.application_name,
            'local_name': self.local_name,
            'title': self.title,
            'providers': providers,
            'provider': providers[-1] if len(providers) else None,
            'urls': urls,
            'display_to_user': self.kwargs['display_to_user'] and (urls is not None),
        })
        self.conf = type(self.local_name.capitalize()+'Conf', (object,), self.kwargs)

        try:
            views_module = import_module(self.application_name+'.views')
        except ImportError:
            views_module = None
        else:
            bases = tuple(base() for base in self.extra_bases)
            if self.secure:
                bases = (SecureView,) + bases

            bar = dir(views_module)
            for n in dir(views_module):
                view = getattr(views_module, n)
                if not isinstance(view, type) or not BaseView in view.__mro__ or view is BaseView or view.__dict__.get('abstract'):
                    continue

                view.conf = self.conf
                view.__bases__ = bases + view.__bases__

        return self.conf

class Authentication(object):
    def __init__(klass, **kwargs):
        pass

class ExtraBase(object):
    def __init__(self, klass, **kwargs):
        self.klass, self.kwargs = klass, kwargs

    def __call__(self):
        mod_name, cls_name = self.klass.rsplit('.', 1)
        module = import_module(mod_name)
        klass = getattr(module, cls_name)
        base = type(cls_name, (klass,), self.kwargs)
        base.__module__ = mod_name
        return base

def extract_installed_apps(applications):
    return tuple(app.application_name for app in applications)

class SimpleProvider(object):
    def __init__(self, klass, **kwargs):
        self.klass, self.kwargs = klass, kwargs

    def __call__(self):
        try:
            return self._provider
        except:
            mod_name, cls_name = self.klass.rsplit('.', 1)
            module = import_module(mod_name)
            klass = getattr(module, cls_name)
            self._provider = klass(**self.kwargs)
            self._provider.class_path = self.klass
            return self._provider

def batch(cron_stmt, initial_metadata={}):
    def g(f):
        f.is_batch = True
        f.cron_stmt = cron_stmt
        f.initial_metadata = initial_metadata
        return f
    return g
<commit_msg>Conf objects and extra bases classes are now no longer monkey-patched onto views. Instead, we walk the urlconf tree for an application and create new views that subclass the originals, adding in the conf and extra base classes.<commit_after>from django.utils.importlib import import_module
from django.conf.urls.defaults import include as urlconf_include
from django.core.urlresolvers import RegexURLResolver, RegexURLPattern

"""
Provides a framework for Molly application objects.

An Application object wraps a Django application, and allows Molly to
extend an application with configuration information, and add extra base
classes to views to mix-in deployment-specific functionality.
"""

# This module does a lot of dynamically creating class objects using the
# second form of the 'type' function.[0]
#
# [0] http://docs.python.org/library/functions.html#type

class Application(object):
    def __init__(self, application_name, local_name, title, **kwargs):
        self.application_name, self.local_name = application_name, local_name
        self.title = title

        self.authentication = kwargs.pop('authentication', None)
        self.secure = kwargs.pop('secure', False)
        self.extra_bases = kwargs.pop('extra_bases', ())
        self.urlconf = kwargs.pop('urlconf', application_name+'.urls')
        self.kwargs = kwargs
        self.batches = []
        self.conf = None

        kwargs['display_to_user'] = kwargs.get('display_to_user', True)

        self.providers = kwargs.pop('providers', ())
        if 'provider' in kwargs:
            self.providers += (kwargs.pop('provider'),)

    def get(self):
        if self.conf:
            return self.conf

        providers = []
        for provider in self.providers:
            if isinstance(provider, SimpleProvider):
                providers.append(provider())
            else:
                providers.append(SimpleProvider(provider)())

        self.kwargs.update({
            'application_name': self.application_name,
            'local_name': self.local_name,
            'title': self.title,
            'providers': providers,
            'provider': providers[-1] if len(providers) else None,
        })
        self.conf = type(self.local_name.capitalize()+'Conf', (object,), self.kwargs)

        try:
            urlpatterns = import_module(self.urlconf).urlpatterns
        except ImportError, e:
            if e.message == 'No module named urls':
                # We'll assume this means the application we're trying to load
                # doesn't have a urls module, so we'll create a usefully named
                # object in case someone tries to include it in a urlconf.
                urls = type('Missing'+self.local_name.capitalize()+'URLConf',
                            (object,),
                            { '__nonzero__':(lambda self: False)} )()
            else:
                # Otherwise, the ImportError was something else unexpected and
                # we should give up and tell someone.
                raise
        else:
            # Load our extra base classes
            bases = tuple(base() for base in self.extra_bases)
            if self.secure:
                from molly.utils.views import SecureView
                bases = (SecureView,) + bases

            # Walk the tree of urlpatterns to add the conf and bases
            new_urlpatterns = []
            for pattern in urlpatterns:
                new_urlpatterns.append(self.add_conf_to_pattern(pattern, self.conf, bases))
            urls = urlconf_include(new_urlpatterns, self.application_name.split('.')[-1], self.local_name)

        # Add our newly created urls to our conf object.
        self.conf.urls = urls
        self.conf.display_to_user = self.kwargs['display_to_user'] and isinstance(urls, tuple)

        return self.conf

    def add_conf_to_pattern(self, pattern, conf, bases):
        """
        Coalesces an Application's configuration with the views in its urlconf.

        Takes a RegexURLPattern or RegexURLResolver, a conf object and a tuple
        of extra base classes to inherit from. Returns an object of the same
        type as its first argument with callbacks replaced with new views using
        conf and bases.
        """

        # Don't import at module scope as this module will be imported from a
        # settings file.
        from molly.utils.views import BaseView

        if isinstance(pattern, RegexURLResolver):
            # Recurse through the patterns
            patterns = []
            for subpattern in pattern.url_patterns:
                patterns.append(self.add_conf_to_pattern(subpattern, conf, bases))
            # Create a new RegexURLResolver with the new patterns
            return RegexURLResolver(pattern.regex.pattern, # The regex pattern string
                                    patterns,
                                    pattern.default_kwargs,
                                    pattern.app_name,
                                    pattern.namespace)
        elif isinstance(pattern, RegexURLPattern):
            # Get the callback and make sure it derives BaseView
            callback = pattern.callback
            if not (isinstance(callback, type) and BaseView in callback.__mro__):
                return
            # Create a new callback with the conf and extra bases
            callback = type(callback.__name__ + 'WithConf',
                            (callback,) + bases + callback.__bases__,
                            { 'conf': conf })
            # Transplant this new callback into a new RegexURLPattern, keeping
            # the same regex, default_args and name.
            return RegexURLPattern(pattern.regex.pattern,
                                   callback,
                                   pattern.default_args,
                                   pattern.name)
        else:
            raise TypeError("Expected RegexURLResolver or RegexURLPattern instance, got %r." % type(pattern))

class Authentication(object):
    def __init__(klass, **kwargs):
        pass

class ExtraBase(object):
    def __init__(self, klass, **kwargs):
        self.klass, self.kwargs = klass, kwargs

    def __call__(self):
        mod_name, cls_name = self.klass.rsplit('.', 1)
        module = import_module(mod_name)
        klass = getattr(module, cls_name)
        base = type(cls_name, (klass,), self.kwargs)
        base.__module__ = mod_name
        return base

def extract_installed_apps(applications):
    return tuple(app.application_name for app in applications)

class SimpleProvider(object):
    def __init__(self, klass, **kwargs):
        self.klass, self.kwargs = klass, kwargs

    def __call__(self):
        try:
            return self._provider
        except:
            mod_name, cls_name = self.klass.rsplit('.', 1)
            module = import_module(mod_name)
            klass = getattr(module, cls_name)
            self._provider = klass(**self.kwargs)
            self._provider.class_path = self.klass
            return self._provider

def batch(cron_stmt, initial_metadata={}):
    def g(f):
        f.is_batch = True
        f.cron_stmt = cron_stmt
        f.initial_metadata = initial_metadata
        return f
    return g
<|endoftext|>


<commit_before># Copyright 2020 - 2021 MONAI Consortium
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#     http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
A collection of "vanilla" transforms for IO functions
https://github.com/Project-MONAI/MONAI/wiki/MONAI_Design
"""

import sys
from typing import Dict, List, Optional, Sequence, Union

import numpy as np
import torch

from monai.config import DtypeLike
from monai.data.image_reader import ImageReader, ITKReader, NibabelReader, NumpyReader, PILReader
from monai.data.nifti_saver import NiftiSaver
from monai.data.png_saver import PNGSaver
from monai.transforms.transform import Transform
from monai.utils import GridSampleMode, GridSamplePadMode
from monai.utils import ImageMetaKey as Key
from monai.utils import InterpolateMode, ensure_tuple, optional_import

nib, _ = optional_import("nibabel")
Image, _ = optional_import("PIL.Image")

__all__ = ["LoadImage", "SaveImage"]

def switch_endianness(data, new="<"):
    """
    Convert the input `data` endianness to `new`.

    Args:
        data: input to be converted.
        new: the target endianness, currently support "<" or ">".
    """
    if isinstance(data, np.ndarray):
        # default to system endian
        sys_native = ((sys.byteorder == "little") and "<") or ">"
        current_ = sys_native if data.dtype.byteorder not in ("<", ">") else data.dtype.byteorder
        if new not in ("<", ">"):
            raise NotImplementedError(f"Not implemented option new={new}.")
        if current_ != new:
            data = data.byteswap().newbyteorder(new)
    elif isinstance(data, tuple):
        data = tuple(switch_endianness(x, new) for x in data)
    elif isinstance(data, list):
        data = [switch_endianness(x, new) for x in data]
    elif isinstance(data, dict):
        data = {k: switch_endianness(v, new) for k, v in data.items()}
    elif isinstance(data, (bool, str, float, int, type(None))):
        pass
    else:
        raise AssertionError(f"Unknown type: {type(data).__name__}")
    return data

class LoadImage(Transform):
    """
    Load image file or files from provided path based on reader.
    Automatically choose readers based on the supported suffixes and in below order:
    - User specified reader at runtime when call this loader.
    - Registered readers from the latest to the first in list.
    - Default readers: (nii, nii.gz -> NibabelReader), (png, jpg, bmp -> PILReader),
    (npz, npy -> NumpyReader), (others -> ITKReader).

    """

    def __init__(
        self,
        reader: Optional[Union[ImageReader, str]] = None,
        image_only: bool = False,
        dtype: DtypeLike = np.float32,
        *args,
        **kwargs,
    ) -> None:
        """
        Args:
            reader: register reader to load image file and meta data, if None, still can register readers
                at runtime or use the default readers. If a string of reader name provided, will construct
                a reader object with the `*args` and `**kwargs` parameters, supported reader name: "NibabelReader",
                "PILReader", "ITKReader", "NumpyReader".
            image_only: if True return only the image volume, otherwise return image data array and header dict.
            dtype: if not None convert the loaded image to this data type.
            args: additional parameters for reader if providing a reader name.
            kwargs: additional parameters for reader if providing a reader name.

        Note:
            The transform returns image data array if `image_only` is True,
            or a tuple of two elements containing the data array, and the meta data in a dict format otherwise.

        """
        # set predefined readers as default
        self.readers: List[ImageReader] = [ITKReader(), NumpyReader(), PILReader(), NibabelReader()]
        if reader is not None:
            if isinstance(reader, str):
                supported_readers = {
                    "nibabelreader": NibabelReader,
                    "pilreader": PILReader,
                    "itkreader": ITKReader,
                    "numpyreader": NumpyReader,
                }
                reader = reader.lower()
                if reader not in supported_readers:
                    raise ValueError(f"unsupported reader type: {reader}, available options: {supported_readers}.")
                self.register(supported_readers[reader](*args, **kwargs))
            else:
                self.register(reader)

        self.image_only = image_only
        self.dtype = dtype

    def register(self, reader: ImageReader) -> List[ImageReader]:
        """
        Register image reader to load image file and meta data, latest registered reader has higher priority.
        Return all the registered image readers.

        Args:
            reader: registered reader to load image file and meta data based on suffix,
                if all registered readers can't match suffix at runtime, use the default readers.

        """
        if not isinstance(reader, ImageReader):
            raise ValueError(f"reader must be ImageReader object, but got {type(reader)}.")
        self.readers.append(reader)
        return self.readers

    def __call__(
        self,
        filename: Union[Sequence[str], str],
        reader: Optional[ImageReader] = None,
    ):
        """
        Args:
            filename: path file or file-like object or a list of files.
                will save the filename to meta_data with key `filename_or_obj`.
                if provided a list of files, use the filename of first file.
            reader: runtime reader to load image file and meta data.

        """
        if reader is None or not reader.verify_suffix(filename):
            for r in reversed(self.readers):
                if r.verify_suffix(filename):
                    reader = r
                    break

        if reader is None:
            raise RuntimeError(
                f"can not find suitable reader for this file: {filename}. \
                Please install dependency libraries: (nii, nii.gz) -> Nibabel, (png, jpg, bmp) -> PIL, \
                (npz, npy) -> Numpy, others -> ITK. Refer to the installation instruction: \
                https://docs.monai.io/en/latest/installation.html#installing-the-recommended-dependencies."
            )

        img = reader.read(filename)
        img_array, meta_data = reader.get_data(img)
        img_array = img_array.astype(self.dtype)

        if self.image_only:
            return img_array
        meta_data[Key.FILENAME_OR_OBJ] = ensure_tuple(filename)[0]
        # make sure all elements in metadata are little endian
        meta_data = switch_endianness(meta_data, "<")

        return img_array, meta_data

class SaveImage(Transform):
    """
    Save transformed data into files, support NIfTI and PNG formats.
    It can work for both numpy array and PyTorch Tensor in both preprocessing transform
    chain and postprocessing transform chain.
    The name of saved file will be `{input_image_name}_{output_postfix}{output_ext}`,
    where the input image name is extracted from the provided meta data dictionary.
    If no meta data provided, use index from 0 as the filename prefix.
    It can also save a list of PyTorch Tensor or numpy array without `batch dim`.

    Note: image should be channel-first shape: [C,H,W,[D]].

    Args:
        output_dir: output image directory.
        output_postfix: a string appended to all output file names, default to `trans`.
        output_ext: output file extension name, available extensions: `.nii.gz`, `.nii`, `.png`.
        resample: whether to resample before saving the data array.
            if saving PNG format image, based on the `spatial_shape` from metadata.
            if saving NIfTI format image, based on the `original_affine` from metadata.
        mode: This option is used when ``resample = True``. Defaults to ``"nearest"``.

            - NIfTI files {``"bilinear"``, ``"nearest"``}
                Interpolation mode to calculate output values.
                See also: https://pytorch.org/docs/stable/nn.functional.html#grid-sample
            - PNG files {``"nearest"``, ``"linear"``, ``"bilinear"``, ``"bicubic"``, ``"trilinear"``, ``"area"``}
                The interpolation mode.
                See also: https://pytorch.org/docs/stable/nn.functional.html#interpolate

        padding_mode: This option is used when ``resample = True``. Defaults to ``"border"``.

            - NIfTI files {``"zeros"``, ``"border"``, ``"reflection"``}
                Padding mode for outside grid values.
                See also: https://pytorch.org/docs/stable/nn.functional.html#grid-sample
            - PNG files
                This option is ignored.

        scale: {``255``, ``65535``} postprocess data by clipping to [0, 1] and scaling
            [0, 255] (uint8) or [0, 65535] (uint16). Default is None to disable scaling.
            it's used for PNG format only.
        dtype: data type during resampling computation. Defaults to ``np.float64`` for best precision.
            if None, use the data type of input data. To be compatible with other modules,
            the output data type is always ``np.float32``.
            it's used for NIfTI format only.
        output_dtype: data type for saving data. Defaults to ``np.float32``.
            it's used for NIfTI format only.
        squeeze_end_dims: if True, any trailing singleton dimensions will be removed (after the channel
            has been moved to the end). So if input is (C,H,W,D), this will be altered to (H,W,D,C), and
            then if C==1, it will be saved as (H,W,D). If D also ==1, it will be saved as (H,W). If false,
            image will always be saved as (H,W,D,C).
            it's used for NIfTI format only.
        data_root_dir: if not empty, it specifies the beginning parts of the input file's
            absolute path. it's used to compute `input_file_rel_path`, the relative path to the file from
            `data_root_dir` to preserve folder structure when saving in case there are files in different
            folders with the same file names. for example:
            input_file_name: /foo/bar/test1/image.nii,
            output_postfix: seg
            output_ext: nii.gz
            output_dir: /output,
            data_root_dir: /foo/bar,
            output will be: /output/test1/image/image_seg.nii.gz
        print_log: whether to print log about the saved file path, etc. default to `True`.

    """

    def __init__(
        self,
        output_dir: str = "./",
        output_postfix: str = "trans",
        output_ext: str = ".nii.gz",
        resample: bool = True,
        mode: Union[GridSampleMode, InterpolateMode, str] = "nearest",
        padding_mode: Union[GridSamplePadMode, str] = GridSamplePadMode.BORDER,
        scale: Optional[int] = None,
        dtype: DtypeLike = np.float64,
        output_dtype: DtypeLike = np.float32,
        squeeze_end_dims: bool = True,
        data_root_dir: str = "",
        print_log: bool = True,
    ) -> None:
        self.saver: Union[NiftiSaver, PNGSaver]
        if output_ext in (".nii.gz", ".nii"):
            self.saver = NiftiSaver(
                output_dir=output_dir,
                output_postfix=output_postfix,
                output_ext=output_ext,
                resample=resample,
                mode=GridSampleMode(mode),
                padding_mode=padding_mode,
                dtype=dtype,
                output_dtype=output_dtype,
                squeeze_end_dims=squeeze_end_dims,
                data_root_dir=data_root_dir,
                print_log=print_log,
            )
        elif output_ext == ".png":
            self.saver = PNGSaver(
                output_dir=output_dir,
                output_postfix=output_postfix,
                output_ext=output_ext,
                resample=resample,
                mode=InterpolateMode(mode),
                scale=scale,
                data_root_dir=data_root_dir,
                print_log=print_log,
            )
        else:
            raise ValueError(f"unsupported output extension: {output_ext}.")

    def __call__(self, img: Union[torch.Tensor, np.ndarray], meta_data: Optional[Dict] = None):
        """
        Args:
            img: target data content that save into file.
            meta_data: key-value pairs of meta_data corresponding to the data.

        """
        self.saver.save(img, meta_data)
<commit_msg>[DLMED] add return to SaveImage (#2568)<commit_after># Copyright 2020 - 2021 MONAI Consortium
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#     http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
A collection of "vanilla" transforms for IO functions
https://github.com/Project-MONAI/MONAI/wiki/MONAI_Design
"""

import sys
from typing import Dict, List, Optional, Sequence, Union

import numpy as np
import torch

from monai.config import DtypeLike
from monai.data.image_reader import ImageReader, ITKReader, NibabelReader, NumpyReader, PILReader
from monai.data.nifti_saver import NiftiSaver
from monai.data.png_saver import PNGSaver
from monai.transforms.transform import Transform
from monai.utils import GridSampleMode, GridSamplePadMode
from monai.utils import ImageMetaKey as Key
from monai.utils import InterpolateMode, ensure_tuple, optional_import

nib, _ = optional_import("nibabel")
Image, _ = optional_import("PIL.Image")

__all__ = ["LoadImage", "SaveImage"]

def switch_endianness(data, new="<"):
    """
    Convert the input `data` endianness to `new`.

    Args:
        data: input to be converted.
        new: the target endianness, currently support "<" or ">".
    """
    if isinstance(data, np.ndarray):
        # default to system endian
        sys_native = ((sys.byteorder == "little") and "<") or ">"
        current_ = sys_native if data.dtype.byteorder not in ("<", ">") else data.dtype.byteorder
        if new not in ("<", ">"):
            raise NotImplementedError(f"Not implemented option new={new}.")
        if current_ != new:
            data = data.byteswap().newbyteorder(new)
    elif isinstance(data, tuple):
        data = tuple(switch_endianness(x, new) for x in data)
    elif isinstance(data, list):
        data = [switch_endianness(x, new) for x in data]
    elif isinstance(data, dict):
        data = {k: switch_endianness(v, new) for k, v in data.items()}
    elif isinstance(data, (bool, str, float, int, type(None))):
        pass
    else:
        raise AssertionError(f"Unknown type: {type(data).__name__}")
    return data

class LoadImage(Transform):
    """
    Load image file or files from provided path based on reader.
    Automatically choose readers based on the supported suffixes and in below order:
    - User specified reader at runtime when call this loader.
    - Registered readers from the latest to the first in list.
    - Default readers: (nii, nii.gz -> NibabelReader), (png, jpg, bmp -> PILReader),
    (npz, npy -> NumpyReader), (others -> ITKReader).

    """

    def __init__(
        self,
        reader: Optional[Union[ImageReader, str]] = None,
        image_only: bool = False,
        dtype: DtypeLike = np.float32,
        *args,
        **kwargs,
    ) -> None:
        """
        Args:
            reader: register reader to load image file and meta data, if None, still can register readers
                at runtime or use the default readers. If a string of reader name provided, will construct
                a reader object with the `*args` and `**kwargs` parameters, supported reader name: "NibabelReader",
                "PILReader", "ITKReader", "NumpyReader".
            image_only: if True return only the image volume, otherwise return image data array and header dict.
            dtype: if not None convert the loaded image to this data type.
            args: additional parameters for reader if providing a reader name.
            kwargs: additional parameters for reader if providing a reader name.

        Note:
            The transform returns image data array if `image_only` is True,
            or a tuple of two elements containing the data array, and the meta data in a dict format otherwise.

        """
        # set predefined readers as default
        self.readers: List[ImageReader] = [ITKReader(), NumpyReader(), PILReader(), NibabelReader()]
        if reader is not None:
            if isinstance(reader, str):
                supported_readers = {
                    "nibabelreader": NibabelReader,
                    "pilreader": PILReader,
                    "itkreader": ITKReader,
                    "numpyreader": NumpyReader,
                }
                reader = reader.lower()
                if reader not in supported_readers:
                    raise ValueError(f"unsupported reader type: {reader}, available options: {supported_readers}.")
                self.register(supported_readers[reader](*args, **kwargs))
            else:
                self.register(reader)

        self.image_only = image_only
        self.dtype = dtype

    def register(self, reader: ImageReader) -> List[ImageReader]:
        """
        Register image reader to load image file and meta data, latest registered reader has higher priority.
        Return all the registered image readers.

        Args:
            reader: registered reader to load image file and meta data based on suffix,
                if all registered readers can't match suffix at runtime, use the default readers.

        """
        if not isinstance(reader, ImageReader):
            raise ValueError(f"reader must be ImageReader object, but got {type(reader)}.")
        self.readers.append(reader)
        return self.readers

    def __call__(
        self,
        filename: Union[Sequence[str], str],
        reader: Optional[ImageReader] = None,
    ):
        """
        Args:
            filename: path file or file-like object or a list of files.
                will save the filename to meta_data with key `filename_or_obj`.
                if provided a list of files, use the filename of first file.
            reader: runtime reader to load image file and meta data.

        """
        if reader is None or not reader.verify_suffix(filename):
            for r in reversed(self.readers):
                if r.verify_suffix(filename):
                    reader = r
                    break

        if reader is None:
            raise RuntimeError(
                f"can not find suitable reader for this file: {filename}. \
                Please install dependency libraries: (nii, nii.gz) -> Nibabel, (png, jpg, bmp) -> PIL, \
                (npz, npy) -> Numpy, others -> ITK. Refer to the installation instruction: \
                https://docs.monai.io/en/latest/installation.html#installing-the-recommended-dependencies."
            )

        img = reader.read(filename)
        img_array, meta_data = reader.get_data(img)
        img_array = img_array.astype(self.dtype)

        if self.image_only:
            return img_array
        meta_data[Key.FILENAME_OR_OBJ] = ensure_tuple(filename)[0]
        # make sure all elements in metadata are little endian
        meta_data = switch_endianness(meta_data, "<")

        return img_array, meta_data

class SaveImage(Transform):
    """
    Save transformed data into files, support NIfTI and PNG formats.
    It can work for both numpy array and PyTorch Tensor in both preprocessing transform
    chain and postprocessing transform chain.
    The name of saved file will be `{input_image_name}_{output_postfix}{output_ext}`,
    where the input image name is extracted from the provided meta data dictionary.
    If no meta data provided, use index from 0 as the filename prefix.
    It can also save a list of PyTorch Tensor or numpy array without `batch dim`.

    Note: image should be channel-first shape: [C,H,W,[D]].

    Args:
        output_dir: output image directory.
        output_postfix: a string appended to all output file names, default to `trans`.
        output_ext: output file extension name, available extensions: `.nii.gz`, `.nii`, `.png`.
        resample: whether to resample before saving the data array.
            if saving PNG format image, based on the `spatial_shape` from metadata.
            if saving NIfTI format image, based on the `original_affine` from metadata.
        mode: This option is used when ``resample = True``. Defaults to ``"nearest"``.

            - NIfTI files {``"bilinear"``, ``"nearest"``}
                Interpolation mode to calculate output values.
                See also: https://pytorch.org/docs/stable/nn.functional.html#grid-sample
            - PNG files {``"nearest"``, ``"linear"``, ``"bilinear"``, ``"bicubic"``, ``"trilinear"``, ``"area"``}
                The interpolation mode.
                See also: https://pytorch.org/docs/stable/nn.functional.html#interpolate

        padding_mode: This option is used when ``resample = True``. Defaults to ``"border"``.

            - NIfTI files {``"zeros"``, ``"border"``, ``"reflection"``}
                Padding mode for outside grid values.
                See also: https://pytorch.org/docs/stable/nn.functional.html#grid-sample
            - PNG files
                This option is ignored.

        scale: {``255``, ``65535``} postprocess data by clipping to [0, 1] and scaling
            [0, 255] (uint8) or [0, 65535] (uint16). Default is None to disable scaling.
            it's used for PNG format only.
        dtype: data type during resampling computation. Defaults to ``np.float64`` for best precision.
            if None, use the data type of input data. To be compatible with other modules,
            the output data type is always ``np.float32``.
            it's used for NIfTI format only.
        output_dtype: data type for saving data. Defaults to ``np.float32``.
            it's used for NIfTI format only.
        squeeze_end_dims: if True, any trailing singleton dimensions will be removed (after the channel
            has been moved to the end). So if input is (C,H,W,D), this will be altered to (H,W,D,C), and
            then if C==1, it will be saved as (H,W,D). If D also ==1, it will be saved as (H,W). If false,
            image will always be saved as (H,W,D,C).
            it's used for NIfTI format only.
        data_root_dir: if not empty, it specifies the beginning parts of the input file's
            absolute path. it's used to compute `input_file_rel_path`, the relative path to the file from
            `data_root_dir` to preserve folder structure when saving in case there are files in different
            folders with the same file names. for example:
            input_file_name: /foo/bar/test1/image.nii,
            output_postfix: seg
            output_ext: nii.gz
            output_dir: /output,
            data_root_dir: /foo/bar,
            output will be: /output/test1/image/image_seg.nii.gz
        print_log: whether to print log about the saved file path, etc. default to `True`.

    """

    def __init__(
        self,
        output_dir: str = "./",
        output_postfix: str = "trans",
        output_ext: str = ".nii.gz",
        resample: bool = True,
        mode: Union[GridSampleMode, InterpolateMode, str] = "nearest",
        padding_mode: Union[GridSamplePadMode, str] = GridSamplePadMode.BORDER,
        scale: Optional[int] = None,
        dtype: DtypeLike = np.float64,
        output_dtype: DtypeLike = np.float32,
        squeeze_end_dims: bool = True,
        data_root_dir: str = "",
        print_log: bool = True,
    ) -> None:
        self.saver: Union[NiftiSaver, PNGSaver]
        if output_ext in (".nii.gz", ".nii"):
            self.saver = NiftiSaver(
                output_dir=output_dir,
                output_postfix=output_postfix,
                output_ext=output_ext,
                resample=resample,
                mode=GridSampleMode(mode),
                padding_mode=padding_mode,
                dtype=dtype,
                output_dtype=output_dtype,
                squeeze_end_dims=squeeze_end_dims,
                data_root_dir=data_root_dir,
                print_log=print_log,
            )
        elif output_ext == ".png":
            self.saver = PNGSaver(
                output_dir=output_dir,
                output_postfix=output_postfix,
                output_ext=output_ext,
                resample=resample,
                mode=InterpolateMode(mode),
                scale=scale,
                data_root_dir=data_root_dir,
                print_log=print_log,
            )
        else:
            raise ValueError(f"unsupported output extension: {output_ext}.")

    def __call__(self, img: Union[torch.Tensor, np.ndarray], meta_data: Optional[Dict] = None):
        """
        Args:
            img: target data content that save into file.
            meta_data: key-value pairs of meta_data corresponding to the data.

        """
        self.saver.save(img, meta_data)

        return img
<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
=====================
Classifier comparison
=====================

A comparison of a several classifiers in scikit-learn on synthetic datasets.
The point of this example is to illustrate the nature of decision boundaries
of different classifiers.
This should be taken with a grain of salt, as the intuition conveyed by
these examples does not necessarily carry over to real datasets.

Particularly in high-dimensional spaces, data can more easily be separated
linearly and the simplicity of classifiers such as naive Bayes and linear SVMs
might lead to better generalization than is achieved by other classifiers.

The plots show training points in solid colors and testing points
semi-transparent. The lower right shows the classification accuracy on the test
set.
"""
print(__doc__)

# Code source: Gaël Varoquaux
#              Andreas Müller
# Modified for documentation by Jaques Grobler
# License: BSD 3 clause

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_moons, make_circles, make_classification
from sklearn.neural_network import MLPClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.gaussian_process.kernels import RBF
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis

h = .02  # step size in the mesh

names = ["Nearest Neighbors", "Linear SVM", "RBF SVM", "Gaussian Process",
         "Decision Tree", "Random Forest", "Neural Net", "AdaBoost",
         "Naive Bayes", "QDA"]

classifiers = [
    KNeighborsClassifier(3),
    SVC(kernel="linear", C=0.025),
    SVC(gamma=2, C=1),
    GaussianProcessClassifier(1.0 * RBF(1.0), warm_start=True),
    DecisionTreeClassifier(max_depth=5),
    RandomForestClassifier(max_depth=5, n_estimators=10, max_features=1),
    MLPClassifier(alpha=1),
    AdaBoostClassifier(),
    GaussianNB(),
    QuadraticDiscriminantAnalysis()]

X, y = make_classification(n_features=2, n_redundant=0, n_informative=2,
                           random_state=1, n_clusters_per_class=1)
rng = np.random.RandomState(2)
X += 2 * rng.uniform(size=X.shape)
linearly_separable = (X, y)

datasets = [make_moons(noise=0.3, random_state=0),
            make_circles(noise=0.2, factor=0.5, random_state=1),
            linearly_separable
            ]

figure = plt.figure(figsize=(27, 9))
i = 1
# iterate over datasets
for ds_cnt, ds in enumerate(datasets):
    # preprocess dataset, split into training and test part
    X, y = ds
    X = StandardScaler().fit_transform(X)
    X_train, X_test, y_train, y_test = \
        train_test_split(X, y, test_size=.4, random_state=42)

    x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
    y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))

    # just plot the dataset first
    cm = plt.cm.RdBu
    cm_bright = ListedColormap(['#FF0000', '#0000FF'])
    ax = plt.subplot(len(datasets), len(classifiers) + 1, i)
    if ds_cnt == 0:
        ax.set_title("Input data")
    # Plot the training points
    ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright)
    # and testing points
    ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, alpha=0.6)
    ax.set_xlim(xx.min(), xx.max())
    ax.set_ylim(yy.min(), yy.max())
    ax.set_xticks(())
    ax.set_yticks(())
    i += 1

    # iterate over classifiers
    for name, clf in zip(names, classifiers):
        ax = plt.subplot(len(datasets), len(classifiers) + 1, i)
        clf.fit(X_train, y_train)
        score = clf.score(X_test, y_test)

        # Plot the decision boundary. For that, we will assign a color to each
        # point in the mesh [x_min, x_max]x[y_min, y_max].
        if hasattr(clf, "decision_function"):
            Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
        else:
            Z = clf.predict_proba(np.c_[xx.ravel(), yy.ravel()])[:, 1]

        # Put the result into a color plot
        Z = Z.reshape(xx.shape)
        ax.contourf(xx, yy, Z, cmap=cm, alpha=.8)

        # Plot also the training points
        ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright)
        # and testing points
        ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright,
                   alpha=0.6)

        ax.set_xlim(xx.min(), xx.max())
        ax.set_ylim(yy.min(), yy.max())
        ax.set_xticks(())
        ax.set_yticks(())
        if ds_cnt == 0:
            ax.set_title(name)
        ax.text(xx.max() - .3, yy.min() + .3, ('%.2f' % score).lstrip('0'),
                size=15, horizontalalignment='right')
        i += 1

plt.tight_layout()
plt.show()
<commit_msg>[MRG] Modify Classification module example matplotlibv2 (#8516)<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
=====================
Classifier comparison
=====================

A comparison of a several classifiers in scikit-learn on synthetic datasets.
The point of this example is to illustrate the nature of decision boundaries
of different classifiers.
This should be taken with a grain of salt, as the intuition conveyed by
these examples does not necessarily carry over to real datasets.

Particularly in high-dimensional spaces, data can more easily be separated
linearly and the simplicity of classifiers such as naive Bayes and linear SVMs
might lead to better generalization than is achieved by other classifiers.

The plots show training points in solid colors and testing points
semi-transparent. The lower right shows the classification accuracy on the test
set.
"""
print(__doc__)

# Code source: Gaël Varoquaux
#              Andreas Müller
# Modified for documentation by Jaques Grobler
# License: BSD 3 clause

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_moons, make_circles, make_classification
from sklearn.neural_network import MLPClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.gaussian_process.kernels import RBF
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis

h = .02  # step size in the mesh

names = ["Nearest Neighbors", "Linear SVM", "RBF SVM", "Gaussian Process",
         "Decision Tree", "Random Forest", "Neural Net", "AdaBoost",
         "Naive Bayes", "QDA"]

classifiers = [
    KNeighborsClassifier(3),
    SVC(kernel="linear", C=0.025),
    SVC(gamma=2, C=1),
    GaussianProcessClassifier(1.0 * RBF(1.0), warm_start=True),
    DecisionTreeClassifier(max_depth=5),
    RandomForestClassifier(max_depth=5, n_estimators=10, max_features=1),
    MLPClassifier(alpha=1),
    AdaBoostClassifier(),
    GaussianNB(),
    QuadraticDiscriminantAnalysis()]

X, y = make_classification(n_features=2, n_redundant=0, n_informative=2,
                           random_state=1, n_clusters_per_class=1)
rng = np.random.RandomState(2)
X += 2 * rng.uniform(size=X.shape)
linearly_separable = (X, y)

datasets = [make_moons(noise=0.3, random_state=0),
            make_circles(noise=0.2, factor=0.5, random_state=1),
            linearly_separable
            ]

figure = plt.figure(figsize=(27, 9))
i = 1
# iterate over datasets
for ds_cnt, ds in enumerate(datasets):
    # preprocess dataset, split into training and test part
    X, y = ds
    X = StandardScaler().fit_transform(X)
    X_train, X_test, y_train, y_test = \
        train_test_split(X, y, test_size=.4, random_state=42)

    x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
    y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))

    # just plot the dataset first
    cm = plt.cm.RdBu
    cm_bright = ListedColormap(['#FF0000', '#0000FF'])
    ax = plt.subplot(len(datasets), len(classifiers) + 1, i)
    if ds_cnt == 0:
        ax.set_title("Input data")
    # Plot the training points
    ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright,
               edgecolors='k')
    # and testing points
    ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, alpha=0.6,
               edgecolors='k')
    ax.set_xlim(xx.min(), xx.max())
    ax.set_ylim(yy.min(), yy.max())
    ax.set_xticks(())
    ax.set_yticks(())
    i += 1

    # iterate over classifiers
    for name, clf in zip(names, classifiers):
        ax = plt.subplot(len(datasets), len(classifiers) + 1, i)
        clf.fit(X_train, y_train)
        score = clf.score(X_test, y_test)

        # Plot the decision boundary. For that, we will assign a color to each
        # point in the mesh [x_min, x_max]x[y_min, y_max].
        if hasattr(clf, "decision_function"):
            Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
        else:
            Z = clf.predict_proba(np.c_[xx.ravel(), yy.ravel()])[:, 1]

        # Put the result into a color plot
        Z = Z.reshape(xx.shape)
        ax.contourf(xx, yy, Z, cmap=cm, alpha=.8)

        # Plot also the training points
        ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright,
                   edgecolors='k')
        # and testing points
        ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright,
                   edgecolors='k', alpha=0.6)

        ax.set_xlim(xx.min(), xx.max())
        ax.set_ylim(yy.min(), yy.max())
        ax.set_xticks(())
        ax.set_yticks(())
        if ds_cnt == 0:
            ax.set_title(name)
        ax.text(xx.max() - .3, yy.min() + .3, ('%.2f' % score).lstrip('0'),
                size=15, horizontalalignment='right')
        i += 1

plt.tight_layout()
plt.show()
<|endoftext|>


<commit_before>import atexit
import inspect

from pulsar.core import PulsarApp
from pulsar.web.framework import RoutingApp

import pulsar.web.routes

def app_factory(global_conf, **local_conf):
    """
    Returns the LWR WSGI application.
    """
    pulsar_app = PulsarApp(global_conf=global_conf, **local_conf)
    webapp = LwrWebApp(pulsar_app=pulsar_app)
    atexit.register(webapp.shutdown)
    return webapp

class LwrWebApp(RoutingApp):
    """
    Web application for LWR web server.
    """

    def __init__(self, pulsar_app):
        super(LwrWebApp, self).__init__()
        self.pulsar_app = pulsar_app
        self.__setup_routes()

    def __setup_routes(self):
        for func_name, func in inspect.getmembers(pulsar.web.routes, lambda x: getattr(x, '__controller__', False)):
            self.__add_route_for_function(func)

    def __add_route_for_function(self, function):
        path = function.__path__
        method = function.__method__

        # Default or old-style route without explicit manager specified,
        # will be routed to manager '_default_'.
        default_manager_route = path
        self.add_route(default_manager_route, method, function)
        # Add route for named manager as well.
        named_manager_route = '/managers/{manager_name}%s' % path
        self.add_route(named_manager_route, method, function)

    def __getattr__(self, name):
        return getattr(self.pulsar_app, name)
<commit_msg>Rename LwrWebApp.<commit_after>import atexit
import inspect

from pulsar.core import PulsarApp
from pulsar.web.framework import RoutingApp

import pulsar.web.routes

def app_factory(global_conf, **local_conf):
    """
    Returns the LWR WSGI application.
    """
    pulsar_app = PulsarApp(global_conf=global_conf, **local_conf)
    webapp = PulsarWebApp(pulsar_app=pulsar_app)
    atexit.register(webapp.shutdown)
    return webapp

class PulsarWebApp(RoutingApp):
    """
    Web application for LWR web server.
    """

    def __init__(self, pulsar_app):
        super(PulsarWebApp, self).__init__()
        self.pulsar_app = pulsar_app
        self.__setup_routes()

    def __setup_routes(self):
        for func_name, func in inspect.getmembers(pulsar.web.routes, lambda x: getattr(x, '__controller__', False)):
            self.__add_route_for_function(func)

    def __add_route_for_function(self, function):
        path = function.__path__
        method = function.__method__

        # Default or old-style route without explicit manager specified,
        # will be routed to manager '_default_'.
        default_manager_route = path
        self.add_route(default_manager_route, method, function)
        # Add route for named manager as well.
        named_manager_route = '/managers/{manager_name}%s' % path
        self.add_route(named_manager_route, method, function)

    def __getattr__(self, name):
        return getattr(self.pulsar_app, name)
<|endoftext|>


<commit_before>from __future__ import division, absolute_import, print_function

__all__ = ['punic_cli', 'main']

import logging
import os
import punic.shshutil as shutil
import sys
import click
from click_didyoumean import DYMGroup
import networkx as nx
import punic
from .copy_frameworks import *
from .errors import *
from .logger import *
from .model import *
from .runner import *
from .semantic_version import *
from .utilities import *
from .version_check import *
from .config_init import *

@click.group(cls=DYMGroup)
@click.option('--echo', default=False, is_flag=True, help="""Echo all commands to terminal.""")
@click.option('--verbose', default=False, is_flag=True, help="""Verbose logging.""")
@click.option('--color/--no-color', default=True, is_flag=True, help="""TECHNICOLOR.""")
@click.option('--timing/--no-timing', default=False, is_flag=True, help="""Log timing info""")
@click.pass_context
def punic_cli(context, echo, verbose, timing, color):

    # Configure click
    context.token_normalize_func = lambda x:x if not x else x.lower()

    # Configure logging
    level = logging.DEBUG if verbose else logging.INFO
    logging.basicConfig(format='%(message)s', level=level)
    runner.echo = echo
    requests_log = logging.getLogger("requests.packages.urllib3")
    requests_log.setLevel(logging.WARNING)
    requests_log.propagate = True
    logger.color = color

    # Set up punic
    punic = Punic()
    punic.config.log_timings = timing
    context.obj = punic

@punic_cli.command()
@click.pass_context
def fetch(context):
    """Fetch the project's dependencies.."""
    logger.info("<cmd>fetch</cmd>")
    punic = context.obj
    punic.config.can_fetch = True  # obviously

    with timeit('fetch', log = punic.config.log_timings):
        with error_handling():
            punic.fetch()

@punic_cli.command()
@click.pass_context
@click.option('--fetch/--no-fetch', default=True, is_flag=True, help="""Controls whether to fetch dependencies.""")
def resolve(context, fetch):
    """Resolve dependencies and output `Carthage.resolved` file.

    This sub-command does not build dependencies. Use this sub-command when a dependency has changed and you just want to update `Cartfile.resolved`.
    """
    punic = context.obj
    logger.info("<cmd>Resolve</cmd>")
    punic.config.can_fetch = fetch

    with timeit('resolve', log = punic.config.log_timings):
        with error_handling():
            punic.resolve()

@punic_cli.command()
@click.pass_context
@click.option('--configuration', default=None,
    help="""Dependency configurations to build. Usually 'Release' or 'Debug'.""")
@click.option('--platform', default=None, help="""Platform to build. Comma separated list.""")
@click.option('--fetch/--no-fetch', default=True, is_flag=True, help="""Controls whether to fetch dependencies.""")
@click.option('--xcode-version', default=None, help="""Xcode version to use""")
@click.argument('deps', nargs=-1)
def build(context, configuration, platform, fetch, xcode_version, deps):
    """Fetch and build the project's dependencies."""
    logger.info("<cmd>Build</cmd>")
    punic = context.obj

    punic.config.update(configuration=configuration, platform=platform)
    punic.config.can_fetch = fetch
    if xcode_version:
        punic.config.xcode_version = xcode_version

    with timeit('build', log = punic.config.log_timings):
        with error_handling():
            punic.build(dependencies=deps)

@punic_cli.command()
@click.pass_context
@click.option('--configuration', default=None,
    help="""Dependency configurations to build. Usually 'Release' or 'Debug'.""")
@click.option('--platform', default=None, help="""Platform to build. Comma separated list.""")
@click.option('--fetch/--no-fetch', default=True, is_flag=True, help="""Controls whether to fetch dependencies.""")
@click.option('--xcode-version', default=None, help="""Xcode version to use""")
@click.argument('deps', nargs=-1)
def update(context, configuration, platform, fetch, xcode_version, deps):
    """Update and rebuild the project's dependencies."""
    logger.info("<cmd>Update</cmd>")
    punic = context.obj
    punic.config.update(configuration=configuration, platform=platform)
    punic.config.can_fetch = fetch
    if xcode_version:
        punic.config.xcode_version = xcode_version

    with timeit('update', log = punic.config.log_timings):
        with error_handling():
            punic.resolve()
            punic.build(dependencies=deps)

@punic_cli.command()
@click.pass_context
@click.option('--derived-data', default=False, is_flag=True, help="""Clean the punic derived data directory.""")
@click.option('--caches', default=False, is_flag=True, help="""Clean the global punic carthage files.""")
@click.option('--all', default=False, is_flag=True, help="""Clean all.""")
def clean(context, derived_data, caches, all):
    """Clean project & punic environment."""
    logger.info("<cmd>Clean</cmd>")
    punic = context.obj

    if derived_data or all:
        logger.info('Erasing derived data directory')
        if punic.config.derived_data_path.exists():
            shutil.rmtree(punic.config.derived_data_path)

    if caches or all:
        if punic.config.repo_cache_directory.exists():
            logger.info('Erasing {}'.format(punic.config.repo_cache_directory))
            shutil.rmtree(punic.config.repo_cache_directory )
        logger.info('Erasing run cache')
        runner.reset()

@punic_cli.command()
@click.pass_context
@click.option('--fetch/--no-fetch', default=True, is_flag=True, help="""Controls whether to fetch dependencies.""")
@click.option('--open', default=False, is_flag=True, help="""Open the graph image file.""")
def graph(context, fetch, open):
    """Output resolved dependency graph."""
    logger.info("<cmd>Graph</cmd>")
    punic = context.obj
    punic.config.can_fetch = fetch

    with timeit('graph', log = punic.config.log_timings):
        with error_handling():

            graph = punic.graph()

            logger.info('Writing graph file to "{}".'.format(os.getcwd()))
            nx.drawing.nx_pydot.write_dot(graph, 'graph.dot')

            command = 'dot graph.dot -ograph.png -Tpng'
            if runner.can_run(command):
                logger.info('Rendering dot file to png file.')
                runner.check_run(command)
                if open:
                    runner.run('open graph.png')
            else:
                logging.warning('graphviz not installed. Cannot convert graph to a png.')

@punic_cli.command(name ='copy-frameworks')
@click.pass_context
def copy_frameworks(context):
    """In a Run Script build phase, copies each framework specified by a SCRIPT_INPUT_FILE environment variable into the built app bundle."""
    copy_frameworks_main()

# noinspection PyUnusedLocal
@punic_cli.command()
@click.pass_context
def version(context):
    """Display the current version of Carthage."""
    logger.info('Punic version: {}'.format(punic.__version__), prefix = False)

    sys_version = sys.version_info
    sys_version = SemanticVersion.from_dict(dict(
        major = sys_version.major,
        minor = sys_version.minor,
        micro = sys_version.micro,
        releaselevel = sys_version.releaselevel,
        serial = sys_version.serial,
    ))

    logger.info('Python version: {}'.format(sys_version), prefix=False)
    version_check(verbose = True, timeout = None, failure_is_an_option=False)

@punic_cli.command()
@click.pass_context
@click.option(
    '--configuration', default=None,
    help="""Dependency configurations to build. Usually 'Release' or 'Debug'.""")
@click.option(
    '--platform', default=None,
    help="""Platform to build. Comma separated list.""")
@click.option(
    '--xcode', default=None)
def init(context, **kwargs):
    """Generate punic configuration file."""

    config_init(**kwargs)

def main():
    punic_cli()
<commit_msg>Added "home" command.<commit_after>from __future__ import division, absolute_import, print_function

__all__ = ['punic_cli', 'main']

import logging
import os
import punic.shshutil as shutil
import sys
import click
from click_didyoumean import DYMGroup
import networkx as nx
import punic
from .copy_frameworks import *
from .errors import *
from .logger import *
from .model import *
from .runner import *
from .semantic_version import *
from .utilities import *
from .version_check import *
from .config_init import *

@click.group(cls=DYMGroup)
@click.option('--echo', default=False, is_flag=True, help="""Echo all commands to terminal.""")
@click.option('--verbose', default=False, is_flag=True, help="""Verbose logging.""")
@click.option('--color/--no-color', default=True, is_flag=True, help="""TECHNICOLOR.""")
@click.option('--timing/--no-timing', default=False, is_flag=True, help="""Log timing info""")
@click.pass_context
def punic_cli(context, echo, verbose, timing, color):

    # Configure click
    context.token_normalize_func = lambda x:x if not x else x.lower()

    # Configure logging
    level = logging.DEBUG if verbose else logging.INFO
    logging.basicConfig(format='%(message)s', level=level)
    runner.echo = echo
    requests_log = logging.getLogger("requests.packages.urllib3")
    requests_log.setLevel(logging.WARNING)
    requests_log.propagate = True
    logger.color = color

    # Set up punic
    punic = Punic()
    punic.config.log_timings = timing
    context.obj = punic

@punic_cli.command()
@click.pass_context
def fetch(context):
    """Fetch the project's dependencies.."""
    logger.info("<cmd>fetch</cmd>")
    punic = context.obj
    punic.config.can_fetch = True  # obviously

    with timeit('fetch', log = punic.config.log_timings):
        with error_handling():
            punic.fetch()

@punic_cli.command()
@click.pass_context
@click.option('--fetch/--no-fetch', default=True, is_flag=True, help="""Controls whether to fetch dependencies.""")
def resolve(context, fetch):
    """Resolve dependencies and output `Carthage.resolved` file.

    This sub-command does not build dependencies. Use this sub-command when a dependency has changed and you just want to update `Cartfile.resolved`.
    """
    punic = context.obj
    logger.info("<cmd>Resolve</cmd>")
    punic.config.can_fetch = fetch

    with timeit('resolve', log = punic.config.log_timings):
        with error_handling():
            punic.resolve()

@punic_cli.command()
@click.pass_context
@click.option('--configuration', default=None,
    help="""Dependency configurations to build. Usually 'Release' or 'Debug'.""")
@click.option('--platform', default=None, help="""Platform to build. Comma separated list.""")
@click.option('--fetch/--no-fetch', default=True, is_flag=True, help="""Controls whether to fetch dependencies.""")
@click.option('--xcode-version', default=None, help="""Xcode version to use""")
@click.argument('deps', nargs=-1)
def build(context, configuration, platform, fetch, xcode_version, deps):
    """Fetch and build the project's dependencies."""
    logger.info("<cmd>Build</cmd>")
    punic = context.obj

    punic.config.update(configuration=configuration, platform=platform)
    punic.config.can_fetch = fetch
    if xcode_version:
        punic.config.xcode_version = xcode_version

    with timeit('build', log = punic.config.log_timings):
        with error_handling():
            punic.build(dependencies=deps)

@punic_cli.command()
@click.pass_context
@click.option('--configuration', default=None,
    help="""Dependency configurations to build. Usually 'Release' or 'Debug'.""")
@click.option('--platform', default=None, help="""Platform to build. Comma separated list.""")
@click.option('--fetch/--no-fetch', default=True, is_flag=True, help="""Controls whether to fetch dependencies.""")
@click.option('--xcode-version', default=None, help="""Xcode version to use""")
@click.argument('deps', nargs=-1)
def update(context, configuration, platform, fetch, xcode_version, deps):
    """Update and rebuild the project's dependencies."""
    logger.info("<cmd>Update</cmd>")
    punic = context.obj
    punic.config.update(configuration=configuration, platform=platform)
    punic.config.can_fetch = fetch
    if xcode_version:
        punic.config.xcode_version = xcode_version

    with timeit('update', log = punic.config.log_timings):
        with error_handling():
            punic.resolve()
            punic.build(dependencies=deps)

@punic_cli.command()
@click.pass_context
@click.option('--derived-data', default=False, is_flag=True, help="""Clean the punic derived data directory.""")
@click.option('--caches', default=False, is_flag=True, help="""Clean the global punic carthage files.""")
@click.option('--all', default=False, is_flag=True, help="""Clean all.""")
def clean(context, derived_data, caches, all):
    """Clean project & punic environment."""
    logger.info("<cmd>Clean</cmd>")
    punic = context.obj

    if derived_data or all:
        logger.info('Erasing derived data directory')
        if punic.config.derived_data_path.exists():
            shutil.rmtree(punic.config.derived_data_path)

    if caches or all:
        if punic.config.repo_cache_directory.exists():
            logger.info('Erasing {}'.format(punic.config.repo_cache_directory))
            shutil.rmtree(punic.config.repo_cache_directory )
        logger.info('Erasing run cache')
        runner.reset()

@punic_cli.command()
@click.pass_context
@click.option('--fetch/--no-fetch', default=True, is_flag=True, help="""Controls whether to fetch dependencies.""")
@click.option('--open', default=False, is_flag=True, help="""Open the graph image file.""")
def graph(context, fetch, open):
    """Output resolved dependency graph."""
    logger.info("<cmd>Graph</cmd>")
    punic = context.obj
    punic.config.can_fetch = fetch

    with timeit('graph', log = punic.config.log_timings):
        with error_handling():

            graph = punic.graph()

            logger.info('Writing graph file to "{}".'.format(os.getcwd()))
            nx.drawing.nx_pydot.write_dot(graph, 'graph.dot')

            command = 'dot graph.dot -ograph.png -Tpng'
            if runner.can_run(command):
                logger.info('Rendering dot file to png file.')
                runner.check_run(command)
                if open:
                    click.launch('graph.png')
            else:
                logging.warning('graphviz not installed. Cannot convert graph to a png.')

@punic_cli.command(name ='copy-frameworks')
@click.pass_context
def copy_frameworks(context):
    """In a Run Script build phase, copies each framework specified by a SCRIPT_INPUT_FILE environment variable into the built app bundle."""
    copy_frameworks_main()

# noinspection PyUnusedLocal
@punic_cli.command()
@click.pass_context
def version(context):
    """Display the current version of Carthage."""
    logger.info('Punic version: {}'.format(punic.__version__), prefix = False)

    sys_version = sys.version_info
    sys_version = SemanticVersion.from_dict(dict(
        major = sys_version.major,
        minor = sys_version.minor,
        micro = sys_version.micro,
        releaselevel = sys_version.releaselevel,
        serial = sys_version.serial,
    ))

    logger.info('Python version: {}'.format(sys_version), prefix=False)
    version_check(verbose = True, timeout = None, failure_is_an_option=False)

@punic_cli.command()
@click.pass_context
@click.option(
    '--configuration', default=None,
    help="""Dependency configurations to build. Usually 'Release' or 'Debug'.""")
@click.option(
    '--platform', default=None,
    help="""Platform to build. Comma separated list.""")
@click.option(
    '--xcode', default=None)
def init(context, **kwargs):
    """Generate punic configuration file."""

    config_init(**kwargs)

@punic_cli.command()
@click.pass_context
def home(context):
    click.launch('https://github.com/schwa/punic')

def main():
    punic_cli()
<|endoftext|>


<commit_before>from mongoengine import *

__all__ = ['DynamicFields', 'has_dfields']

def has_dfields(cls):
    cls._dfields = DynamicFields._dfields(cls.__name__)
    return cls

# Create your models here.
class DynamicFields(Document):
    refer = StringField(max_length=120, required=True)
    name = StringField(max_length=120, required=True)
    typo = StringField(required=True)
    max_length = IntField()
    min_value = IntField()
    max_value = IntField()
    required = BooleanField(default=False)
    choices = ListField(required=False)

    @classmethod
    def _dfields(cls, refer):
        dynamic_fields = cls.objects.filter(refer = refer)
        ddynamic_fields = {}
        for df in dynamic_fields:
            ddynamic_fields[df.name] = eval(df.typo)()
            ddynamic_fields[df.name].name = df.name
            ddynamic_fields[df.name].max_length = df.max_length
            ddynamic_fields[df.name].min_value = df.min_value
            ddynamic_fields[df.name].max_value = df.max_value
            ddynamic_fields[df.name].required = df.required
            ddynamic_fields[df.name].choices = df.choices
        return ddynamic_fields

    def __unicode__(self):
        return u"[%s] %s: %s" % (self.refer, self.typo, self.name)<commit_msg>Lazy get dynamic fields<commit_after>from mongoengine import *

__all__ = ['DynamicFields', 'has_dfields']

def has_dfields(cls):
    cls._dfields = DynamicFields._dfields(cls.__name__)
    return cls

# Create your models here.
class DynamicFields(Document):
    refer = StringField(max_length=120, required=True)
    name = StringField(max_length=120, required=True)
    typo = StringField(required=True)
    max_length = IntField()
    min_value = IntField()
    max_value = IntField()
    required = BooleanField(default=False)
    choices = ListField(required=False)

    @classmethod
    def _dfields(cls, refer):
        def _call(*args):
            dynamic_fields = cls.objects.filter(refer = refer)
            ddynamic_fields = {}
            for df in dynamic_fields:
                ddynamic_fields[df.name] = eval(df.typo)()
                ddynamic_fields[df.name].name = df.name
                ddynamic_fields[df.name].max_length = df.max_length
                ddynamic_fields[df.name].min_value = df.min_value
                ddynamic_fields[df.name].max_value = df.max_value
                ddynamic_fields[df.name].required = df.required
                ddynamic_fields[df.name].choices = df.choices
            return ddynamic_fields
        return _call

    def __unicode__(self):
        return u"[%s] %s: %s" % (self.refer, self.typo, self.name)
<|endoftext|>


<commit_before>from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
from bson.json_util import default, object_hook
from django.utils.encoding import smart_unicode
from models import Friend
import json
import time as _time
from datetime import datetime
from django.contrib.auth.models import User
import logging

logger = logging.getLogger(__name__)

def recommend(request):
	recommend_friends = []
	friends = User.objects.all()
	for friend in friends:
		if(friend.username == "root"):
			continue
		logger.debug("friend is : %s" %friend.username)
		recommend = {'friends': friend.username}
		recommend_friends.append(recommend)
	# scrapy today news from web
	return HttpResponse(toJSON(recommend_friends))

def list_contains_record(record_list, record):
	if (record is None):
		return False

	record_id = str(record.id)
	for next in record_list:
		if ((next != None) and (next['sid'] == record_id)):
			return True
	return False

def safe_attr(obj, attr_name):
	if attr_name in obj:
		return obj[attr_name]
	return None

def process_client_changes(request_url, username, friends_buffer, updated_friends):
	logger.debug('* Processing client changes')
	base_url = request_url

	# build an array of generic objects containing contact data,
	# using the Django built-in JSON parser
	logger.debug('Uploaded friends buffer: ' + smart_unicode(friends_buffer))
	json_list = json.loads(friends_buffer, object_hook=object_hook)
	logger.debug('Client-side updates: ' + str(len(json_list)))

	# keep track of the number of new records the client sent to us,
	# so that we can log it below
	new_record_count = 0

	for jrecord in json_list:
		logger.debug('json record ' + str(jrecord))
		new_record = False
		sid = safe_attr(jrecord, 'sid')
		if(sid != None):
			logger.debug('Updating record: ' + str(sid))
			record = Friend.objects.get(id=sid)
		else:
			logger.debug('creating new friend record')
			new_record = True
			# todo : need pass user name to handle
			record = Friend(username=username)

		# if the 'change' for this record is that they were deleted
		# on the client-side, all we want to do is set the deleted
		# flag here, and we're done.
		if(safe_attr(jrecord,'d') == True):
			record.deleted = True
			record.save()
			logger.debug('Deleted record: '+record.handle)
			continue

		record.handle = safe_attr(jrecord, 'h')
		record.username = safe_attr(jrecord, 'u')
		record.phone_mobile = safe_attr(jrecord, 'p')

		record.deleted = (safe_attr(jrecord, 'd') == 'true')
		if(new_record):
			# new record - add them to db ...
			new_record_count = new_record_count + 1
			#record.handle = 'temp'
			logger.debug('Created new record username: '+ record.username)
		record.save()
		logger.debug('Saved username record: '+record.username)

		# we don't save off the client_id value (thus we add it after
		# the "save"), but we want it to be in the JSON object we
		# serialize out, so that the client can match this contact
		# up with the client version
		client_id = safe_attr(jrecord, 'cid')

		# create a high-water-mark for sync-state from the 'updated' time
		# for this record, so we return the corrent value to the client.
		high_water = str(long(_time.mktime(record.updated.utctimetuple())) + 1)

		# add new records to our updated_friends, so that we return them
		# to the client (so the client gets the serverId for the
		# added record)
		if (new_record):
			UpdatedRecordData(updated_friends, record.username, client_id,
				base_url, high_water)

	logger.debug('Client-side adds: '+str(new_record_count))

def get_updated_friends(request_url, username, client_state, updated_friends):
	logger.debug('* Processing server changes')
	timestamp = None

	base_url = request_url

	# the client sends the last high-water-mark that they sucessfully
	# sync'd to in the syncstate parameter. it's opaque to them, but
	# its actually a seconds-in-unix-epoch timestamp that we use
	# as a baseline.
	if client_state:
		logger.debug('Client sync state: '+client_state)
		timestamp = datetime.utcformattimestamp(float(client_state))

	# keep track of the update/delete counts, so we can log in
	# below. Makes debugging easier...
	update_count = 0
	delete_count = 0

	records = Friend.objects.filter(username=username)
	if records:
		# find the high-water mark for the most recently updated record.
		# we'll return this as the syncstate (x) value for all the friends
		# we return from this function.
		high_water_date = datetime.min
		for record in records:
			result = record.updated.replace(microsecond=0, tzinfo=None)
			logger.debug("record updated: "+str(result))
			logger.debug("high water date: "+str(high_water_date))
			if (result > high_water_date):
				high_water_date = result
		high_water_mark = str(long(_time.mktime(high_water_date.utctimetuple())) + 1)
		logger.debug('New sync state: '+high_water_mark)

		# Now build the updated_friends containing all the friends that have been
		# changed since the last sync
		for record in records:
			# if our list of records we're returning already contains this
			# record (for example, it's a record just uploaded from the client)
			# then don't bother processing it any further...
			if (list_contains_record(updated_friends, record)):
				continue

			username = record.username
			logger.debug("record updated: "+str(record.updated))
			logger.debug("timestamp: "+str(timestamp))
			if timestamp is None or record.updated > timestamp:
				if record.deleted == True:
					delete_count = delete_count + 1
					DeletedRecordData(updated_friends, username, high_water_mark)
				else:
					update_count = update_count + 1
					UpdatedRecordData(updated_friends, handle, None, base_url, high_water_mark)

	logger.debug('Server-side updates: '+str(update_count))
	logger.debug('Server-side deletes: '+str(delete_count))

def sync(request):

	username = request.POST.get('username')
	# upload client dirty friends
	updated_friends = []
	if request.method == 'POST':
		logger.debug("request POST: "+str(request.POST))
	else:
		logger.debug("request GET: "+str(request.GET))
	client_buffer = request.POST.get('friends')
	request_url = request.POST.get('host_url')

	if((client_buffer != None) and (client_buffer != '')):
		process_client_changes(request_url, username, client_buffer, updated_friends)

	# add any friends on the server-side
	client_state = request.POST.get('syncstate')
	get_updated_friends(request_url, username, client_state, updated_friends)

	logger.debug("update friends are : "+toJSON(updated_friends))
	# update latest friends
	return HttpResponse(toJSON(updated_friends))

def toJSON(object):
	"""Dumps the data represented by the object to JSON for wire transfer."""
	return json.dumps(object, default=default)

class UpdatedRecordData(object):
	"""Holds data for user's records.

	This class knows how to serialize itself to JSON.
	"""
	__FIELD_MAP = {
		'handle': 'h',
		'username': 'u',
		'phone_mobile': 'p',
		'client_id': 'cid'
	}

	def __init__(self, record_list, username, client_id, host_url, high_water_mark):
		obj = Friend.objects.get(username=username)

		record = {}
		for obj_name, json_name in self.__FIELD_MAP.items():
			if hasattr(obj, obj_name):
				v = getattr(obj, obj_name)
				if (v != None):
					record[json_name] = smart_unicode(v)
				else:
					record[json_name] = None

		record['sid'] = str(obj.id)
		record['x'] = high_water_mark
		logger.debug("mark client id: "+str(client_id))
		if (client_id != None):
			record['cid'] = client_id
		record_list.append(record)

class DeletedRecordData(object):
	def __init__(self, record_list, username, high_water_mark):
		obj = Friend.objects.get(username=username)
		record = {}
		record['d'] = 'true'
		record['sid'] = obj.id
		record['x'] = high_water_mark
		record_list.append(record)
<commit_msg>update<commit_after>from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
from bson.json_util import default, object_hook
from django.utils.encoding import smart_unicode
from models import Friend
import json
import time as _time
from datetime import datetime
from django.contrib.auth.models import User
import logging

logger = logging.getLogger(__name__)

def recommend(request):
	recommend_friends = []
	friends = User.objects.all()
	for friend in friends:
		if(friend.username == "root"):
			continue
		logger.debug("friend is : %s" %friend.username)
		recommend = {'friends': friend.username}
		recommend_friends.append(recommend)
	# scrapy today news from web
	return HttpResponse(toJSON(recommend_friends))

def list_contains_record(record_list, record):
	if (record is None):
		return False

	record_id = str(record.id)
	for next in record_list:
		if ((next != None) and (next['sid'] == record_id)):
			return True
	return False

def safe_attr(obj, attr_name):
	if attr_name in obj:
		return obj[attr_name]
	return None

def process_client_changes(request_url, username, friends_buffer, updated_friends):
	logger.debug('* Processing client changes')
	base_url = request_url

	# build an array of generic objects containing contact data,
	# using the Django built-in JSON parser
	logger.debug('Uploaded friends buffer: ' + smart_unicode(friends_buffer))
	json_list = json.loads(friends_buffer, object_hook=object_hook)
	logger.debug('Client-side updates: ' + str(len(json_list)))

	# keep track of the number of new records the client sent to us,
	# so that we can log it below
	new_record_count = 0

	for jrecord in json_list:
		logger.debug('json record ' + str(jrecord))
		new_record = False
		sid = safe_attr(jrecord, 'sid')
		if(sid != None):
			logger.debug('Updating record: ' + str(sid))
			record = Friend.objects.get(id=sid)
		else:
			logger.debug('creating new friend record')
			new_record = True
			# todo : need pass user name to handle
			record = Friend(username=username)

		# if the 'change' for this record is that they were deleted
		# on the client-side, all we want to do is set the deleted
		# flag here, and we're done.
		if(safe_attr(jrecord,'d') == True):
			record.deleted = True
			record.save()
			logger.debug('Deleted record: '+record.handle)
			continue

		record.handle = safe_attr(jrecord, 'h')
		record.username = safe_attr(jrecord, 'u')
		record.phone_mobile = safe_attr(jrecord, 'p')

		record.deleted = (safe_attr(jrecord, 'd') == 'true')
		if(new_record):
			# new record - add them to db ...
			new_record_count = new_record_count + 1
			#record.handle = 'temp'
			logger.debug('Created new record username: '+ record.username)
		record.save()
		logger.debug('Saved username record: '+record.username)

		# we don't save off the client_id value (thus we add it after
		# the "save"), but we want it to be in the JSON object we
		# serialize out, so that the client can match this contact
		# up with the client version
		client_id = safe_attr(jrecord, 'cid')

		# create a high-water-mark for sync-state from the 'updated' time
		# for this record, so we return the corrent value to the client.
		high_water = str(long(_time.mktime(record.updated.utctimetuple())) + 1)

		# add new records to our updated_friends, so that we return them
		# to the client (so the client gets the serverId for the
		# added record)
		if (new_record):
			UpdatedRecordData(updated_friends, record.username, client_id,
				base_url, high_water)

	logger.debug('Client-side adds: '+str(new_record_count))

def get_updated_friends(request_url, username, client_state, updated_friends):
	logger.debug('* Processing server changes')
	timestamp = None

	base_url = request_url

	# the client sends the last high-water-mark that they sucessfully
	# sync'd to in the syncstate parameter. it's opaque to them, but
	# its actually a seconds-in-unix-epoch timestamp that we use
	# as a baseline.
	if client_state:
		logger.debug('Client sync state: '+client_state)
		timestamp = datetime.utcformattimestamp(float(client_state))

	# keep track of the update/delete counts, so we can log in
	# below. Makes debugging easier...
	update_count = 0
	delete_count = 0

	records = Friend.objects.filter(username=username)
	if records:
		# find the high-water mark for the most recently updated record.
		# we'll return this as the syncstate (x) value for all the friends
		# we return from this function.
		high_water_date = datetime.min
		for record in records:
			result = record.updated.replace(microsecond=0, tzinfo=None)
			logger.debug("record updated: "+str(result))
			logger.debug("high water date: "+str(high_water_date))
			if (result > high_water_date):
				high_water_date = result
		high_water_mark = str(long(_time.mktime(high_water_date.utctimetuple())) + 1)
		logger.debug('New sync state: '+high_water_mark)

		# Now build the updated_friends containing all the friends that have been
		# changed since the last sync
		for record in records:
			# if our list of records we're returning already contains this
			# record (for example, it's a record just uploaded from the client)
			# then don't bother processing it any further...
			if (list_contains_record(updated_friends, record)):
				continue

			username = record.username
			logger.debug("record updated: "+str(record.updated))
			logger.debug("timestamp: "+str(timestamp))
			if timestamp is None or record.updated > timestamp:
				if record.deleted == True:
					delete_count = delete_count + 1
					DeletedRecordData(updated_friends, username, high_water_mark)
				else:
					update_count = update_count + 1
					UpdatedRecordData(updated_friends, username, None, base_url, high_water_mark)

	logger.debug('Server-side updates: '+str(update_count))
	logger.debug('Server-side deletes: '+str(delete_count))

def sync(request):

	username = request.POST.get('username')
	# upload client dirty friends
	updated_friends = []
	if request.method == 'POST':
		logger.debug("request POST: "+str(request.POST))
	else:
		logger.debug("request GET: "+str(request.GET))
	client_buffer = request.POST.get('friends')
	request_url = request.POST.get('host_url')

	if((client_buffer != None) and (client_buffer != '')):
		process_client_changes(request_url, username, client_buffer, updated_friends)

	# add any friends on the server-side
	client_state = request.POST.get('syncstate')
	get_updated_friends(request_url, username, client_state, updated_friends)

	logger.debug("update friends are : "+toJSON(updated_friends))
	# update latest friends
	return HttpResponse(toJSON(updated_friends))

def toJSON(object):
	"""Dumps the data represented by the object to JSON for wire transfer."""
	return json.dumps(object, default=default)

class UpdatedRecordData(object):
	"""Holds data for user's records.

	This class knows how to serialize itself to JSON.
	"""
	__FIELD_MAP = {
		'handle': 'h',
		'username': 'u',
		'phone_mobile': 'p',
		'client_id': 'cid'
	}

	def __init__(self, record_list, username, client_id, host_url, high_water_mark):
		obj = Friend.objects.get(username=username)

		record = {}
		for obj_name, json_name in self.__FIELD_MAP.items():
			if hasattr(obj, obj_name):
				v = getattr(obj, obj_name)
				if (v != None):
					record[json_name] = smart_unicode(v)
				else:
					record[json_name] = None

		record['sid'] = str(obj.id)
		record['x'] = high_water_mark
		logger.debug("mark client id: "+str(client_id))
		if (client_id != None):
			record['cid'] = client_id
		record_list.append(record)

class DeletedRecordData(object):
	def __init__(self, record_list, username, high_water_mark):
		obj = Friend.objects.get(username=username)
		record = {}
		record['d'] = 'true'
		record['sid'] = obj.id
		record['x'] = high_water_mark
		record_list.append(record)
<|endoftext|>