Example #1
0
class UserCollection(UserRelation):

    instantiable = True
    groups_order = UserMember.groups_order
    member_class = schema.Collection
    edit_controls = [
        "cocktail.html.TextArea", "cocktail.html.CheckList",
        "cocktail.html.MultipleChoiceSelector"
    ]
    search_controls = [
        "cocktail.html.DropdownSelector", "cocktail.html.RadioSelector",
        "woost.views.ItemSelector", "cocktail.html.CheckList",
        "cocktail.html.MultipleChoiceSelector"
    ]

    member_items = schema.Reference(type=UserMember,
                                    required=True,
                                    bidirectional=True,
                                    related_key="parent_collection",
                                    integral=True,
                                    member_group="constraints")

    member_min = schema.Integer(listed_by_default=False,
                                member_group="constraints")

    member_max = schema.Integer(min=member_min,
                                listed_by_default=False,
                                member_group="constraints")
Example #2
0
class IFrameBlock(Block):

    instantiable = True
    type_group = "blocks.custom"
    view_class = "cocktail.html.Element"

    members_order = ["src", "width", "height"]

    src = schema.URL(required=True, member_group="content")

    width = schema.Integer(min=0, member_group="content")

    height = schema.Integer(min=0, member_group="content")

    def init_view(self, view):
        Block.init_view(self, view)
        view.tag = "iframe"
        view["src"] = self.src
        view["frameborder"] = "0"

        if self.width:
            view["width"] = self.width

        if self.height:
            view["height"] = self.height
Example #3
0
class ImageFileRenderer(Renderer):
    """A content renderer that handles image files."""

    instantiable = True

    max_size = schema.Tuple(items=(schema.Integer(required=True, min=1),
                                   schema.Integer(required=True, min=1)),
                            request_value_separator="x")

    def can_render(self, item, **parameters):
        return (isinstance(item, File) and item.resource_type == "image"
                and item.mime_type in formats_by_mime_type
                and (self.max_size is None or self.validate_size(item)))

    def validate_size(self, file):
        try:
            width, height = get_image_size(file.file_path)
        except IOError:
            return False
        else:
            max_size = self.max_size
            return (width <= max_size[0] and height <= max_size[1]) \
                or (width <= max_size[1] and height <= max_size[0])

    def render(self, item, **parameters):
        return item.file_path
Example #4
0
class UserString(UserMember):

    instantiable = True
    groups_order = UserMember.groups_order
    member_class = schema.String
    edit_controls = [
        "cocktail.html.TextBox", "cocktail.html.PasswordBox",
        "cocktail.html.TextArea", "woost.views.RichTextEditor"
    ]
    search_controls = ["cocktail.html.TextBox"]

    member_min = schema.Integer(listed_by_default=False,
                                member_group="constraints")

    member_max = schema.Integer(min=member_min,
                                listed_by_default=False,
                                member_group="constraints")

    member_format = schema.String(listed_by_default=False,
                                  text_search=False,
                                  member_group="constraints")

    member_text_search = schema.Boolean(required=True,
                                        default=True,
                                        listed_by_default=False,
                                        member_group="behavior")

    member_normalized_index = schema.Boolean(required=True,
                                             default=True,
                                             listed_by_default=False,
                                             member_group="definition")
Example #5
0
class UserInteger(UserMember):

    instantiable = True
    groups_order = UserMember.groups_order
    member_class = schema.Integer

    member_min = schema.Integer(listed_by_default=False,
                                member_group="constraints")

    member_max = schema.Integer(min=member_min,
                                listed_by_default=False,
                                member_group="constraints")
Example #6
0
class HTMLRenderer(Renderer):
    """A content renderer that handles XHTML/HTML pages."""

    instantiable = True

    mime_types = set(["text/html", "text/xhtml", "application/xhtml"])

    command = schema.String(
        required=True,
        default="python -m woost.models.rendering.renderurl "
        "%(source)s %(dest)s")

    window_width = schema.Integer(min=0)

    window_height = schema.Integer(min=0)

    def can_render(self, item, **parameters):
        return (isinstance(item, Publishable)
                and item.mime_type in self.mime_types and item.is_accessible(
                    user=User.get_instance(qname="woost.anonymous_user")))

    def render(self,
               item,
               window_width=None,
               window_height=None,
               **parameters):
        temp_path = mkdtemp()

        try:
            temp_image_file = os.path.join(temp_path, "thumbnail.png")

            command = self.command % {
                "source": item.get_uri(host="."),
                "dest": temp_image_file
            }

            if window_width is None:
                window_width = self.window_width

            if window_width is not None:
                command += " --min-width %d" % window_width

            if window_height is None:
                window_height = self.window_height

            if window_height is not None:
                command += " --min-width %d" % window_height

            Popen(command, shell=True).wait()
            return Image.open(temp_image_file)

        finally:
            rmtree(temp_path)
Example #7
0
class VideoPlayerSettings(Item):

    instantiable = True
    visible_from_root = False
    player_initialization = TypeMapping()

    members_order = [
        "title", "width", "height", "autoplay", "show_player_controls"
    ]

    title = schema.String(
        listed_by_default = False,
        required = True,
        unique = True,
        indexed = True,
        normalized_index = True,
        full_text_indexed = True,
        descriptive = True,
        translated = True
    )

    width = schema.Integer(
        required = True,
        default = 480,
        listed_by_default = False
    )

    height = schema.Integer(
        required = True,
        default = 385,
        listed_by_default = False
    )

    autoplay = schema.Boolean(
        required = True,
        default = False,
        listed_by_default = False
    )

    show_player_controls = schema.Boolean(
        required = True,
        default = True,
        listed_by_default = False
    )

    def create_player(self, video):
        player = templates.new(video.video_player)
        player_initialization = self.player_initialization.get(video.__class__)
        if player_initialization:
            player_initialization(player, self, video)
        return player
class TwitterTimelineBlock(Block):

    instantiable = True
    type_group = "blocks.social"
    view_class = "cocktail.html.TwitterTimeline"

    members_order = [
        "widget_id",
        "theme",
        "link_color",
        "width",
        "height",
        "related_accounts"
    ]

    widget_id = schema.String(
        required = True,
        member_group = "content"
    )

    theme = schema.String(
        required = True,
        default = "light",
        enumeration = ("light", "dark"),
        member_group = "appearence"
    )

    link_color = schema.Color(
        member_group = "appearence"
    )

    width = schema.Integer(
        member_group = "appearence"
    )

    height = schema.Integer(
        member_group = "appearence"
    )

    related_accounts = schema.String(
        member_group = "tweet"
    )

    def init_view(self, view):
        Block.init_view(self, view)
        view.widget_id = self.widget_id
        view.theme = self.theme
        view.link_color = self.link_color
        view.width = self.width
        view.height = self.height
        view.related = self.related_accounts
Example #9
0
class UserDateTime(UserMember):

    instantiable = True
    groups_order = UserMember.groups_order
    member_class = schema.DateTime
    edit_controls = ["cocktail.html.TextBox", "cocktail.html.DatePicker"]
    search_controls = ["cocktail.html.TextBox", "cocktail.html.DatePicker"]

    member_min = schema.Integer(listed_by_default=False,
                                member_group="constraints")

    member_max = schema.Integer(min=member_min,
                                listed_by_default=False,
                                member_group="constraints")
Example #10
0
class IconRenderer(Renderer):

    instantiable = True

    members_order = ["icon_size", "icon_resolver_expression"]

    icon_size = schema.Integer(required=True,
                               enumeration=[16, 32],
                               edit_control="cocktail.html.RadioSelector")

    icon_resolver_expression = schema.String()

    def can_render(self, item, **parameters):
        return True

    def render(self, item, **parameters):
        return self.icon_resolver.find_icon_path(item, self.icon_size)

    @property
    def icon_resolver(self):
        try:
            return self._v_icon_resolver
        except AttributeError:
            expr = self.icon_resolver_expression
            icon_resolver = resolve(expr) if expr else app.icon_resolver
            self._v_icon_resolver = icon_resolver
            return icon_resolver

    @event_handler
    def handle_changed(cls, e):
        if e.member is cls.icon_resolver_expression:
            e.source._v_icon_resolver = None
Example #11
0
    def __init__(self, *args, **kwargs):

        schema.Schema.__init__(self, *args, **kwargs)

        file_name_kw = {}
        file_size_kw = {"min": 0}
        mime_type_kw = {}

        file_name_properties = kwargs.get("file_name_properties")
        if file_name_properties:
            file_name_kw.update(file_name_properties)

        file_size_properties = kwargs.get("file_size_properties")
        if file_size_properties:
            file_size_kw.update(file_size_properties)

        file_size_kw.setdefault(
            "translate_value",
            lambda value, language=None, **kwargs: format_bytes(value)
            if value or value == 0 else "")

        mime_type_properties = kwargs.get("mime_type_properties")
        if mime_type_properties:
            mime_type_kw.update(mime_type_properties)

        self.add_member(schema.String("file_name", **file_name_kw))
        self.add_member(schema.Integer("file_size", **file_size_kw))
        self.add_member(schema.String("mime_type", **mime_type_kw))
Example #12
0
class MenuBlock(Block):

    instantiable = True
    view_class = "woost.views.Menu"

    root = schema.Reference(type=Document,
                            related_end=schema.Collection(),
                            member_group="content")

    root_visible = schema.Boolean(required=True,
                                  default=False,
                                  member_group="content")

    max_depth = schema.Integer(member_group="content")

    expanded = schema.Boolean(required=True,
                              default=False,
                              member_group="content")

    def init_view(self, view):
        Block.init_view(self, view)
        view.root = self.root
        view.root_visible = self.root_visible
        view.max_depth = self.max_depth
        view.expanded = self.expanded
Example #13
0
 def expanded_items(self):
     if self.params.read(schema.String("expanded")) == "all":
         return "all"
     else:
         return self.params.read(
             schema.Collection("expanded",
                               type=set,
                               items=schema.Integer(),
                               default=set()))
Example #14
0
class IssuuBlock(Block):

    instantiable = True
    view_class = "woost.extensions.issuu.IssuuBlockView"
    block_display = "woost.extensions.issuu.IssuuBlockDisplay"

    members_order = ["element_type", "issuu_document", "width", "height"]

    element_type = ElementType(member_group="content")

    issuu_document = schema.Reference(type=IssuuDocument,
                                      required=True,
                                      related_end=schema.Collection(),
                                      listed_by_default=False,
                                      member_group="content")

    width = schema.Integer(listed_by_default=False, member_group="content")

    height = schema.Integer(listed_by_default=False, member_group="content")
Example #15
0
class Shadow(ImageEffect):

    instantiable = True

    offset = schema.Integer(required=True, default=5)

    padding = schema.Integer(required=True, default=8)

    color = schema.Color(required=True, default="#444444")

    iterations = 3

    def apply(self, image):

        # Create the backdrop image -- a box in the background colour with a
        # shadow on it.
        total_width = image.size[0] + abs(self.offset) + 2 * self.padding
        total_height = image.size[1] + abs(self.offset) + 2 * self.padding
        back = Image.new("RGBA", (total_width, total_height))

        # Place the shadow, taking into account the offset from the image
        shadow_left = self.padding + max(self.offset, 0)
        shadow_top = self.padding + max(self.offset, 0)
        color = resolve_color(self.color)
        back.paste(self.color, [
            shadow_left, shadow_top, shadow_left + image.size[0],
            shadow_top + image.size[1]
        ])

        # Apply the filter to blur the edges of the shadow.  Since a small
        # kernel is used, the filter must be applied repeatedly to get a
        # decent blur.
        for n in range(self.iterations):
            back = back.filter(ImageFilter.BLUR)

        # Paste the input image onto the shadow backdrop
        image_left = self.padding - min(self.offset, 0)
        image_top = self.padding - min(self.offset, 0)
        back.paste(image, (image_left, image_top),
                   image if image.mode in ("1", "L", "RGBA") else None)

        return back
Example #16
0
class Rotate(ImageEffect):

    instantiable = True

    angle = schema.Integer(required=True)

    filter = Image.BICUBIC

    def apply(self, image):
        if image.mode != "RGBA":
            image = image.convert("RGBA")
        return image.rotate(self.angle, self.filter, True)
Example #17
0
class PDFRenderer(Renderer):
    """A content renderer that handles pdf files."""

    instantiable = True

    command = schema.String(required=True)

    timeout = schema.Integer(required=True, default=20)

    timeout_size_factor = schema.Float(default=10.0)

    def can_render(self, item, **parameters):
        return (self.command and isinstance(item, File)
                and item.resource_type == "document"
                and item.file_name.split(".")[-1].lower() == "pdf")

    def render(self, item, page=1, **parameters):

        timeout = self.timeout

        # Increase the timeout for bigger files
        if self.timeout_size_factor:
            size = item.file_size
            if size:
                timeout += size / (self.timeout_size_factor * 1024 * 1024)

        RESOLUTION = 0.25
        temp_path = mkdtemp()

        try:
            temp_image_file = os.path.join(temp_path, "thumbnail.png")

            command = self.command % {
                "source": item.file_path,
                "dest": temp_image_file,
                "page": page
            }

            p = Popen(command, shell=True, stdout=PIPE)
            start = time()

            while p.poll() is None:
                if time() - start > timeout:
                    p.terminate()
                    raise IOError("PDF rendering timeout: '%s' took more than "
                                  "%.2f seconds" % (command, timeout))
                sleep(RESOLUTION)

            return Image.open(temp_image_file)

        finally:
            rmtree(temp_path)
Example #18
0
class Frame(ImageEffect):

    instantiable = True

    members_order = [
        "edge_width", "edge_color", "vertical_padding", "horizontal_padding",
        "background"
    ]

    edge_width = schema.Integer(required=True, min=1, default=1)

    edge_color = schema.Color(required=True, default="#000000")

    vertical_padding = ImageSize(required=True, default="0")

    horizontal_padding = ImageSize(required=True, default="0")

    background = schema.Color(required=True, default="#000000")

    def apply(self, image):

        edge_color = resolve_color(self.edge_color)
        background = resolve_color(self.background)

        # Create the canvas
        width, height = image.size
        vertical_padding = ImageSize.resolve_size(self.vertical_padding,
                                                  height)
        vertical_offset = self.edge_width + vertical_padding
        horizontal_padding = ImageSize.resolve_size(self.horizontal_padding,
                                                    width)
        horizontal_offset = self.edge_width + horizontal_padding

        canvas = Image.new(
            "RGBA",
            (width + horizontal_offset * 2, height + vertical_offset * 2))

        # Paint the border
        edge = self.edge_width
        if edge:
            canvas.paste(edge_color, None)

        # Paint the padding color
        canvas.paste(background,
                     (edge, edge, edge + width + horizontal_padding * 2,
                      edge + height + vertical_padding * 2))

        # Paste the original image over the frame
        canvas.paste(image, (horizontal_offset, vertical_offset),
                     image if image.mode in ("1", "L", "RGBA") else None)

        return canvas
Example #19
0
class FreeUnitsDiscount(Discount):

    instantiable = True
    members_order = ["paid_units", "free_units", "repeated"]

    members_order = [
        "paid_units",
        "free_units",
        "repeated"
    ]
    
    paid_units = schema.Integer(
        required = True,
        min = 0
    )

    free_units = schema.Integer(
        required = True,
        min = 1
    )

    repeated = schema.Boolean(
        required = True,
        default = True
    )

    def apply(self, item, costs):

        paid = self.paid_units
        free = self.free_units
        quantity = costs["paid_quantity"]
        
        if self.repeated:
            quantity -= (quantity / (paid + free)) * free
        elif quantity > paid:
            quantity = max(paid, quantity - free)

        costs["paid_quantity"] = quantity
Example #20
0
        def model(self):
            model = schema.Schema("SetQuantitiesForm", members = [
                schema.Collection("quantity",
                    items = schema.Integer(min = 1),
                    length = len(Basket.get().purchases)
                )
            ])

            @extend(model["quantity"].items)
            def translate_error(member, error, language = None, **kwargs):
                if isinstance(error, schema.exceptions.MinValueError):
                    return translations(
                        "SetQuantitiesForm-MinValueError",
                        language,
                        **kwargs
                    )
                else:
                    return call_base(error, language, **kwargs)

            return model
Example #21
0
def _handle_declared(event):

    cls = event.source

    # Add 'id' as an alias for custom primary members
    if cls.primary_member:
        if cls.primary_member.schema is cls \
        and cls.primary_member.name != "id":
            cls.id = cls.__dict__[cls.primary_member.name]

    # Add an 'id' field to all indexed schemas that don't define their
    # own primary member explicitly. Will be initialized to an
    # incremental integer.
    elif cls.indexed:
        cls._generated_id = True
        cls.id = schema.Integer(name="id",
                                primary=True,
                                unique=True,
                                required=True,
                                indexed=True)
        cls.add_member(cls.id)
Example #22
0
class ShopOrderEntry(Item):

    listed_from_root = False

    members_order = [
        "shop_order",
        "product",
        "quantity"
    ]

    shop_order = schema.Reference(
        type = "woost.extensions.shop.shoporder.ShopOrder",
        bidirectional = True,
        required = True
    )

    product = schema.Reference(
        type = "woost.extensions.shop.product.Product",
        bidirectional = True,
        required = True
    )

    quantity = schema.Integer(
        required = True,
        min = 1
    )

    cost = schema.Decimal(
        required = True,
        default = Decimal("0"),
        editable = False
    )

    def __translate__(self, language, **kwargs):
        return "%s (%d)" % (
            translations(self.product, language),
            self.quantity
        )
Example #23
0
class NewsListing(Block):

    max_page_size = 50

    instantiable = True
    type_group = "blocks.listings"

    groups_order = list(Block.groups_order)
    groups_order.insert(groups_order.index("content") + 1, "listing")

    members_order = ["element_type", "paginated", "page_size", "view_class"]

    element_type = ElementType(member_group="content")

    paginated = schema.Boolean(required=True,
                               default=False,
                               member_group="listing")

    page_size = schema.Integer(min=1,
                               required=paginated,
                               member_group="listing")

    view_class = schema.String(required=True,
                               shadows_attribute=True,
                               enumeration=[
                                   "woost.views.CompactNewsListing",
                                   "woost.views.TextOnlyNewsListing",
                                   "woost.views.TextAndImageNewsListing"
                               ],
                               default="woost.views.TextOnlyNewsListing",
                               member_group="listing")

    def init_view(self, view):
        Block.init_view(self, view)
        view.tag = self.element_type
        view.name_prefix = self.name_prefix
        view.name_suffix = self.name_suffix
        view.depends_on(News)

        if self.paginated:
            view.pagination = self.pagination
        else:
            view.news = self.select_news()

    def select_news(self):
        news = News.select_accessible(order="-news_date")

        if not self.paginated and self.page_size:
            news.range = (0, self.page_size)

        return news

    @request_property
    def pagination(self):
        return get_parameter(self.pagination_member,
                             errors="set_default",
                             prefix=self.name_prefix,
                             suffix=self.name_suffix)

    @request_property
    def pagination_member(self):
        return Pagination.copy(
            **{
                "page_size.default": self.page_size,
                "page_size.max": self.max_page_size,
                "items": self.select_news()
            })
Example #24
0
.. moduleauthor:: Martí Congost <*****@*****.**>
"""
from cocktail import schema
from cocktail.translations import translations
from woost.models import add_setting, Configuration
from .locationtype import LocationType

translations.load_bundle("woost.extensions.locations.settings")

add_setting(schema.String("x_locations_service_uri",
                          required=True,
                          default="http://services.woost.info/locations",
                          text_search=False),
            scopes=(Configuration, ))

add_setting(schema.Integer("x_locations_update_frequency", min=1, default=15),
            scopes=(Configuration, ))

add_setting(schema.Collection("x_locations_updated_location_types",
                              default=[
                                  "continent", "country",
                                  "autonomous_community", "province", "town"
                              ],
                              items=LocationType(required=True),
                              text_search=False,
                              ui_form_control="cocktail.ui.CheckList"),
            scopes=(Configuration, ))

add_setting(schema.Collection("x_locations_updated_subset",
                              items=schema.String(required=True),
                              ui_form_control="cocktail.ui.TextArea"),
Example #25
0
 def position(self):
     return get_parameter(
         schema.Integer("position", min=0, max=len(self.collection)))
Example #26
0
class FacebookLikeButton(Block):

    instantiable = True
    type_group = "blocks.social"
    view_class = "cocktail.html.FacebookLikeButton"

    members_order = [
        "fb_href", "fb_layout", "fb_send", "fb_show_faces", "fb_width",
        "fb_action", "fb_font", "fb_colorscheme", "fb_ref"
    ]

    fb_href = schema.Reference(type=Publishable,
                               related_end=schema.Collection(),
                               member_group="content")

    fb_layout = schema.String(
        required=True,
        default="standard",
        enumeration=["standard", "button_count", "box_count"],
        member_group="appearence")

    fb_send = schema.Boolean(default=False,
                             required=True,
                             member_group="appearence")

    fb_show_faces = schema.Boolean(default=False,
                                   required=True,
                                   member_group="appearence")

    fb_width = schema.Integer(required=True,
                              default=450,
                              member_group="appearence")

    fb_action = schema.String(required=True,
                              default="like",
                              enumeration=["like", "recommend"],
                              member_group="appearence")

    fb_font = schema.String(required=True,
                            default="arial",
                            enumeration=[
                                "arial", "lucida grande", "segoe ui", "tahoma",
                                "trebuchet ms", "verdana"
                            ],
                            translatable_enumeration=False,
                            member_group="appearence")

    fb_colorscheme = schema.String(required=True,
                                   default="light",
                                   enumeration=["light", "dark"],
                                   member_group="appearence")

    fb_ref = schema.String(member_group="content")

    def init_view(self, view):
        Block.init_view(self, view)
        view.href = self.fb_href and self.fb_href.get_uri(host=".")
        view.send = self.fb_send
        view.layout = self.fb_layout
        view.show_faces = self.fb_show_faces
        view.width = self.fb_width
        view.action = self.fb_action
        view.font = self.fb_font
        view.colorscheme = self.fb_colorscheme
        view.ref = self.fb_ref
Example #27
0
class AudioEncoder(Item):

    instantiable = True
    visible_from_root = False
    resolution = 0.25

    members_order = [
        "identifier", "mime_type", "extension", "command", "timeout",
        "timeout_size_factor"
    ]

    identifier = schema.String(required=True,
                               unique=True,
                               indexed=True,
                               normalized_index=False,
                               descriptive=True)

    mime_type = schema.String(required=True)

    extension = schema.String(required=True)

    command = schema.String(required=True)

    timeout = schema.Integer(required=True, default=60)

    timeout_size_factor = schema.Float(default=10.0)

    def encode(self, file, dest):

        # Most encoders expect PCM wave files as input, so we start by finding
        # an appropiate decoder for the given file.
        mime_type = file.mime_type

        if mime_type == "audio/mp3":
            mime_type = "audio/mpeg"

        decoder = AudioDecoder.require_instance(mime_type=mime_type)

        # Next, we produce the command line instructions for the decoding /
        # encoding procedure, using a shell pipe.
        decode_command = decoder.command % file.file_path
        encode_command = self.command % dest
        command = decode_command + " | " + encode_command

        # Calculate the timeout, based on a base value incremented according to
        # a file size factor
        timeout = self.timeout

        if self.timeout_size_factor:
            size = file.file_size
            if size:
                timeout += size / (self.timeout_size_factor * 1024 * 1024)

        # Encode the file and save it to the indicated location
        proc = Popen(command, shell=True, stdout=PIPE, stderr=PIPE)
        start = time()

        while proc.poll() is None:
            if time() - start > timeout:
                proc.terminate()
                raise AudioEncodingTimeoutError(
                    "The following audio encoding command exceeded its "
                    "timeout of %d seconds: %s" % (timeout, command))
            sleep(self.resolution)

        if proc.returncode:
            raise AudioEncodingCommandError(
                "The following audio encoding command reported an error: "
                "%s\n%s" % (command, proc.stderr.read().strip()))
Example #28
0
class CountriesExtension(Extension):
    def __init__(self, **values):
        Extension.__init__(self, **values)
        self.extension_author = u"Whads/Accent SL"
        self.set(
            "description", u"""Proporciona accés a la llista de països del món,
            actualitzada a través d'Internet.""", "ca")
        self.set(
            "description",
            u"""Proporciona acceso a la lista de países del mundo, actualizada
            a través de Internet.""", "es")
        self.set(
            "description",
            u"""Provides a list of world countries, automatically updated from
            the Internet.""", "en")

    last_update = None

    update_frequency = schema.Integer(min=1, required=True, default=15)

    def _load(self):

        from woost.extensions.countries import country, strings

        now = time()

        if self.last_update is None \
        or now - self.last_update >= self.update_frequency * SECONDS_IN_A_DAY:
            try:
                self.update_country_list()
            except:
                pass
            else:
                self.last_update = now
                datastore.commit()

    def update_country_list(self):
        from woost.extensions.countries.country import Country
        error = None

        database_modified = False
        service_uri = "http://www.lonelydrops.com/drops/1.0/list/%s/countries"

        data_expr = re.compile(r"var\s+drops_countries_[a-z]{2}\s*=\s*([^;]+)",
                               re.DOTALL)
        json_property_normalization = re.compile(
            r"([a-zA-Z_$][a-zA-Z_$0-9]*)(?=\s*:)")

        for language in Configuration.instance.languages:
            try:
                javascript = urlopen(service_uri % language).read()
            except Exception, error:
                pass
            else:
                match = data_expr.search(javascript)

                if not match:
                    sys.stderr.write(
                        "The country list provider returned data in an "
                        "unexpected format (requested translation: %s)" %
                        language)
                    continue

                json = match.group(1)
                json = json_property_normalization.sub(r'"\1"', json)

                try:
                    data = loads(json)
                except Exception, error:
                    sys.stderr.write(
                        "The country list provider returned invalid data: %s"
                        "(requested translation: %s)\n" % (error, language))
                    continue

                for country_data in data:

                    # Ignore continents
                    if country_data.get("isParent"):
                        continue

                    name = country_data["label"]
                    iso_code = country_data["value"].lower()
                    country = Country.get_instance(iso_code=iso_code)

                    # New country
                    if country is None:
                        country = Country()
                        country.iso_code = iso_code
                        country.set("country_name", name, language)
                        country.insert()
                        database_modified = True

                    # Modified country
                    elif country.get("country_name", language) != name:
                        country.set("country_name", name, language)
                        database_modified = True
Example #29
0
class Feed(Publishable):

    type_group = "setup"
    instantiable = True

    groups_order = ["meta", "feed_items"]

    members_order = [
        "title", "ttl", "image", "description", "limit", "query_parameters",
        "item_title_expression", "item_link_expression",
        "item_publication_date_expression", "item_description_expression"
    ]

    default_mime_type = u"application/rss+xml"

    default_controller = schema.DynamicDefault(
        lambda: Controller.get_instance(qname="woost.feed_controller"))

    edit_controller = \
        "woost.controllers.backoffice.feedfieldscontroller." \
        "FeedFieldsController"
    edit_view = "woost.views.FeedFields"

    title = schema.String(indexed=True,
                          normalized_index=True,
                          full_text_indexed=True,
                          descriptive=True,
                          translated=True,
                          member_group="meta")

    ttl = schema.Integer(listed_by_default=False, member_group="meta")

    image = schema.Reference(
        type=Publishable,
        related_end=schema.Collection(),
        relation_constraints=Publishable.resource_type.equal("image"),
        member_group="meta")

    description = schema.String(required=True,
                                translated=True,
                                listed_by_default=False,
                                edit_control="cocktail.html.TextArea",
                                member_group="meta")

    limit = schema.Integer(min=1,
                           listed_by_default=False,
                           member_group="feed_items")

    query_parameters = schema.Mapping(keys=schema.String(),
                                      required=True,
                                      listed_by_default=False,
                                      member_group="feed_items")

    item_title_expression = schema.CodeBlock(language="python",
                                             required=True,
                                             default="translations(item)",
                                             member_group="feed_items")

    item_link_expression = schema.CodeBlock(language="python",
                                            required=True,
                                            default="cms.uri(item)",
                                            member_group="feed_items")

    item_publication_date_expression = schema.CodeBlock(
        language="python",
        required=True,
        default="item.start_date or item.creation_time",
        member_group="feed_items")

    item_description_expression = schema.CodeBlock(language="python",
                                                   required=True,
                                                   default="item.description",
                                                   member_group="feed_items")

    def select_items(self):

        user_collection = UserCollection(Publishable)
        user_collection.allow_paging = False
        user_collection.allow_member_selection = False
        user_collection.allow_language_selection = False
        user_collection.params.source = self.query_parameters.get
        user_collection.available_languages = \
            Configuration.instance.get_enabled_languages()
        items = user_collection.subset

        if self.limit:
            items.range = (0, self.limit)

        return items
Example #30
0
class File(Publishable):

    instantiable = True
    cacheable = False
    type_group = "resource"

    edit_node_class = \
        "woost.controllers.backoffice.fileeditnode.FileEditNode"
    backoffice_heading_view = "woost.views.BackOfficeFileHeading"
    video_player = "cocktail.html.MediaElementVideo"

    default_mime_type = None

    default_encoding = None

    default_controller = schema.DynamicDefault(
        lambda: Controller.get_instance(qname="woost.file_controller"))

    members_order = ["title", "file_name", "file_size", "file_hash"]

    title = schema.String(indexed=True,
                          normalized_index=True,
                          full_text_indexed=True,
                          descriptive=True,
                          translated=True,
                          member_group="content")

    file_name = schema.String(required=True,
                              editable=False,
                              member_group="content")

    file_size = schema.Integer(
        required=True,
        editable=False,
        translate_value=lambda size, language=None, **kwargs: ""
        if size in (None, "") else format_bytes(size),
        min=0,
        member_group="content")

    file_hash = schema.String(visible=False,
                              searchable=False,
                              text_search=False,
                              member_group="content")

    @property
    def file_extension(self):
        return os.path.splitext(self.file_name)[1]

    @property
    def file_path(self):
        return app.path("upload", str(self.id))

    @classmethod
    def from_path(cls,
                  path,
                  dest=None,
                  languages=None,
                  hash=None,
                  encoding="utf-8",
                  download_temp_folder=None,
                  redownload=False):
        """Imports a file into the site.
        
        @param path: The path to the file that should be imported.
        @type path: str

        @param dest: The base path where the file should be copied (should match
            the upload folder for the application).
        @type dest: str

        @param languages: The set of languages that the created file will be
            translated into.
        @type languages: str set
       
        @return: The created file.
        @rtype: L{File}
        """

        # The default behavior is to translate created files into all the languages
        # defined by the site
        if languages is None:
            from woost.models import Configuration
            languages = Configuration.instance.languages

        file_name = os.path.split(path)[1]
        title, ext = os.path.splitext(file_name)

        # Download remote files
        if "://" in path:
            if not download_temp_folder:
                download_temp_folder = mkdtemp()

            temp_path = os.path.join(download_temp_folder, file_name)

            if redownload or not os.path.exists(temp_path):
                response = urlopen(path)
                with open(temp_path, "w") as temp_file:
                    copyfileobj(response, temp_file)

            path = temp_path

        if encoding:
            if isinstance(title, str):
                title = title.decode(encoding)
            if isinstance(file_name, str):
                file_name = file_name.decode(encoding)

        title = title.replace("_", " ").replace("-", " ")
        title = title[0].upper() + title[1:]

        file = cls()

        file.file_size = os.stat(path).st_size
        file.file_hash = hash or file_hash(path)
        file.file_name = file_name

        # Infer the file's MIME type
        mime_type = guess_type(file_name, strict=False)
        if mime_type:
            file.mime_type = mime_type[0]

        for language in languages:
            file.set("title", title, language)

        if dest is None:
            upload_path = file.file_path
        else:
            upload_path = os.path.join(dest, str(file.id))

        copy(path, upload_path)

        return file