Ejemplo n.º 1
0
def test_notice_collection_used_issues(session):
    collection = GazetteNoticeCollection(session)

    issues = IssueCollection(session)
    a = issues.add(name='2017-1',
                   number=1,
                   date=date(2017, 1, 2),
                   deadline=standardize_date(datetime(2017, 1, 1, 12, 0),
                                             'UTC'))
    b = issues.add(name='2017-2',
                   number=2,
                   date=date(2017, 2, 2),
                   deadline=standardize_date(datetime(2017, 2, 1, 12, 0),
                                             'UTC'))
    c = issues.add(name='2017-3',
                   number=3,
                   date=date(2017, 3, 2),
                   deadline=standardize_date(datetime(2017, 3, 1, 12, 0),
                                             'UTC'))
    for issues in (('3', '2'), ('1', ), ('1', '3')):
        collection.add(title='',
                       text='',
                       organization_id='',
                       category_id='',
                       issues=[f'2017-{issue}' for issue in issues],
                       user=None)

    assert collection.used_issues == [a, b, c]
Ejemplo n.º 2
0
def test_overlaps():

    overlaps = [[
        datetime(2013, 1, 1, 12, 0),
        datetime(2013, 1, 1, 13, 0),
        datetime(2013, 1, 1, 12, 0),
        datetime(2013, 1, 1, 13, 0),
    ],
                [
                    datetime(2013, 1, 1, 11, 0),
                    datetime(2013, 1, 1, 12, 0),
                    datetime(2013, 1, 1, 12, 0),
                    datetime(2013, 1, 1, 13, 0),
                ]]

    doesnt = [[
        datetime(2013, 1, 1, 11, 0),
        datetime(2013, 1, 1, 11, 59, 59),
        datetime(2013, 1, 1, 12, 0),
        datetime(2013, 1, 1, 13, 0),
    ]]

    tz = 'Europe/Zurich'

    for dates in overlaps:
        assert sedate.overlaps(*dates)

        timezone_aware = [sedate.standardize_date(d, tz) for d in dates]
        assert sedate.overlaps(*timezone_aware)

    for dates in doesnt:
        assert not sedate.overlaps(*dates)

        timezone_aware = [sedate.standardize_date(d, tz) for d in dates]
        assert not sedate.overlaps(*timezone_aware)
Ejemplo n.º 3
0
    def _prepare_range(self, start, end):
        if start:
            start = sedate.standardize_date(start, self.timezone)
        if end:
            end = sedate.standardize_date(end, self.timezone)

        return start, end
Ejemplo n.º 4
0
def test_align_date_to_day_summertime():

    unaligned = sedate.standardize_date(datetime(2016, 3, 27, 1),
                                        'Europe/Zurich')
    aligned = sedate.align_date_to_day(unaligned, 'Europe/Zurich', 'down')

    assert aligned.isoformat() == '2016-03-26T23:00:00+00:00'

    unaligned = sedate.standardize_date(datetime(2016, 3, 27, 4),
                                        'Europe/Zurich')
    aligned = sedate.align_date_to_day(unaligned, 'Europe/Zurich', 'down')

    assert aligned.isoformat() == '2016-03-26T23:00:00+00:00'

    unaligned = sedate.standardize_date(datetime(2016, 3, 27, 1),
                                        'Europe/Zurich')
    aligned = sedate.align_date_to_day(unaligned, 'Europe/Zurich', 'up')

    assert aligned.isoformat() == '2016-03-27T21:59:59.999999+00:00'

    unaligned = sedate.standardize_date(datetime(2016, 3, 27, 4),
                                        'Europe/Zurich')
    aligned = sedate.align_date_to_day(unaligned, 'Europe/Zurich', 'up')

    assert aligned.isoformat() == '2016-03-27T21:59:59.999999+00:00'
Ejemplo n.º 5
0
def test_align_date_to_day_wintertime():

    unaligned = sedate.standardize_date(datetime(2016, 10, 30, 1),
                                        'Europe/Zurich')
    aligned = sedate.align_date_to_day(unaligned, 'Europe/Zurich', 'down')

    assert aligned.isoformat() == '2016-10-29T22:00:00+00:00'

    unaligned = sedate.standardize_date(datetime(2016, 10, 30, 4),
                                        'Europe/Zurich')
    aligned = sedate.align_date_to_day(unaligned, 'Europe/Zurich', 'down')

    assert aligned.isoformat() == '2016-10-29T22:00:00+00:00'

    unaligned = sedate.standardize_date(datetime(2016, 10, 30, 1),
                                        'Europe/Zurich')
    aligned = sedate.align_date_to_day(unaligned, 'Europe/Zurich', 'up')

    assert aligned.isoformat() == '2016-10-30T22:59:59.999999+00:00'

    unaligned = sedate.standardize_date(datetime(2016, 10, 30, 4),
                                        'Europe/Zurich')
    aligned = sedate.align_date_to_day(unaligned, 'Europe/Zurich', 'up')

    assert aligned.isoformat() == '2016-10-30T22:59:59.999999+00:00'
Ejemplo n.º 6
0
def test_notice_apply_meta(session, categories, organizations, issues):
    notice = GazetteNotice()

    notice.apply_meta(session)
    assert notice.organization is None
    assert notice.category is None
    assert notice.first_issue is None

    notice.organization_id = 'invalid'
    notice.category_id = 'invalid'
    notice.issues = [str(IssueName(2020, 1))]
    notice.apply_meta(session)
    assert notice.organization is None
    assert notice.category is None
    assert notice.first_issue is None

    notice.organization_id = '100'
    notice.category_id = '12'
    notice.issues = [str(IssueName(2017, 46))]
    notice.apply_meta(session)
    assert notice.organization == 'State Chancellery'
    assert notice.category == 'Submissions'
    assert notice.first_issue == standardize_date(datetime(2017, 11, 17),
                                                  'UTC')

    notice.issues = [str(IssueName(2017, 46)), str(IssueName(2017, 40))]
    notice.apply_meta(session)
    assert notice.first_issue == standardize_date(datetime(2017, 10, 6), 'UTC')
Ejemplo n.º 7
0
def test_issue_collection(session):
    collection = IssueCollection(session)

    issue_1 = collection.add(name='2017-1',
                             number=1,
                             date=date(2017, 1, 2),
                             deadline=standardize_date(
                                 datetime(2017, 1, 1, 12, 0), 'UTC'))
    issue_3 = collection.add(name='2017-3',
                             number=3,
                             date=date(2017, 3, 2),
                             deadline=standardize_date(
                                 datetime(2017, 3, 1, 12, 0), 'UTC'))
    issue_2 = collection.add(name='2017-2',
                             number=2,
                             date=date(2017, 2, 2),
                             deadline=standardize_date(
                                 datetime(2017, 2, 1, 12, 0), 'UTC'))
    issue_4 = collection.add(name='2018-1',
                             number=1,
                             date=date(2018, 1, 1),
                             deadline=standardize_date(
                                 datetime(2017, 12, 20, 12, 0), 'UTC'))

    # test query
    assert [issue.name for issue in collection.query()
            ] == ['2017-1', '2017-2', '2017-3', '2018-1']

    # test current issue
    with freeze_time("2017-01-01 11:00"):
        assert collection.current_issue == issue_1
    with freeze_time("2017-01-01 13:00"):
        assert collection.current_issue == issue_2
    with freeze_time("2017-02-10 13:00"):
        assert collection.current_issue == issue_3
    with freeze_time("2017-12-10 13:00"):
        assert collection.current_issue == issue_4
    with freeze_time("2018-04-10 13:00"):
        assert collection.current_issue is None

    # test by name
    assert collection.by_name('2017-1') == issue_1
    assert collection.by_name('2017-2') == issue_2
    assert collection.by_name('2017-3') == issue_3
    assert collection.by_name('2018-1') == issue_4
    assert collection.by_name('2018-2') is None

    # test years
    assert collection.years == [2017, 2018]
    assert collection.by_years() == OrderedDict((
        (2017, [issue_1, issue_2, issue_3]),
        (2018, [issue_4]),
    ))
    assert collection.by_years(desc=True) == OrderedDict((
        (2018, [issue_4]),
        (2017, [issue_3, issue_2, issue_1]),
    ))
Ejemplo n.º 8
0
def test_is_whole_day_summertime():

    start = sedate.standardize_date(datetime(2014, 10, 26, 0, 0, 0),
                                    'Europe/Zurich')

    end = sedate.standardize_date(datetime(2014, 10, 26, 23, 59, 59),
                                  'Europe/Zurich')

    assert sedate.is_whole_day(start, end, 'Europe/Zurich')
    assert not sedate.is_whole_day(start, end, 'Europe/Istanbul')
Ejemplo n.º 9
0
def test_is_whole_day_wintertime():

    start = sedate.standardize_date(datetime(2015, 3, 29, 0, 0, 0),
                                    'Europe/Zurich')

    end = sedate.standardize_date(datetime(2015, 3, 29, 23, 59, 59),
                                  'Europe/Zurich')

    assert sedate.is_whole_day(start, end, 'Europe/Zurich')
    assert not sedate.is_whole_day(start, end, 'Europe/Istanbul')
Ejemplo n.º 10
0
def test_issue(gazette_app, session):
    issue = Issue(
        id=0,
        name='2018-7',
        number=7,
        date=date(2017, 7, 1),
        deadline=standardize_date(datetime(2017, 6, 25, 12, 0), 'UTC'),
    )
    issue.pdf = 'PDF'.encode('utf-8')
    session.add(issue)
    session.flush()
    issue = session.query(Issue).one()

    assert issue.id == 0
    assert issue.name == '2018-7'
    assert issue.number == 7
    assert issue.date == date(2017, 7, 1)
    assert issue.deadline == standardize_date(datetime(2017, 6, 25, 12, 0),
                                              'UTC')
    assert issue.pdf.id
    assert issue.pdf.name == '2018-7.pdf'
    assert issue.pdf.type == 'gazette_issue'
    assert issue.pdf.reference.file.read().decode('utf-8') == 'PDF'

    # Test query etc
    assert len(issue.notices().all()) == 0
    assert issue.notices('accepted').all() == []
    assert issue.notices('submitted').all() == []
    assert issue.in_use is False

    issues = [issue.name]
    session.add(GazetteNotice(title='d', issues=issues))
    session.add(GazetteNotice(title='a', state='accepted', issues=issues))
    session.add(GazetteNotice(title='s', state='submitted', issues=issues))
    session.add(GazetteNotice(title='s', issues=['2018-1']))
    session.add(GazetteNotice(title='s', issues=['2018-1', issue.name]))
    session.flush()

    assert len(issue.notices().all()) == 4
    assert issue.notices('accepted').all()[0].title == 'a'
    assert issue.notices('submitted').one().title == 's'
    assert issue.in_use is True

    # Test date observer
    issue.date = date(2018, 7, 2)
    session.flush()
    dates = [i.first_issue for i in session.query(GazetteNotice)]
    dates = [d.date() for d in dates if d]
    assert set(dates) == set([issue.date])

    # Test publish
    issue.publish(DummyRequest(session))
    assert len(issue.notices().all()) == 4
    assert issue.notices('accepted').all() == []
    assert issue.notices('published').count() == 1
Ejemplo n.º 11
0
def is_valid_reservation_length(start, end, timezone):
    start = sedate.standardize_date(start, timezone)
    end = sedate.standardize_date(end, timezone)

    hours = (end - start).total_seconds() // 3600

    if hours < 24:
        return True

    if sedate.is_whole_day(start, end, timezone) and hours <= 25:
        return True

    return False
Ejemplo n.º 12
0
def test_align_date_to_day_up():
    unaligned = sedate.standardize_date(datetime(2012, 1, 24, 10), 'UTC')
    aligned = sedate.align_date_to_day(unaligned, 'Europe/Zurich', 'up')

    assert aligned.tzname() == 'UTC'
    assert aligned == sedate.standardize_date(
        datetime(2012, 1, 24, 23, 59, 59, 999999), 'Europe/Zurich')

    already_aligned = sedate.replace_timezone(
        datetime(2012, 1, 1, 23, 59, 59, 999999), 'Europe/Zurich')

    assert already_aligned == sedate.align_date_to_day(already_aligned,
                                                       'Europe/Zurich', 'up')
Ejemplo n.º 13
0
def test_layout_format(session, principal):
    request = DummyRequest(session, principal)
    layout = Layout(None, request)

    # Date
    assert layout.principal.time_zone == 'Europe/Zurich'
    assert layout.format_date(date(2019, 1, 2), 'date') == '02.01.2019'
    assert layout.format_date(datetime(2019, 1, 2, 12), 'date') == '02.01.2019'
    assert layout.format_date(datetime(2019, 1, 2, 12), 'date_long') == \
        '2. Januar 2019'
    assert layout.format_date(datetime(2019, 1, 2, 12), 'datetime') == \
        '02.01.2019 12:00'
    assert layout.format_date(
        standardize_date(datetime(2019, 1, 2, 12, 0), 'UTC'),
        'date') == '02.01.2019'
    assert layout.format_date(
        standardize_date(datetime(2019, 1, 2, 12, 0), 'UTC'),
        'datetime') == '02.01.2019 13:00'

    # Issue
    with raises(AssertionError):
        layout.format_issue(None)
    with raises(AssertionError):
        layout.format_issue('')

    assert layout.format_issue(Issue()) == 'No. , '

    assert layout.format_issue(Issue(number=1,
                                     date=date(2017, 1,
                                               2))) == 'No. 1, 02.01.2017'
    assert layout.format_issue(
        Issue(number=1, date=date(2017, 1, 2)),
        date_format='date_with_weekday') == 'No. 1, Montag 02.01.2017'
    assert layout.format_issue(Issue(name='2017-1',
                                     number=1,
                                     date=date(2017, 1, 2)),
                               notice=GazetteNotice()) == 'No. 1, 02.01.2017'
    assert layout.format_issue(
        Issue(name='2017-1', number=1, date=date(2017, 1, 2)),
        notice=GazetteNotice(issues=['2017-1'])) == 'No. 1, 02.01.2017'
    assert layout.format_issue(
        Issue(name='2017-1', number=1, date=date(2017, 1, 2)),
        notice=GazetteNotice(
            _issues={'2017-1': 10})) == 'No. 1, 02.01.2017 / 10'

    # Text
    assert layout.format_text(None) == ''
    assert layout.format_text('abc') == 'abc'
    assert layout.format_text('a\nb\r\nc') == 'a<br>b<br>c'
Ejemplo n.º 14
0
    def apply_meta(self, session):
        """ Updates the category, organization and issue date from the meta
        values.

        """
        self.organization = None
        query = session.query(Organization.title)
        query = query.filter(Organization.name == self.organization_id).first()
        if query:
            self.organization = query[0]

        self.category = None
        query = session.query(Category.title)
        query = query.filter(Category.name == self.category_id).first()
        if query:
            self.category = query[0]

        self.first_issue = None
        if self._issues:
            query = session.query(Issue.date)
            query = query.filter(Issue.name.in_(self._issues.keys()))
            query = query.order_by(Issue.date).first()
            if query:
                self.first_issue = standardize_date(as_datetime(query[0]),
                                                    'UTC')
Ejemplo n.º 15
0
def migrate_issues(context):
    principal = getattr(context.app, 'principal', None)
    if not principal:
        return False

    issues = getattr(principal, '_issues', None)
    if not issues:
        return False

    if not context.has_table('gazette_issues'):
        return False

    session = context.app.session_manager.session()
    count = session.execute("select count(*) from gazette_issues")
    if count.scalar() != 0:
        return False

    collection = IssueCollection(session)
    for year, values in issues.items():
        for number, dates in values.items():
            assert dates.issue_date.year == year
            collection.add(name='{}-{}'.format(year, number),
                           number=number,
                           date=dates.issue_date,
                           deadline=standardize_date(dates.deadline, 'UTC'))
Ejemplo n.º 16
0
def test_notice_collection(session, organizations, categories, issues):
    user = UserCollection(session).add(username='******',
                                       password='******',
                                       role='admin')

    collection = GazetteNoticeCollection(session)
    collection.add(title='Notice A',
                   text='An <strong>important</strong> Notice!',
                   organization_id='100',
                   category_id='11',
                   issues=['2017-46', '2017-47'],
                   user=user)
    collection.add(title='Notice B',
                   text='Another Notice',
                   organization_id='200',
                   category_id='13',
                   issues={'2017-47', '2017-48'},
                   user=user)

    notice = collection.for_term('Notice A').query().one()
    assert notice.title == 'Notice A'
    assert notice.text == 'An <strong>important</strong> Notice!'
    assert notice.organization_id == '100'
    assert notice.organization == 'State Chancellery'
    assert notice.category_id == '11'
    assert notice.category == 'Education'
    assert notice.issues == {'2017-46': None, '2017-47': None}
    assert notice.first_issue == standardize_date(datetime(2017, 11, 17),
                                                  'UTC')
    assert notice.user == user
    assert notice.changes.one().event == 'created'
    assert notice.changes.one().user == user

    notice = collection.for_term('Notice B').query().one()
    assert notice.title == 'Notice B'
    assert notice.text == 'Another Notice'
    assert notice.organization_id == '200'
    assert notice.organization == 'Civic Community'
    assert notice.category_id == '13'
    assert notice.category == 'Commercial Register'
    assert notice.issues == {'2017-47': None, '2017-48': None}
    assert notice.first_issue == standardize_date(datetime(2017, 11, 24),
                                                  'UTC')
    assert notice.user == user
    assert notice.changes.one().event == 'created'
    assert notice.changes.one().user == user
Ejemplo n.º 17
0
def test_standardize_aware_date():
    aware_date = sedate.replace_timezone(datetime(2014, 10, 1, 13, 30),
                                         'Europe/Zurich')

    normalized = sedate.standardize_date(aware_date, 'Europe/Zurich')

    assert normalized.tzname() == 'UTC'
    assert normalized.replace(tzinfo=None) == datetime(2014, 10, 1, 11, 30)
Ejemplo n.º 18
0
 def update_model(self, model):
     model.number = self.number.data
     model.date = self.date_.data
     model.deadline = self.deadline.data
     model.name = str(IssueName(model.date.year, model.number))
     # Convert the deadline from the local timezone to UTC
     if model.deadline:
         model.deadline = standardize_date(model.deadline,
                                           self.timezone.data)
Ejemplo n.º 19
0
    def parsed_dates(self):
        result = []

        DateRange = namedtuple('DateRange', ['start', 'end'])

        for date in json.loads(self.dates.data or '{}').get('values', []):
            try:
                start = isodate.parse_datetime(date['start'].replace(' ', 'T'))
                end = isodate.parse_datetime(date['end'].replace(' ', 'T'))
            except isodate.isoerror.ISO8601Error:
                continue

            result.append(DateRange(
                start=standardize_date(start, self.timezone),
                end=standardize_date(end, self.timezone)
            ))

        return result
Ejemplo n.º 20
0
    def events(self, request):
        session = request.session
        stmt = self.attendee_calendar

        records = session.execute(
            select(stmt.c).where(
                and_(stmt.c.attendee_id == self.attendee_id,
                     stmt.c.state == 'accepted', stmt.c.confirmed == True)))

        datestamp = utcnow()

        for record in records:
            event = icalendar.Event()

            event.add('uid', record.uid)
            event.add('summary', record.title)

            if record.note:
                event.add('description', record.note)

            event.add('dtstart', standardize_date(record.start, 'UTC'))
            event.add('dtend', standardize_date(record.end, 'UTC'))
            event.add('dtstamp', datestamp)
            event.add(
                'url',
                request.class_link(VacationActivity, {'name': record.name}))

            if record.meeting_point:
                event.add('location', record.meeting_point)

            if record.lat and record.lon:
                event.add('geo', (float(record.lat), float(record.lon)))

            if record.meeting_point and record.lat and record.lon:
                event.add("X-APPLE-STRUCTURED-LOCATION",
                          f"geo:{record.lat},{record.lon}",
                          parameters={
                              "VALUE": "URI",
                              "X-ADDRESS": record.meeting_point,
                              "X-APPLE-RADIUS": "50",
                              "X-TITLE": record.meeting_point
                          })

            yield event
Ejemplo n.º 21
0
    def _import_issues(request, app):
        if not app.principal:
            return

        request.locale = locale
        headers = {
            'number': request.translate(_("Number")),
            'date': request.translate(_("Date")),
            'deadline': request.translate(_("Deadline"))
        }

        session = app.session()
        issues = IssueCollection(session)

        if clear:
            click.secho("Deleting issues", fg='yellow')
            for category in issues.query():
                session.delete(category)

        csvfile = convert_xls_to_csv(
            file, sheet_name=request.translate(_("Issues"))
        )
        csv = CSVFile(csvfile, expected_headers=headers.values())
        lines = list(csv.lines)
        columns = {
            key: csv.as_valid_identifier(value)
            for key, value in headers.items()
        }

        count = 0
        for line in lines:
            count += 1
            number = int(getattr(line, columns['number']))
            date_ = parser.parse(getattr(line, columns['date'])).date()
            deadline = standardize_date(
                parser.parse(getattr(line, columns['deadline'])),
                timezone or request.app.principal.time_zone
            )
            name = str(IssueName(date_.year, number))

            issues.add(
                name=name,
                number=number,
                date=date_,
                deadline=deadline
            )

        click.secho(f"{count} categorie(s) imported", fg='green')

        if dry_run:
            transaction.abort()
            click.secho("Aborting transaction", fg='yellow')
Ejemplo n.º 22
0
def test_group_reservation_timespans(scheduler):
    dates = [
        (datetime(2015, 2, 5, 15), datetime(2015, 2, 5, 16)),
        (datetime(2015, 2, 6, 15), datetime(2015, 2, 6, 16))
    ]

    group = scheduler.allocate(dates=dates, grouped=True)[0].group
    token = scheduler.reserve('*****@*****.**', group=group)
    scheduler.commit()

    reservation = scheduler.reservations_by_token(token)[0]

    timespans = reservation.timespans()
    assert len(timespans) == 2

    assert timespans[0].start == standardize_date(dates[0][0], 'Europe/Zurich')
    assert timespans[0].end == standardize_date(dates[0][1], 'Europe/Zurich')\
        - timedelta(microseconds=1)

    assert timespans[1].start == standardize_date(dates[1][0], 'Europe/Zurich')
    assert timespans[1].end == standardize_date(dates[1][1], 'Europe/Zurich')\
        - timedelta(microseconds=1)
Ejemplo n.º 23
0
    def get_publication(self, identifier):
        """ Fetches a single publication and adds it as an official notice.

        """
        session = self.session

        response = get(f'{self.endpoint}/publications/{identifier}/xml')
        response.raise_for_status()
        response.encoding = 'utf-8'

        root = etree.fromstring(response.text.encode('utf-8'))
        subrubric = root.find('meta/subRubric').text
        converter = self.converters[subrubric](root)

        name = get_unique_notice_name(converter.title, session, GazetteNotice)
        author_date = converter.publication_date or None
        if author_date:
            author_date = standardize_date(author_date, 'UTC')
        expiry_date = converter.expiration_date or None
        if expiry_date:
            expiry_date = standardize_date(expiry_date, 'UTC')

        notice = GazetteNotice(id=uuid4(),
                               name=name,
                               state='imported',
                               source=converter.source,
                               title=converter.title,
                               text=converter.text,
                               organization_id=self.organization,
                               category_id=self.category,
                               issues=converter.issues(session),
                               author_date=author_date,
                               expiry_date=expiry_date)
        notice.apply_meta(session)
        session.add(notice)
        session.flush()

        MessageCollection(session, type='gazette_notice').add(
            channel_id=str(notice.id), meta={'event': _("imported")})
Ejemplo n.º 24
0
def test_event_collection_remove_stale_events(session):
    timezone = 'UTC'

    events = EventCollection(session)
    events.add(
        title='Event', timezone=timezone,
        start=datetime(2010, 6, 1, 10),
        end=datetime(2010, 6, 1, 10) + timedelta(hours=1),
    )
    assert events.query().count() == 1

    max_stale = standardize_date(datetime.today() + timedelta(days=2), 'UTC')
    events.remove_stale_events(max_stale=max_stale)
    assert events.query().count() == 0
Ejemplo n.º 25
0
    def occurrence_dates(self, limit=True, localize=False):
        """ Returns the start dates of all occurrences.

        Returns non-localized dates per default. Limits the occurrences per
        default to this and the next year.
        """

        occurrences = [self.start]
        if self.recurrence:
            occurrences = rrule.rrulestr(self.recurrence, dtstart=self.start)
            occurrences = list(map(lambda x: standardize_date(x, self.timezone), occurrences))
            if localize:
                occurrences = list(map(lambda x: to_timezone(x, self.timezone), occurrences))
            if limit:
                max_year = datetime.today().year + 1
                occurrences = list(filter(lambda x: x.year <= max_year, occurrences))
        return occurrences
Ejemplo n.º 26
0
    def date_observer(self, date_):
        """ Changes the issue date of the notices when updating the date
        of the issue.

        At this moment, the transaction is not yet commited: Querying the
        current issue returns the old date.

        """

        issues = object_session(self).query(Issue.name, Issue.date)
        issues = dict(issues.order_by(Issue.date))
        issues[self.name] = date_
        issues = {
            key: standardize_date(as_datetime(value), 'UTC')
            for key, value in issues.items()
        }

        for notice in self.notices():
            dates = [issues.get(issue, None) for issue in notice._issues]
            dates = [date for date in dates if date]
            notice.first_issue = min(dates)
Ejemplo n.º 27
0
    def remove_stale_events(self, max_stale=None):
        """ Remove events which have never been submitted and are created more
        than five days ago.

        """

        if max_stale is None:
            max_stale = datetime.utcnow() - timedelta(days=5)
            max_stale = standardize_date(max_stale, 'UTC')

        events = self.session.query(Event).filter(
            Event.state == 'initiated',
            and_(
                or_(Event.created < max_stale, Event.created.is_(None)),
                or_(Event.modified < max_stale, Event.modified.is_(None))
            )
        )
        for event in events:
            self.session.delete(event)

        self.session.flush()
Ejemplo n.º 28
0
    def query(self, start=None, end=None, tags=None, outdated=False):
        """ Queries occurrences with the given parameters.

        Finds all occurrences with any of the given tags and within the given
        start and end date. Start and end date are assumed to be dates only and
        therefore without a timezone - we search for the given date in the
        timezone of the occurrence!.

        If no start date is given and ``outdated`` is not set, only current
        occurrences are returned.
        """

        query = self.session.query(Occurrence)

        if start is not None:
            assert type(start) is date
            start = as_datetime(start)

            expressions = []
            for timezone in self.used_timezones:
                localized_start = replace_timezone(start, timezone)
                localized_start = standardize_date(localized_start, timezone)
                expressions.append(
                    and_(
                        Occurrence.timezone == timezone,
                        Occurrence.start >= localized_start
                    )
                )

            query = query.filter(or_(*expressions))
        elif not outdated:
            start = as_datetime(date.today())

            expressions = []
            for timezone in self.used_timezones:
                localized_start = replace_timezone(start, timezone)
                localized_start = standardize_date(localized_start, timezone)
                expressions.append(
                    and_(
                        Occurrence.timezone == timezone,
                        Occurrence.start >= localized_start
                    )
                )

            query = query.filter(or_(*expressions))

        if end is not None:
            assert type(end) is date
            end = as_datetime(end)
            end = end + timedelta(days=1)

            expressions = []
            for timezone in self.used_timezones:
                localized_end = replace_timezone(end, timezone)
                localized_end = standardize_date(localized_end, timezone)
                expressions.append(
                    and_(
                        Occurrence.timezone == timezone,
                        Occurrence.end < localized_end
                    )
                )

            query = query.filter(or_(*expressions))

        if tags:
            query = query.filter(Occurrence._tags.has_any(array(tags)))

        query = query.order_by(Occurrence.start, Occurrence.title)

        return query
Ejemplo n.º 29
0
def create_issues(session):
    issues = IssueCollection(session)
    issues.add(name='2017-40',
               number=40,
               date=date(2017, 10, 6),
               deadline=standardize_date(datetime(2017, 10, 4, 12, 0), 'UTC'))
    issues.add(name='2017-41',
               number=41,
               date=date(2017, 10, 13),
               deadline=standardize_date(datetime(2017, 10, 11, 12, 0), 'UTC'))
    issues.add(name='2017-42',
               number=42,
               date=date(2017, 10, 20),
               deadline=standardize_date(datetime(2017, 10, 18, 12, 0), 'UTC'))
    issues.add(name='2017-43',
               number=43,
               date=date(2017, 10, 27),
               deadline=standardize_date(datetime(2017, 10, 25, 12, 0), 'UTC'))
    issues.add(name='2017-44',
               number=44,
               date=date(2017, 11, 3),
               deadline=standardize_date(datetime(2017, 11, 1, 12, 0), 'UTC'))
    issues.add(name='2017-45',
               number=45,
               date=date(2017, 11, 10),
               deadline=standardize_date(datetime(2017, 11, 8, 12, 0), 'UTC'))
    issues.add(name='2017-46',
               number=46,
               date=date(2017, 11, 17),
               deadline=standardize_date(datetime(2017, 11, 15, 12, 0), 'UTC'))
    issues.add(name='2017-47',
               number=47,
               date=date(2017, 11, 24),
               deadline=standardize_date(datetime(2017, 11, 22, 12, 0), 'UTC'))
    issues.add(name='2017-48',
               number=48,
               date=date(2017, 12, 1),
               deadline=standardize_date(datetime(2017, 11, 29, 12, 0), 'UTC'))
    issues.add(name='2017-49',
               number=49,
               date=date(2017, 12, 8),
               deadline=standardize_date(datetime(2017, 12, 6, 12, 0), 'UTC'))
    issues.add(name='2017-50',
               number=50,
               date=date(2017, 12, 15),
               deadline=standardize_date(datetime(2017, 12, 13, 12, 0), 'UTC'))
    issues.add(name='2017-51',
               number=51,
               date=date(2017, 12, 22),
               deadline=standardize_date(datetime(2017, 12, 20, 12, 0), 'UTC'))
    issues.add(name='2017-52',
               number=52,
               date=date(2017, 12, 29),
               deadline=standardize_date(datetime(2017, 12, 27, 12, 0), 'UTC'))
    issues.add(name='2018-1',
               number=1,
               date=date(2018, 1, 5),
               deadline=standardize_date(datetime(2018, 1, 3, 12, 0), 'UTC'))
    return issues.query().all()
Ejemplo n.º 30
0
 def author_date_utc(self):
     if self.author_date.data:
         return standardize_date(as_datetime(self.author_date.data), 'UTC')
     return None
Ejemplo n.º 31
0
def test_issue_form(session):
    request = DummyRequest(session, DummyPrincipal())

    # Test apply / update
    # ... unused
    issues = IssueCollection(session)
    issue = issues.add(name='2018-1',
                       number=1,
                       date=date(2018, 1, 5),
                       deadline=standardize_date(datetime(2018, 1, 4, 12, 0),
                                                 'UTC'))

    form = IssueForm()
    form.request = request
    form.on_request()

    form.apply_model(issue)
    assert form.number.data == 1
    assert form.name.data == '2018-1'
    assert form.date_.data == date(2018, 1, 5)
    assert form.deadline.data == datetime(2018, 1, 4, 13, 0)

    form.number.data = 2
    form.date_.data = date(2019, 1, 5)
    form.deadline.data = datetime(2019, 1, 4, 13, 0)
    form.update_model(issue)
    assert issue.number == 2
    assert issue.name == '2019-2'
    assert issue.date == date(2019, 1, 5)
    assert issue.deadline == standardize_date(datetime(2019, 1, 4, 12, 0),
                                              'UTC')

    # used
    issue = issues.add(name='2019-3',
                       number=3,
                       date=date(2019, 2, 5),
                       deadline=standardize_date(datetime(2019, 2, 4, 12, 0),
                                                 'UTC'))
    notices = GazetteNoticeCollection(session)
    notices.add('title', 'text', '', '', None, ['2019-3'])

    form.apply_model(issue)
    assert form.number.render_kw == {'readonly': True}

    # Test validation
    # ... empty values
    form = IssueForm()
    form.request = request
    assert not form.validate()

    # ... new model
    form = IssueForm(
        DummyPostData({
            'number': '3',
            'date_': '2019-03-05',
            'deadline': '2019-03-04T12:00'
        }))
    form.request = request
    assert not form.validate()
    assert 'This value already exists.' in form.errors['name']

    form = IssueForm(
        DummyPostData({
            'number': '5',
            'date_': '2019-03-05',
            'deadline': '2019-03-04T12:00'
        }))
    form.request = request
    assert form.validate()

    form = IssueForm(
        DummyPostData({
            'number': '3',
            'date_': '2018-03-05',
            'deadline': '2019-03-04T12:00'
        }))
    form.request = request
    assert form.validate()

    # ... existing model
    form = IssueForm(
        DummyPostData({
            'number': '2',
            'date_': '2019-03-05',
            'deadline': '2019-03-04T12:00'
        }))
    form.model = issues.query().filter_by(number='3').one()
    form.request = request
    assert not form.validate()
    assert 'This value already exists.' in form.errors['name']
    assert 'This value is in use.' in form.errors['name']

    form = IssueForm(
        DummyPostData({
            'number': '5',
            'date_': '2019-03-05',
            'deadline': '2019-03-04T12:00'
        }))
    form.model = issues.query().filter_by(number='2').one()
    form.request = request
    assert form.validate()

    # Datetimepicker forma
    form = IssueForm(
        DummyPostData({
            'number': '1',
            'date_': '2020-01-01',
            'deadline': '2011-01-01 12:00'
        }))
    form.request = request
    assert form.validate()
Ejemplo n.º 32
0
def test_notice_form(session, categories, organizations, issues):
    users = UserCollection(session)
    user = users.add(
        username='******',
        realname='User',
        role='editor',
        password='******',
    )
    user.phone_number = '+41415554433'

    notice = GazetteNotice(
        title='Title',
        text='A <b>text</b>.',
        author_place='Govikon',
        author_name='State Chancellerist',
        author_date=standardize_date(datetime(2018, 1, 1), 'UTC'),
    )
    notice.organization_id = '200'
    notice.category_id = '13'
    notice.issues = ['2017-43']
    notice.user = user

    # Test apply / update
    form = NoticeForm()
    form.request = DummyRequest(session)

    form.apply_model(notice)
    assert form.title.data == 'Title'
    assert form.organization.data == '200'
    assert form.category.data == '13'
    assert form.print_only.data is False
    assert form.at_cost.data == 'no'
    assert form.billing_address.data == ''
    assert form.text.data == 'A <b>text</b>.'
    assert form.author_place.data == 'Govikon'
    assert form.author_name.data == 'State Chancellerist'
    assert form.author_date.data == standardize_date(datetime(2018, 1, 1),
                                                     'UTC')
    assert form.issues.data == ['2017-43']
    assert form.phone_number.data == '+41415554433'

    form.title.data = 'Notice'
    form.organization.data = '300'
    form.category.data = '11'
    form.print_only.data = True
    form.at_cost.data = 'yes'
    form.billing_address.data = 'someone\nsomewhere'
    form.text.data = 'A <b>notice</b>.'
    form.author_place.data = 'Govtown'
    form.author_name.data = 'Bureau of Public Affairs'
    form.author_date.data = standardize_date(datetime(2019, 1, 1), 'UTC')
    form.issues.data = ['2017-44']
    form.phone_number.data = '796662211'

    form.update_model(notice)
    assert notice.title == 'Notice'
    assert notice.organization == 'Municipality'
    assert notice.category == 'Education'
    assert notice.print_only is True
    assert notice.at_cost is True
    assert notice.billing_address == 'someone\nsomewhere'
    assert notice.text == 'A <b>notice</b>.'
    assert notice.author_place == 'Govtown'
    assert notice.author_name == 'Bureau of Public Affairs'
    assert notice.author_date == standardize_date(datetime(2019, 1, 1), 'UTC')
    assert notice.issues == {'2017-44': None}
    assert notice.first_issue == standardize_date(datetime(2017, 11, 3), 'UTC')
    assert user.phone_number == '+41796662211'

    # Test validation
    form = NoticeForm()
    form.request = DummyRequest(session)
    assert not form.validate()

    form = NoticeForm()
    form.request = DummyRequest(session)
    form.issues.choices = [('2017-5', '2017-5')]
    form.organization.choices = [('onegov', 'onegov')]
    form.category.choices = [('important', 'important')]
    form.process(
        DummyPostData({
            'title': 'Title',
            'organization': 'onegov',
            'category': 'important',
            'issues': ['2017-5'],
            'text': 'Text',
            'author_place': 'Govtown',
            'author_name': 'Bureau of Public Affairs',
            'author_date': '2019-01-01'
        }))
    assert form.validate()

    # Test UTC conversion
    assert form.author_date.data == date(2019, 1, 1)
    assert form.author_date_utc == standardize_date(datetime(2019, 1, 1),
                                                    'UTC')
    assert NoticeForm().author_date_utc is None

    # Test on request
    with freeze_time("2017-11-01 14:00"):
        form = NoticeForm()
        form.model = None
        form.request = DummyRequest(session)
        form.on_request()
        assert form.organization.choices == [('', 'Select one'),
                                             ('100', 'State Chancellery'),
                                             ('200', 'Civic Community'),
                                             ('300', 'Municipality'),
                                             ('410',
                                              'Evangelical Reformed Parish'),
                                             ('430', 'Catholic Parish'),
                                             ('500', 'Corporation')]
        assert form.issues.choices == [
            ('2017-45', 'No. 45, Freitag 10.11.2017'),
            ('2017-46', 'No. 46, Freitag 17.11.2017'),
            ('2017-47', 'No. 47, Freitag 24.11.2017'),
            ('2017-48', 'No. 48, Freitag 01.12.2017'),
            ('2017-49', 'No. 49, Freitag 08.12.2017'),
            ('2017-50', 'No. 50, Freitag 15.12.2017'),
            ('2017-51', 'No. 51, Freitag 22.12.2017'),
            ('2017-52', 'No. 52, Freitag 29.12.2017'),
            ('2018-1', 'No. 1, Freitag 05.01.2018'),
        ]
        assert form.category.choices == [
            ('13', 'Commercial Register'),
            ('11', 'Education'),
            ('14', 'Elections'),
            ('12', 'Submissions'),
        ]
        assert form.print_only is None

        form = NoticeForm()
        form.model = None
        form.request = DummyRequest(session, private=True)
        form.on_request()
        assert form.organization.choices == [('', 'Select one'),
                                             ('100', 'State Chancellery'),
                                             ('200', 'Civic Community'),
                                             ('300', 'Municipality'),
                                             ('410',
                                              'Evangelical Reformed Parish'),
                                             ('430', 'Catholic Parish'),
                                             ('500', 'Corporation')]
        assert form.issues.choices == [
            ('2017-44', 'No. 44, Freitag 03.11.2017'),
            ('2017-45', 'No. 45, Freitag 10.11.2017'),
            ('2017-46', 'No. 46, Freitag 17.11.2017'),
            ('2017-47', 'No. 47, Freitag 24.11.2017'),
            ('2017-48', 'No. 48, Freitag 01.12.2017'),
            ('2017-49', 'No. 49, Freitag 08.12.2017'),
            ('2017-50', 'No. 50, Freitag 15.12.2017'),
            ('2017-51', 'No. 51, Freitag 22.12.2017'),
            ('2017-52', 'No. 52, Freitag 29.12.2017'),
            ('2018-1', 'No. 1, Freitag 05.01.2018'),
        ]
        assert form.category.choices == [
            ('13', 'Commercial Register'),
            ('11', 'Education'),
            ('14', 'Elections'),
            ('12', 'Submissions'),
        ]
        assert form.issues.render_kw['data-hot-issue'] == '2017-44'
        assert form.print_only is not None
Ejemplo n.º 33
0
def test_unrestricted_notice_form(session, categories, organizations, issues):
    users = UserCollection(session)
    user = users.add(
        username='******',
        realname='User',
        role='editor',
        password='******',
    )
    user.phone_number = '+41415554433'

    notice = GazetteNotice(title='Title', text='A <b>text</b>.')
    notice.organization_id = '200'
    notice.category_id = '13'
    notice.note = 'note'
    notice.issues = ['2017-43']
    notice.user = user

    # Test apply / update
    form = UnrestrictedNoticeForm()
    form.request = DummyRequest(session)

    form.apply_model(notice)
    assert form.title.data == 'Title'
    assert form.organization.data == '200'
    assert form.category.data == '13'
    assert form.text.data == 'A <b>text</b>.'
    assert form.issues.data == ['2017-43']
    assert form.phone_number.data == '+41415554433'
    assert form.note.data == 'note'

    form.title.data = 'Notice'
    form.organization.data = '300'
    form.category.data = '11'
    form.text.data = 'A <b>notice</b>.'
    form.issues.data = ['2017-44']
    form.phone_number.data = '796662211'
    form.note.data = 'A note'

    form.update_model(notice)
    assert notice.title == 'Notice'
    assert notice.organization == 'Municipality'
    assert notice.category == 'Education'
    assert notice.text == 'A <b>notice</b>.'
    assert notice.issues == {'2017-44': None}
    assert notice.first_issue == standardize_date(datetime(2017, 11, 3), 'UTC')
    assert notice.note == 'A note'
    assert user.phone_number == '+41796662211'

    notice.state = 'published'
    form.issues.data = ['2017-45']
    form.update_model(notice)
    assert notice.issues == {'2017-44': None}

    # Test on request
    with freeze_time("2019-11-01 14:00"):
        form = UnrestrictedNoticeForm()
        form.model = None
        form.request = DummyRequest(session)
        form.on_request()
        assert form.organization.choices == [('', 'Select one'),
                                             ('100', 'State Chancellery'),
                                             ('200', 'Civic Community'),
                                             ('300', 'Municipality'),
                                             ('410',
                                              'Evangelical Reformed Parish'),
                                             ('420', '(Sikh Community)'),
                                             ('430', 'Catholic Parish'),
                                             ('500', 'Corporation')]
        assert form.issues.choices == [
            ('2017-40', 'No. 40, Freitag 06.10.2017'),
            ('2017-41', 'No. 41, Freitag 13.10.2017'),
            ('2017-42', 'No. 42, Freitag 20.10.2017'),
            ('2017-43', 'No. 43, Freitag 27.10.2017'),
            ('2017-44', 'No. 44, Freitag 03.11.2017'),
            ('2017-45', 'No. 45, Freitag 10.11.2017'),
            ('2017-46', 'No. 46, Freitag 17.11.2017'),
            ('2017-47', 'No. 47, Freitag 24.11.2017'),
            ('2017-48', 'No. 48, Freitag 01.12.2017'),
            ('2017-49', 'No. 49, Freitag 08.12.2017'),
            ('2017-50', 'No. 50, Freitag 15.12.2017'),
            ('2017-51', 'No. 51, Freitag 22.12.2017'),
            ('2017-52', 'No. 52, Freitag 29.12.2017'),
            ('2018-1', 'No. 1, Freitag 05.01.2018')
        ]
        assert form.category.choices == [
            ('13', 'Commercial Register'),
            ('10', '(Complaints)'),
            ('11', 'Education'),
            ('14', 'Elections'),
            ('12', 'Submissions'),
        ]

    # Test disable issues
    form = UnrestrictedNoticeForm()
    form.model = None
    form.request = DummyRequest(session)
    form.on_request()
    form.disable_issues()
    assert form.issues.validators == []
    assert all([field.render_kw['disabled'] for field in form.issues])
Ejemplo n.º 34
0
def test_standardize_naive_date():
    naive_date = datetime(2014, 10, 1, 13, 30)
    normalized = sedate.standardize_date(naive_date, 'Europe/Zurich')

    assert normalized.tzname() == 'UTC'
    assert normalized.replace(tzinfo=None) == datetime(2014, 10, 1, 11, 30)