Example #1
0
def test_empty_stub():
    """an EmptyStub can be created with instance attributes"""

    #normal case
    value = EmptyStub()
    stub = EmptyStub(a_value = value)
    assert stub.a_value is value
Example #2
0
def test_invalid_schedule_name_raises():
    """A useful error is raised when an attempt is made to schedule a call in a phase that is not defined."""
    
    migration_schedule = MigrationSchedule(EmptyStub(), EmptyStub(), [])

    with expected(ProgrammerError, test=r'A phase with name<wrong_name> does not exist\.'):
        migration_schedule.schedule('wrong_name', EmptyStub(), EmptyStub(), EmptyStub())
Example #3
0
def test_file_marshalling(fixture):
    """A FileField receives as input a list of UploadedFile objects.  Its marshalling job consists
       of merely changing such a list into a single value, or returning it as is depending on
       the setting of its allow_multiple flag.
    """

    field = FileField()
    obj = fixture.model_object
    field.bind('file_value', obj)

    files = [EmptyStub(), EmptyStub()]

    # Single file only
    field.from_input(files[:1])
    assert obj.file_value == files[0]

    obj.file_value = files[0]
    assert field.as_input() == ''

    # Multiple files
    field = FileField(allow_multiple=True)
    field.bind('file_value', obj)

    field.from_input(files)
    assert obj.file_value == files

    obj.file_value = files
    assert field.as_input() == ''
Example #4
0
def view_rights_propagate_to_a(fixture):
    """The access rights specified for a View are propagated to an A, made from a Bookmark to that View."""
    fixture.view.write_check = EmptyStub()
    fixture.view.read_check = EmptyStub()
    a = A.from_bookmark(fixture.view, fixture.view.as_bookmark())
    vassert( a.read_check is fixture.view.read_check )
    vassert( a.write_check is fixture.view.write_check )
Example #5
0
def test_file_validation(fixture):
    """A FileField needs to check that the right number of files were submitted, depending on the
       setting of allow_multiple and/or required.
    """

    field = FileField()
    obj = fixture.model_object
    field.bind('file_value', obj)

    files = [EmptyStub(), EmptyStub()]

    # Single file only
    with expected(SingleFileConstraint):
        field.set_user_input(files)

    with expected(NoException):
        field.set_user_input(files[:1])

    # Single file that is required
    field = FileField(required=True)
    field.bind('file_value', obj)

    with expected(NoException):
        field.set_user_input(files[:1])

    with expected(RequiredConstraint):
        field.set_user_input([])

    # Multiple files
    field = FileField(allow_multiple=True)
    field.bind('file_value', obj)

    with expected(NoException):
        field.set_user_input(files)
Example #6
0
def test_global_state():
    """A Field can store its data in a global dict so that it can be recreated later with the same underlying data."""
    ExecutionContext().install()
    state_dict = {}
    a = Field()
    a.bind('x', a)

    a.input_status = EmptyStub()
    a.validation_error = EmptyStub()
    a.user_input = EmptyStub()
    a.parsed_input = EmptyStub()

    a.activate_global_field_data_store(state_dict)

    a.initial_value = EmptyStub()

    b = Field()
    b.bind('x', b)

    assert a.initial_value is not b.initial_value
    assert a.input_status is not b.input_status
    assert a.validation_error is not b.validation_error
    assert a.user_input is not b.user_input
    assert a.parsed_input is not b.parsed_input

    b.activate_global_field_data_store(state_dict)

    assert a.initial_value is b.initial_value
    assert a.input_status is b.input_status
    assert a.validation_error is b.validation_error
    assert a.user_input is b.user_input
    assert a.parsed_input is b.parsed_input
Example #7
0
def test_namespaces():
    ExecutionContext().install()
    state_dict = {}
    a = Field()
    a.bind('x', a)

    # Case: namespaces change the name of the Field
    b = a.in_namespace('deeper')

    assert a.name == 'x'
    assert b.name == 'deeper-x'

    # Case: namespaces can be nested
    c = b.in_namespace('even')
    assert c.name == 'even-deeper-x'

    # Case: a Field *in* different namespace, but made from another share the same data
    a.initial_value = EmptyStub()
    a.input_status = EmptyStub()
    a.validation_error = EmptyStub()
    a.user_input = EmptyStub()
    a.parsed_input = EmptyStub()

    assert a.initial_value is b.initial_value is c.initial_value
    assert a.input_status is b.input_status is c.input_status
    assert a.validation_error is b.validation_error is c.validation_error
    assert a.user_input is b.user_input is c.user_input
    assert a.parsed_input is b.parsed_input is c.parsed_input
Example #8
0
class ColumnScenarios(Fixture):
    sort_key = EmptyStub()
    heading = 'A heading'
    row_item = EmptyStub(some_attribute=True)

    @scenario
    def static_column(self):
        """StaticColumn represents an attribute of the item in a row, using a Field to translate the value of that attribute into a string and to specify a column header."""
        self.column = StaticColumn(BooleanField(label=self.heading), 'some_attribute', sort_key=self.sort_key)
        self.expected_cell_html = 'on' # as translated by BooleanField
        self.expected_heading_html = '<span>A heading</span>'

    @scenario
    def dynamic_column(self):
        """DynamicColumn uses a function to create a Widget on the fly for each cell and uses the specified heading."""
        def make_span(view, data_item):
            return Span(view, text='Answer: %s' % (data_item.some_attribute))

        self.column = DynamicColumn(self.heading, make_span, sort_key=self.sort_key)
        self.expected_cell_html = '<span>Answer: True</span>' # raw attribute used
        self.expected_heading_html = '<span>A heading</span>'

    @scenario
    def dynamic_column_static_heading(self):
        """A DynamicColumn can also use a function to create its heading on the fly."""
        def make_span(view, data_item):
            return Span(view, text='Answer: %s' % (data_item.some_attribute))

        def make_heading(view):
            return P(view, text=self.heading)

        self.column = DynamicColumn(make_heading, make_span, sort_key=self.sort_key)
        self.expected_cell_html = '<span>Answer: True</span>' # raw attribute used
        self.expected_heading_html = '<p>A heading</p>'
Example #9
0
def test_arguments_to_event(fixture):
    """Only Action objects can be sent as action= when creating an Event. The arguments passed to readable and writable
       should be callable objects with correct signature."""

    # action=
    with expected(IsInstance):
        Event(action=EmptyStub())

    def check_exc(expected_message, ex):
        message = str(ex).split(':')[1][1:]
        assert message.startswith(expected_message)

        # readable/writable are callable

    with expected(IsCallable,
                  test=functools.partial(
                      check_exc, 'readable should be a callable object')):
        Event(readable=EmptyStub())
    with expected(IsCallable,
                  test=functools.partial(
                      check_exc, 'writable should be a callable object')):
        Event(writable=EmptyStub())

    # readable/writable have correct signature
    def do_nothing(a, b, c, d):
        pass

    with expected(IncorrectArgumentError):
        Event(readable=do_nothing)
    with expected(IncorrectArgumentError):
        Event(writable=do_nothing)
Example #10
0
def wrong_args_to_input(fixture):
    """Passing the wrong arguments upon constructing an Input results in an error."""

    with expected(IsInstance):
        PrimitiveInput(fixture.form, EmptyStub())

    with expected(IsInstance):
        PrimitiveInput(EmptyStub(), Field())
Example #11
0
def test_wrong_args_to_input(simple_input_fixture):
    """Passing the wrong arguments upon constructing an Input results in an error."""

    fixture = simple_input_fixture

    with expected(IsInstance):
        PrimitiveInput(fixture.form, EmptyStub(in_namespace=lambda self: self))

    with expected(IsInstance):
        PrimitiveInput(EmptyStub(channel_name='test'), Field())
Example #12
0
    def widget_adding_error(self, fixture):
        """Passing anything other than other Widgets to .add_child or add_children results in an error."""

        widget = Widget(fixture.view)

        with expected(IsInstance):
            widget.add_child(EmptyStub())

        with expected(IsInstance):
            widget.add_children([Widget(fixture.view), EmptyStub()])
Example #13
0
    def re_binding_behaviour_of_field_index(self, fixture):
        """FieldIndexes wont bind a field if it already is bound."""
        model_object1 = EmptyStub()
        model_object2 = EmptyStub()
        bound_field = Field()
        bound_field.bind('bound_field', model_object2)

        vassert( bound_field.is_bound )
        vassert( bound_field.bound_to is model_object2 )
        index = FieldIndex(model_object1)
        index.new_name_for_bound_field = bound_field
        vassert( index.new_name_for_bound_field.name is 'bound_field' )
        vassert( bound_field.bound_to is model_object2 )
Example #14
0
def test_re_binding_behaviour_of_field_index(fixture):
    """FieldIndexes wont bind a field if it already is bound."""

    model_object1 = EmptyStub()
    model_object2 = EmptyStub()
    bound_field = Field()
    bound_field.bind('bound_field', model_object2)

    assert bound_field.is_bound
    assert bound_field.bound_to is model_object2
    index = FieldIndex(model_object1)
    index.new_name_for_bound_field = bound_field
    assert index.new_name_for_bound_field.name is 'bound_field'
    assert bound_field.bound_to is model_object2
Example #15
0
def test_contents():
    """A Session, Config or SystemControl may be set on the ExecutionContext."""
    some_context = ExecutionContext()

    session = EmptyStub()
    config = EmptyStub()
    system_control = EmptyStub()

    some_context.session = session
    some_context.config = config
    some_context.system_control = system_control

    assert some_context.session is session
    assert some_context.config is config
    assert some_context.system_control is system_control
Example #16
0
    def contents(self, fixture):
        """A Session, Config or SystemControl may be set on the ExecutionContext."""
        some_context = ExecutionContext()

        session = EmptyStub()
        config = EmptyStub()
        system_control = EmptyStub()

        some_context.set_session(session)
        some_context.set_config(config)
        some_context.set_system_control(system_control)

        vassert(some_context.session is session)
        vassert(some_context.config is config)
        vassert(some_context.system_control is system_control)
Example #17
0
    def interface_with_meta_info(self, fixture):
        """A Reahl component can publish a ReahlEgg instance to supply extra meta information about itself.
           Such interfaces with extra information are also often used from a flattened list in dependency order."""

        easter_egg.clear()
        easter_egg.add_dependency('reahl-component')

        # The interface for a component is published via the reahl.eggs entry point
        line = 'Egg = reahl.component.eggs:ReahlEgg'
        easter_egg.add_entry_point_from_line('reahl.eggs', line)

        # Interfaces can be queried in dependency order too
        interfaces_in_order = ReahlEgg.compute_all_relevant_interfaces(
            easter_egg.as_requirement_string())
        vassert(len(interfaces_in_order) ==
                2)  # That of reahl-component itself, and of the easteregg
        [interface
         ] = [i for i in interfaces_in_order if i.distribution is easter_egg]

        # The meta-info that can be obtained via such an interface
        vassert(interface.configuration_spec is None)

        orm_control = EmptyStub()
        vassert(interface.get_persisted_classes_in_order(orm_control) == [])
        vassert(interface.migrations_in_order == [])
        vassert(interface.get_roles_to_add() == [])

        # Hooks for allowing a component to do its own housekeeping
        with expected(NoException):
            interface.do_daily_maintenance()
Example #18
0
    def integer_marshalling(self, fixture):
        field = IntegerField()
        obj = EmptyStub()
        field.bind('integer_value', obj)

        # From input
        field.from_input('5')
        vassert( obj.integer_value is 5 )

        # As input
        obj.integer_value = 6
        vassert( field.as_input() == '6' )

        # As input - corner case
        obj.integer_value = 0
        vassert( field.as_input() == '0' )
Example #19
0
def test_password_access(fixture):
    """A PasswordField is world writable, but not readable by anyone."""

    field = PasswordField()
    field.bind('password_field', EmptyStub())
    assert not field.can_read()
    assert field.can_write()
Example #20
0
    def basic_marshalling(self, fixture):
        field = Field()
        obj = EmptyStub()
        field.bind('value', obj)

        # From input
        field.from_input('abc')
        vassert( obj.value == 'abc' )

        # As input
        obj.value = 'def'
        vassert( field.as_input() == 'def' )

        # As input - corner case
        obj.value = ''
        vassert( field.as_input() == '' )
Example #21
0
def test_boolean_validation(fixture):

    obj = EmptyStub()
    field = BooleanField()
    field.bind('boolean_attribute', obj)

    # Case: invalid
    invalid_boolean_name = ['negative', 'affirmative', '+', '-', None]
    for boolean_candidate in invalid_boolean_name:
        with expected(AllowedValuesConstraint):
            field.set_user_input(boolean_candidate)
        assert field.validation_error is field.get_validation_constraint_named(
            'pattern')

        # Case: valid
    field.from_input('on')
    assert obj.boolean_attribute is True
    assert field.as_input() == 'on'
    field.from_input('off')
    assert obj.boolean_attribute is False
    assert field.as_input() == 'off'

    # Case: required means True for BooleanField
    field = BooleanField(required=True)
    field.bind('boolean_attribute', obj)
    with expected(AllowedValuesConstraint):
        field.set_user_input('off')
    assert field.validation_error is field.get_validation_constraint_named(
        'pattern')
    with expected(NoException):
        field.from_input('on')
Example #22
0
def test_error_reporting_on_breaking_migrations():
    """When there is an error during execution of a Migration, the code where it was scheduled is reported."""

    class SomeObject:
        def please_call_me(self):
            raise Exception('breaking intentionally')
    some_object = SomeObject()

    migration_schedule = MigrationSchedule(EmptyStub(), EmptyStub(), [])
    migration = Migration(migration_schedule)

    migration.schedule('alter', some_object.please_call_me)

    def is_please_call_me_on_stack(ex):
        return re.match(".*The above Exception happened for the migration that was scheduled here:.*    migration.schedule\('alter', some_object.please_call_me\)", str(ex), re.MULTILINE|re.S)
    with expected(ExceptionDuringMigration, test=is_please_call_me_on_stack):
        migration_schedule.execute_all()
Example #23
0
def test_basic_marshalling(fixture):

    field = Field()
    obj = EmptyStub()
    field.bind('value', obj)

    # From input
    field.from_input('abc')
    assert obj.value == 'abc'

    # As input
    obj.value = 'def'
    assert field.as_input() == 'def'

    # As input - corner case
    obj.value = ''
    assert field.as_input() == ''
Example #24
0
def test_integer_marshalling(fixture):

    field = IntegerField()
    obj = EmptyStub()
    field.bind('integer_value', obj)

    # From input
    field.from_input('5')
    assert obj.integer_value is 5

    # As input
    obj.integer_value = 6
    assert field.as_input() == '6'

    # As input - corner case
    obj.integer_value = 0
    assert field.as_input() == '0'
Example #25
0
def test_getting_modified_copy(fixture):
    """It is possible to get a modified copy of an existing field if you want to link it with
       different constraints on a different input"""

    other_constraint = ValidationConstraint('Other error')
    other_constraint.name = 'other'
    field = Field()
    field.add_validation_constraint(other_constraint)
    model_object = EmptyStub()
    field.bind('field_name', model_object)

    # Getting a copy
    new_field = field.copy()
    assert new_field is not field
    assert new_field.name == field.name
    assert new_field.storage_object == field.storage_object
    assert new_field.default == field.default
    assert new_field.label == field.label
    copied_other_constraint = new_field.get_validation_constraint_named(other_constraint.name)
    assert copied_other_constraint.field is new_field
    new_validation_constraints = [i.__class__ for i in new_field.validation_constraints]
    old_validation_constraints = [i.__class__ for i in field.validation_constraints]
    assert new_validation_constraints == old_validation_constraints
    assert new_field.validation_constraints != field.validation_constraints
    assert new_field.validation_constraints is not field.validation_constraints

    assert new_field.access_rights is not field.access_rights
    assert new_field.access_rights.readable is field.access_rights.readable
    assert new_field.access_rights.writable is field.access_rights.writable

    # Getting a required copy
    assert not field.required
    required_field = field.as_required(required_message='new required message')
    assert required_field.required
    required = required_field.get_validation_constraint_named(RequiredConstraint.name)
    assert required.error_message.template == 'new required message'

    # Getting copy that's not required
    field.make_required('')
    assert field.required
    optional_field = field.as_optional()
    assert not optional_field.required

    # Getting copy with a ValidationConstraint of certain type removed
    assert field.required 
    more_lax_field = field.without_validation_constraint(RequiredConstraint)
    assert not more_lax_field.required 

    # Getting copy with a new ValidationConstraint added
    field.make_optional()
    assert not field.required 
    more_strict_field = field.with_validation_constraint(RequiredConstraint())
    assert more_strict_field.required 

    # Getting copy with a new label
    assert field.label != 'new label'
    differently_labelled_field = field.with_label('new label')
    assert differently_labelled_field.label == 'new label'
Example #26
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
Example #27
0
    def read_basic_object(self, fixture):
        fixture.reader.register(fixture.tag_name, fixture.test_class)
        parent = EmptyStub()
        read_object = fixture.reader.read_file(fixture.file, parent)

        vassert(isinstance(read_object, fixture.test_class))
        vassert(read_object.attr1 == fixture.string)
        vassert(read_object.attr2 == fixture.integer)
        vassert(read_object.parent is parent)
Example #28
0
    def tailored_access_make_inputs_security_sensitive(self, fixture):
        """An Input is sensitive if explicitly set as sensitive, or if its Fields has non-defaulted
           mechanisms for determiing access rights."""

        form = Form(fixture.view, 'some_form')
        field = Field(default=3, readable=Allowed(True))
        field.bind('field_name', EmptyStub())
        input_widget = TextInput(form, field)

        vassert(input_widget.is_security_sensitive)
Example #29
0
def test_read_basic_object(basic_object_setup):
    fixture = basic_object_setup
    fixture.reader.register(fixture.tag_name, fixture.test_class)
    parent = EmptyStub()
    read_object = fixture.reader.read_file(fixture.file, parent)

    assert isinstance(read_object, fixture.test_class)
    assert read_object.attr1 == fixture.string
    assert read_object.attr2 == fixture.integer
    assert read_object.parent is parent
Example #30
0
def test_schedule_executes_phases_with_parameters():
    """When a MigrationSchedule executes the calls that were scheduled from a Migration, 
       the methods are actually called, and passed the correct arguments."""

    class SomeObject:
        def please_call_me(self, arg, kwarg=None):
            pass
    some_object = SomeObject()
    
    migration_schedule = MigrationSchedule(EmptyStub(), EmptyStub(), [])
    migration = Migration(migration_schedule)

    with CallMonitor(some_object.please_call_me) as monitor:
        migration.schedule('alter', some_object.please_call_me, 'myarg', kwarg='mykwarg')

    migration_schedule.execute_all()

    assert monitor.calls[0].args == ('myarg',)
    assert monitor.calls[0].kwargs == dict(kwarg='mykwarg')