Esempio n. 1
0
def test_i18n_urls(web_fixture):
    """The current locale is determined by reading the first segment of the path. If the locale is not present in the
    path, web.default_url_locale is used."""
    _ = Catalogue('reahl-web')

    class I18nUI(UserInterface):
        def assemble(self):
            view = self.define_view('/aview', title=_('A View'))

    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page)
            self.define_user_interface('/a_ui',  I18nUI,  IdentityDictionary(), name='test_ui')

    wsgi_app = web_fixture.new_wsgi_app(site_root=MainUI)
    browser = Browser(wsgi_app)

    browser.open('/a_ui/aview')
    assert browser.title == 'A View'

    browser.open('/af/a_ui/aview')
    assert browser.title == '\'n Oogpunt'

    web_fixture.config.web.default_url_locale = 'af'
    browser.open('/a_ui/aview')
    assert browser.title == '\'n Oogpunt'

    browser.open('/en_gb/a_ui/aview')
    assert browser.title == 'A View'
Esempio n. 2
0
def test_translator_singleton():
    """Only one SystemWideCatalogue is ever present per process."""

    SystemWideCatalogue.instance = None  # To "reset" the singleton, else its __init__ will NEVER be called in this test

    with InitMonitor(SystemWideCatalogue) as monitor:
        _ = Catalogue('reahl-component')
        _2 = Catalogue('reahl-component')

        context = LocaleContextStub().install()

        _('test string')
        _.ngettext('thing', 'things', 1)
        _.ngettext('thing', 'things', 2)

        _2('test string')

    assert monitor.times_called == 1
Esempio n. 3
0
def test_translator_singleton_thread_safety():
    """The SystemWideCatalogue.get_instance() is this thread-safe."""
    SystemWideCatalogue.instance = None  # To "reset" the singleton, else its __init__ will NEVER be called in this test
    SystemWideCatalogue.get_instance().map_lock.acquire()
    saved_state = EmptyStub()
    saved_state.lock_released = False

    def release_lock():
        SystemWideCatalogue.get_instance().map_lock.release()
        saved_state.lock_released = True

    timer = Timer(.1, release_lock)
    timer.start()
    context = LocaleContextStub().install()
    _ = Catalogue('reahl-component')
    _.gettext('test string')
    timer.cancel()
    assert saved_state.lock_released
Esempio n. 4
0
def test_formatting():
    """A Catalogue can be used to easily obtain the current locale for use
       by other i18n tools."""

    _ = Catalogue('reahl-component')

    date = datetime.date(2012, 1, 10)

    context = LocaleContextStub().install()

    context.test_locale = 'en_gb'
    assert _.current_locale == 'en_gb'
    actual = babel.dates.format_date(date,
                                     format='long',
                                     locale=_.current_locale)
    assert actual == '10 January 2012'

    context.test_locale = 'af'
    assert _.current_locale == 'af'
    actual = babel.dates.format_date(date,
                                     format='long',
                                     locale=_.current_locale)
    assert actual == '10 Januarie 2012'
Esempio n. 5
0
def test_basic_usage():
    """A Catalogue for a particular component can translate messages for that component into
       the interface_locale on its current ExecutionContext."""

    _ = Catalogue(
        'reahl-component'
    )  # Will find its translations in the compiled messages of reahl-component

    context = LocaleContextStub().install()

    context.test_locale = 'en_gb'
    assert _('test string') == 'test string'
    assert _.gettext('test string') == 'test string'
    assert _.ngettext('thing', 'things', 1) == 'thing'
    assert _.ngettext('thing', 'things', 3) == 'things'

    context.test_locale = 'af'
    assert _('test string') == 'toets string'
    assert _.gettext('test string') == 'toets string'
    assert _.ngettext('thing', 'things', 1) == 'ding'
    assert _.ngettext('thing', 'things', 3) == 'goeters'
Esempio n. 6
0
File: ui.py Progetto: smohaorg/reahl

"""

from reahl.component.exceptions import ProgrammerError
from reahl.component.i18n import Catalogue
from reahl.component.modelinterface import exposed

import reahl.web.ui
# These are imported here for convenience so they can be imported from reahl.web.bootstrap.ui:
from reahl.web.ui import A, Article, Body, Br, Div, Footer, H, Head, Header, Img, \
    Li, Link, LiteralHTML, Meta, Nav, Ol, OptGroup, P, Small, RunningOnBadge, Slot, Span, TextNode, \
    Title, Ul, WrappedInput, FieldSet, Legend, HTMLAttributeValueOption, Widget, HTMLElement, HTMLWidget, \
    Br, Hr

_ = Catalogue('reahl-web')


class Alert(Div):
    """A message box meant to alert the user of some message.

    See also: :class:`Badge`.

    :param view: (See :class:`reahl.web.fw.Widget`)
    :param message_or_widget: Message text or a Widget to display inside the Alert.
    :param severity: One of 'primary', 'secondary', 'success', 'info', 'warning', 'danger', 'light', 'dark'
        to indicate the color scheme for the Alert.

    """
    def __init__(self, view, message_or_widget, severity):
        super().__init__(view)
Esempio n. 7
0
# Copyright 2013-2020 Reahl Software Services (Pty) Ltd. All rights reserved.
#
#    This file is part of Reahl.
#
#    Reahl 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; version 3 of the License.
#
#    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 Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

from sqlalchemy import Column, Integer

from reahl.sqlalchemysupport import Base
from reahl.component.i18n import Catalogue

_ = Catalogue('reahl-domain')


class Party(Base):
    """A Party is any legal entity which the system may keep track of."""
    __tablename__ = 'party'
    id = Column(Integer, primary_key=True)
Esempio n. 8
0
from reahl.web.fw import UserInterface, Widget
from reahl.web.bootstrap.page import HTML5Page
from reahl.web.bootstrap.ui import Div, H, P, FieldSet
from reahl.web.bootstrap.navbar import Navbar, ResponsiveLayout
from reahl.web.bootstrap.navs import Nav
from reahl.web.bootstrap.grid import Container
from reahl.web.bootstrap.forms import TextInput, Form, FormLayout, Button, ButtonLayout
from reahl.component.modelinterface import exposed, Field, EmailField, Action, Event
from reahl.sqlalchemysupport import Session, Base
from reahl.component.i18n import Catalogue
from sqlalchemy import Column, Integer, UnicodeText, Date
import babel.dates

# Declare a Catalogue for your component
_ = Catalogue('reahl-doc')


class AddressBookPage(HTML5Page):
    def __init__(self, view):
        super(AddressBookPage, self).__init__(view)
        self.body.use_layout(Container())

        layout = ResponsiveLayout('md',
                                  colour_theme='dark',
                                  bg_scheme='primary')
        navbar = Navbar(view, css_id='my_nav').use_layout(layout)
        navbar.layout.set_brand_text(_('Address book'))
        navbar.layout.add(Nav(view).with_languages())

        self.body.add_child(navbar)
Esempio n. 9
0
from reahl.domain.systemaccountmodel import LoginSession
from reahl.component.i18n import Catalogue
from reahl.component.py3compat import ascii_as_bytes_or_str
from reahl.component.context import ExecutionContext
from reahl.web.fw import ReahlWSGIApplication, UrlBoundView, UserInterface, Url, Widget
from reahl.web.ui import HTML5Page, Slot, Div
from reahl.web.layout import Layout
from reahl.web.egg import WebConfig

from reahl.dev.fixtures import ReahlSystemFixture
from reahl.webdev.fixtures import WebServerFixture
from reahl.sqlalchemysupport_dev.fixtures import SqlAlchemyFixture
from reahl.domain_dev.fixtures import PartyAccountFixture

_ = Catalogue('reahl-webdev')


@stubclass(ReahlWSGIApplication)
class ReahlWSGIApplicationStub(ReahlWSGIApplication):
    def add_reahl_static_files(self):
        static_files = self.config.web.frontend_libraries.packaged_files()
        static_files_no_js = [
            packaged_file for packaged_file in static_files
            if not packaged_file.relative_name.endswith('.js')
        ]
        return self.define_static_files('/static', static_files_no_js)


class BasicPageLayout(Layout):
    def __init__(self, slots=['main', 'footer']):
Esempio n. 10
0
from sqlalchemy.ext.declarative import instrument_declarative, declarative_base, DeclarativeMeta
from sqlalchemy.exc import InvalidRequestError
from sqlalchemy import Column, Integer, ForeignKey
from alembic.migration import MigrationContext
from alembic.operations import Operations
from alembic.autogenerate import compare_metadata

from reahl.component.i18n import Catalogue
from reahl.component.eggs import ReahlEgg
from reahl.component.dbutils import ORMControl
from reahl.component.context import ExecutionContext, NoContextFound
from reahl.component.modelinterface import Field, IntegerConstraint
from reahl.component.exceptions import ProgrammerError
from reahl.component.config import Configuration

_ = Catalogue('reahl-sqlalchemysupport')


class SqlAlchemyConfig(Configuration):
    filename = 'sqlalchemy.config.py'
    config_key = 'sqlalchemy'

    def do_injections(self, config):
        if not isinstance(config.reahlsystem.orm_control, SqlAlchemyControl):
            config.reahlsystem.orm_control = SqlAlchemyControl(echo=False)


def reahl_scope():
    try:
        return ExecutionContext.get_context_id()
    except NoContextFound:
Esempio n. 11
0
 def as_user_message(self):
     # To ensure this module can be imported at a very low level
     from reahl.component.i18n import Catalogue
     _ = Catalogue('reahl-component')
     return self.message if self.message else _('An error occurred: %s' % self.__class__.__name__)
Esempio n. 12
0
"""

from reahl.component.exceptions import ProgrammerError
from reahl.component.i18n import Catalogue
from reahl.component.context import ExecutionContext
from reahl.sqlalchemysupport import PersistedField
from reahl.web.fw import UserInterface, UrlBoundView, Detour, ViewPreCondition
from reahl.web.ui import HTMLWidget
from reahl.web.bootstrap.ui import P, Div, Ul, Li, H
from reahl.web.bootstrap.forms import Form, Button, FormLayout

from reahl.domain.workflowmodel import Inbox, Task, WorkflowInterface
from reahl.domain.systemaccountmodel import LoginSession

_ = Catalogue('reahl-domainui')


class TaskBox(Li):
    def __init__(self, view, task):
        super().__init__(view)
        self.task = task
        self.add_child(P(view, text=self.task.title))
        form = self.add_child(Form(view, 'task_%s' % task.id))
        form.use_layout(FormLayout())
        form.layout.add_input(
            Button(form,
                   self.user_interface.workflow_interface.events.take_task.
                   with_arguments(task=self.task),
                   style='primary'),
            hide_label=True)
Esempio n. 13
0
from __future__ import print_function, unicode_literals, absolute_import, division
import six
import sys
import functools

import wrapt
import inspect

from reahl.component.i18n import Catalogue

if six.PY2:
    from collections import Callable
else:
    from collections.abc import Callable

_ = Catalogue('reahl-component')


class DomainException(Exception):
    """Any exception indicating an application-specific error condition that 
       should be communicated to a user.

       :keyword commit: Set to True to indicate that the current database transaction 
                        should be committed. By default transactions are rolled back
                        when a DomainException is raised.
       :keyword message: Optional error message.
    """
    def __init__(self, commit=False, message=None, detail_messages=[]):
        super(DomainException, self).__init__(message)
        self.commit = commit
        self.message = message