Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-python-crontab for
openSUSE:Factory checked in at 2026-01-07 16:02:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-python-crontab (Old)
and /work/SRC/openSUSE:Factory/.python-python-crontab.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-python-crontab"
Wed Jan 7 16:02:09 2026 rev:11 rq:1325693 version:3.3.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-python-crontab/python-python-crontab.changes
2025-02-18 19:13:48.000277792 +0100
+++
/work/SRC/openSUSE:Factory/.python-python-crontab.new.1928/python-python-crontab.changes
2026-01-07 16:02:57.114956093 +0100
@@ -1,0 +2,6 @@
+Wed Jan 7 04:23:09 UTC 2026 - Steve Kowalik <[email protected]>
+
+- Update to 3.3.0:
+ * Move specials setting to global.
+
+-------------------------------------------------------------------
Old:
----
python_crontab-3.2.0.tar.gz
New:
----
python_crontab-3.3.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-python-crontab.spec ++++++
--- /var/tmp/diff_new_pack.hGKOF1/_old 2026-01-07 16:02:58.595017695 +0100
+++ /var/tmp/diff_new_pack.hGKOF1/_new 2026-01-07 16:02:58.619018694 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-python-crontab
#
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,18 +18,17 @@
%{?sle15_python_module_pythons}
Name: python-python-crontab
-Version: 3.2.0
+Version: 3.3.0
Release: 0
Summary: Python Crontab API
License: LGPL-3.0-only
-Group: Development/Languages/Python
URL: https://gitlab.com/doctormo/python-crontab/
Source:
https://files.pythonhosted.org/packages/source/p/python_crontab/python_crontab-%{version}.tar.gz
BuildRequires: %{python_module pip}
+BuildRequires: %{python_module setuptools}
BuildRequires: %{python_module wheel}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
-Requires: python-python-dateutil
Recommends: cronie
Recommends: python-cron-descriptor
Recommends: python-croniter
@@ -38,8 +37,7 @@
BuildRequires: %{python_module cron-descriptor}
BuildRequires: %{python_module croniter}
BuildRequires: %{python_module pytest}
-BuildRequires: %{python_module python-dateutil}
-BuildRequires: %{python_module testsuite if %python-base >= 3}
+BuildRequires: %{python_module testsuite}
BuildRequires: cronie
# /SECTION
%python_subpackages
++++++ python_crontab-3.2.0.tar.gz -> python_crontab-3.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_crontab-3.2.0/PKG-INFO
new/python_crontab-3.3.0/PKG-INFO
--- old/python_crontab-3.2.0/PKG-INFO 2024-07-02 00:28:33.541114300 +0200
+++ new/python_crontab-3.3.0/PKG-INFO 2025-07-13 21:34:56.962660000 +0200
@@ -1,6 +1,6 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
Name: python-crontab
-Version: 3.2.0
+Version: 3.3.0
Summary: Python Crontab API
Home-page: https://gitlab.com/doctormo/python-crontab/
Author: Martin Owens
@@ -12,7 +12,6 @@
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
-Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or
later (LGPLv3+)
Classifier: Operating System :: POSIX
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: POSIX :: SunOS/Solaris
@@ -29,11 +28,22 @@
Description-Content-Type: text/x-rst
License-File: COPYING
License-File: AUTHORS
-Requires-Dist: python-dateutil
Provides-Extra: cron-schedule
Requires-Dist: croniter; extra == "cron-schedule"
Provides-Extra: cron-description
Requires-Dist: cron-descriptor; extra == "cron-description"
+Dynamic: author
+Dynamic: author-email
+Dynamic: classifier
+Dynamic: description
+Dynamic: description-content-type
+Dynamic: home-page
+Dynamic: license
+Dynamic: license-file
+Dynamic: platform
+Dynamic: provides
+Dynamic: provides-extra
+Dynamic: summary
Python Crontab
--------------
@@ -95,6 +105,8 @@
@midnight 0 0 * * *
=========== ============
+To control the output of specials see `SPECIALS_CONVERSION` below.
+
How to Use the Module
=====================
@@ -317,11 +329,27 @@
job.env['NEW_VAR'] = 'A'
print(job.env)
+Specials Mode
+=============
+
+You may need to control the output of special schedules such as `@hourly`.
This can be done with the `crontab.SPECIALS_CONVERSION` package variable.
+
+Enable conversion to a special on write (default)::
+
+ crontab.SPECIALS_CONVERSION = True
+
+Enabled conversion to normal output on write::
+
+ crontab.SPECIALS_CONVERSION = False
+
+Do no conversion and write whatever was read in::
+
+ crontab.SPECIALS_CONVERSION = None
Proceeding Unit Confusion
=========================
-It is sometimes logical to think that job.hour.every(2) will set all proceeding
+It is sometimes logical to think that `job.hour.every(2)` will set all
proceeding
units to '0' and thus result in "0 \*/2 * * \*". Instead you are controlling
only the hours units and the minute column is unaffected. The real result would
be "\* \*/2 * * \*" and maybe unexpected to those unfamiliar with crontabs.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_crontab-3.2.0/README.rst
new/python_crontab-3.3.0/README.rst
--- old/python_crontab-3.2.0/README.rst 2023-07-13 16:51:49.000000000 +0200
+++ new/python_crontab-3.3.0/README.rst 2025-07-13 21:28:33.000000000 +0200
@@ -58,6 +58,8 @@
@midnight 0 0 * * *
=========== ============
+To control the output of specials see `SPECIALS_CONVERSION` below.
+
How to Use the Module
=====================
@@ -280,11 +282,27 @@
job.env['NEW_VAR'] = 'A'
print(job.env)
+Specials Mode
+=============
+
+You may need to control the output of special schedules such as `@hourly`.
This can be done with the `crontab.SPECIALS_CONVERSION` package variable.
+
+Enable conversion to a special on write (default)::
+
+ crontab.SPECIALS_CONVERSION = True
+
+Enabled conversion to normal output on write::
+
+ crontab.SPECIALS_CONVERSION = False
+
+Do no conversion and write whatever was read in::
+
+ crontab.SPECIALS_CONVERSION = None
Proceeding Unit Confusion
=========================
-It is sometimes logical to think that job.hour.every(2) will set all proceeding
+It is sometimes logical to think that `job.hour.every(2)` will set all
proceeding
units to '0' and thus result in "0 \*/2 * * \*". Instead you are controlling
only the hours units and the minute column is unaffected. The real result would
be "\* \*/2 * * \*" and maybe unexpected to those unfamiliar with crontabs.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_crontab-3.2.0/cronlog.py
new/python_crontab-3.3.0/cronlog.py
--- old/python_crontab-3.2.0/cronlog.py 2022-12-22 05:41:54.000000000 +0100
+++ new/python_crontab-3.3.0/cronlog.py 2025-07-13 21:28:32.000000000 +0200
@@ -21,12 +21,12 @@
import os
import re
import codecs
-import platform
-from dateutil import parser as dateparse
+from datetime import datetime
MATCHER = r'(?P<date>\w+ +\d+ +\d\d:\d\d:\d\d) (?P<host>\w+) ' + \
r'CRON\[(?P<pid>\d+)\]: \((?P<user>\w+)\) CMD \((?P<cmd>.*)\)'
+
class LogReader(object):
"""Opens a Log file, reading backwards and watching for changes"""
def __init__(self, filename, mass=4096):
@@ -82,6 +82,10 @@
loc -= len(line)
+def cron_date_to_datetime(cron_str):
+ with_year = f"{cron_str} {datetime.now().year}"
+ return datetime.strptime(with_year, "%b %d %H:%M:%S %Y")
+
class CronLog(LogReader):
"""Use the LogReader to make a Cron specific log reader"""
@@ -98,7 +102,7 @@
match = re.match(MATCHER, str(line))
datum = match and match.groupdict()
if datum and (not self.user or datum['user'] == self.user):
- datum['date'] = dateparse.parse(datum['date'])
+ datum['date'] = cron_date_to_datetime(datum['date'])
yield datum
@@ -112,4 +116,3 @@
for entry in self.log:
if entry['cmd'] == str(self.command):
yield entry
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_crontab-3.2.0/crontab.py
new/python_crontab-3.3.0/crontab.py
--- old/python_crontab-3.2.0/crontab.py 2024-07-02 00:20:03.000000000 +0200
+++ new/python_crontab-3.3.0/crontab.py 2025-07-13 21:28:33.000000000 +0200
@@ -1,5 +1,5 @@
#
-# Copyright 2021, Martin Owens <[email protected]>
+# Copyright 2025, Martin Owens <[email protected]>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -100,7 +100,7 @@
from shutil import which
__pkgname__ = 'python-crontab'
-__version__ = '3.2.0'
+__version__ = '3.3.0'
ITEMREX = re.compile(r'^\s*([^@#\s]+)\s+([^@#\s]+)\s+([^@#\s]+)\s+([^@#\s]+)'
r'\s+([^@#\s]+)\s+([^\n]*?)(\s+#\s*([^\n]*)|$)')
@@ -112,6 +112,7 @@
MONTH_ENUM = [None, 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug',
'sep', 'oct', 'nov', 'dec']
+SPECIALS_CONVERSION = True
SPECIALS = {"reboot": '@reboot',
"hourly": '0 * * * *',
"daily": '0 0 * * *',
@@ -433,14 +434,10 @@
sleep(cadence)
count += 1
- def render(self, errors=False, specials=True):
+ def render(self, errors=False):
"""Render this crontab as it would be in the crontab.
errors - Should we not comment out invalid entries and cause errors?
- specials - Turn known times into keywords such as "@daily"
- True - (default) force all values to be converted (unless SYSTEMV)
- False - force all values back from being a keyword
- None - don't change the special keyword use
"""
crons = []
for line in self.lines:
@@ -454,7 +451,7 @@
elif isinstance(line, CronItem):
if not line.is_valid() and not errors:
line.enabled = False
- crons.append(line.render(specials=specials).strip())
+ crons.append(line.render().strip())
# Environment variables are attached to cron lines so order will
# always work no matter how you add lines in the middle of the stack.
@@ -727,7 +724,7 @@
"""Return true if this job is valid"""
return self.valid
- def render(self, specials=True):
+ def render(self):
"""Render this set cron-job to a string"""
if not self.is_valid() and self.enabled:
raise ValueError('Refusing to render invalid crontab.'
@@ -738,7 +735,7 @@
if not self.user:
raise ValueError("Job to system-cron format, no user set!")
user = self.user + ' '
- rend = self.slices.render(specials=specials)
+ rend = self.slices.render()
result = f"{rend} {user}{command}"
if self.stdin:
result += ' %' + self.stdin.replace('\n', '%')
@@ -819,10 +816,6 @@
"""
return self.slices.frequency_at_year(year=year)
- def frequency(self, year=None):
- """Return frequence per year times frequency per day"""
- return self.frequency_per_year(year=year) * self.frequency_per_day()
-
def frequency_per_year(self, year=None):
"""Returns the number of /days/ this item will execute on in a year
(defaults to this year)
@@ -1063,14 +1056,14 @@
"""Return just numbered parts of this crontab"""
return ' '.join([str(s) for s in self])
- def render(self, specials=True):
+ def render(self):
"Return just the first part of a cron job (the numbers or special)"
slices = self.clean_render()
- if self.special and specials is not False:
+ if self.special and SPECIALS_CONVERSION is not False:
if self.special == '@reboot' or \
SPECIALS[self.special.strip('@')] == slices:
return self.special
- if not SYSTEMV and specials is True:
+ if not SYSTEMV and SPECIALS_CONVERSION is True:
for (name, value) in SPECIALS.items():
if value == slices and name not in SPECIAL_IGNORE:
return f"@{name}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_crontab-3.2.0/pyproject.toml
new/python_crontab-3.3.0/pyproject.toml
--- old/python_crontab-3.2.0/pyproject.toml 1970-01-01 01:00:00.000000000
+0100
+++ new/python_crontab-3.3.0/pyproject.toml 2025-07-13 21:29:53.000000000
+0200
@@ -0,0 +1,12 @@
+[tool.ruff]
+line-length = 128
+
+
+[tool.ruff.lint]
+ignore = [
+ "E402",
+ "E731",
+ "F401",
+ "F821",
+ "F841",
+]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_crontab-3.2.0/python_crontab.egg-info/PKG-INFO
new/python_crontab-3.3.0/python_crontab.egg-info/PKG-INFO
--- old/python_crontab-3.2.0/python_crontab.egg-info/PKG-INFO 2024-07-02
00:28:33.000000000 +0200
+++ new/python_crontab-3.3.0/python_crontab.egg-info/PKG-INFO 2025-07-13
21:34:56.000000000 +0200
@@ -1,6 +1,6 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
Name: python-crontab
-Version: 3.2.0
+Version: 3.3.0
Summary: Python Crontab API
Home-page: https://gitlab.com/doctormo/python-crontab/
Author: Martin Owens
@@ -12,7 +12,6 @@
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
-Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or
later (LGPLv3+)
Classifier: Operating System :: POSIX
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: POSIX :: SunOS/Solaris
@@ -29,11 +28,22 @@
Description-Content-Type: text/x-rst
License-File: COPYING
License-File: AUTHORS
-Requires-Dist: python-dateutil
Provides-Extra: cron-schedule
Requires-Dist: croniter; extra == "cron-schedule"
Provides-Extra: cron-description
Requires-Dist: cron-descriptor; extra == "cron-description"
+Dynamic: author
+Dynamic: author-email
+Dynamic: classifier
+Dynamic: description
+Dynamic: description-content-type
+Dynamic: home-page
+Dynamic: license
+Dynamic: license-file
+Dynamic: platform
+Dynamic: provides
+Dynamic: provides-extra
+Dynamic: summary
Python Crontab
--------------
@@ -95,6 +105,8 @@
@midnight 0 0 * * *
=========== ============
+To control the output of specials see `SPECIALS_CONVERSION` below.
+
How to Use the Module
=====================
@@ -317,11 +329,27 @@
job.env['NEW_VAR'] = 'A'
print(job.env)
+Specials Mode
+=============
+
+You may need to control the output of special schedules such as `@hourly`.
This can be done with the `crontab.SPECIALS_CONVERSION` package variable.
+
+Enable conversion to a special on write (default)::
+
+ crontab.SPECIALS_CONVERSION = True
+
+Enabled conversion to normal output on write::
+
+ crontab.SPECIALS_CONVERSION = False
+
+Do no conversion and write whatever was read in::
+
+ crontab.SPECIALS_CONVERSION = None
Proceeding Unit Confusion
=========================
-It is sometimes logical to think that job.hour.every(2) will set all proceeding
+It is sometimes logical to think that `job.hour.every(2)` will set all
proceeding
units to '0' and thus result in "0 \*/2 * * \*". Instead you are controlling
only the hours units and the minute column is unaffected. The real result would
be "\* \*/2 * * \*" and maybe unexpected to those unfamiliar with crontabs.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_crontab-3.2.0/python_crontab.egg-info/SOURCES.txt
new/python_crontab-3.3.0/python_crontab.egg-info/SOURCES.txt
--- old/python_crontab-3.2.0/python_crontab.egg-info/SOURCES.txt
2024-07-02 00:28:33.000000000 +0200
+++ new/python_crontab-3.3.0/python_crontab.egg-info/SOURCES.txt
2025-07-13 21:34:56.000000000 +0200
@@ -6,6 +6,7 @@
cronlog.py
crontab.py
crontabs.py
+pyproject.toml
setup.py
python_crontab.egg-info/PKG-INFO
python_crontab.egg-info/SOURCES.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_crontab-3.2.0/python_crontab.egg-info/requires.txt
new/python_crontab-3.3.0/python_crontab.egg-info/requires.txt
--- old/python_crontab-3.2.0/python_crontab.egg-info/requires.txt
2024-07-02 00:28:33.000000000 +0200
+++ new/python_crontab-3.3.0/python_crontab.egg-info/requires.txt
2025-07-13 21:34:56.000000000 +0200
@@ -1,4 +1,3 @@
-python-dateutil
[cron-description]
cron-descriptor
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_crontab-3.2.0/setup.py
new/python_crontab-3.3.0/setup.py
--- old/python_crontab-3.2.0/setup.py 2023-07-13 16:52:41.000000000 +0200
+++ new/python_crontab-3.3.0/setup.py 2025-07-13 21:30:34.000000000 +0200
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright (C) 2008-2018 Martin Owens
+# Copyright (C) 2008-2025 Martin Owens
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -20,7 +20,6 @@
import os
from setuptools import setup
-from crontab import __version__, __pkgname__
# remove MANIFEST. distutils doesn't properly update it when the
# contents of directories change.
@@ -35,8 +34,8 @@
RELEASE = "1"
setup(
- name = __pkgname__,
- version = __version__,
+ name = 'python-crontab',
+ version = '3.3.0',
release = RELEASE,
description = 'Python Crontab API',
long_description = description,
@@ -49,7 +48,6 @@
license = 'LGPLv3',
py_modules = ['crontab', 'crontabs', 'cronlog'],
provides = ['crontab', 'crontabs', 'cronlog'],
- install_requires = ['python-dateutil'],
extras_require = {
'cron-schedule': ['croniter'],
'cron-description': ['cron-descriptor'],
@@ -60,7 +58,6 @@
'Intended Audience :: Developers',
'Intended Audience :: Information Technology',
'Intended Audience :: System Administrators',
- 'License :: OSI Approved :: GNU Lesser General Public License v3 or
later (LGPLv3+)',
'Operating System :: POSIX',
'Operating System :: POSIX :: Linux',
'Operating System :: POSIX :: SunOS/Solaris',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_crontab-3.2.0/tests/test_compatibility.py
new/python_crontab-3.3.0/tests/test_compatibility.py
--- old/python_crontab-3.2.0/tests/test_compatibility.py 2023-10-21
21:16:57.000000000 +0200
+++ new/python_crontab-3.3.0/tests/test_compatibility.py 2024-07-02
22:02:12.000000000 +0200
@@ -32,14 +32,6 @@
0,30 * * * * firstcommand
"""
-class UserTestCase(unittest.TestCase):
- def test_01_self_user(self):
- tab = crontab.CronTab(user='foo')
- self.assertEqual(tab.user_opt, {'u': 'foo'})
- tab = crontab.CronTab(user=crontab.current_user())
- self.assertEqual(tab.user_opt, {})
-
-
class CompatTestCase(unittest.TestCase):
"""Test basic functionality of crontab."""
@classmethod
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_crontab-3.2.0/tests/test_usage.py
new/python_crontab-3.3.0/tests/test_usage.py
--- old/python_crontab-3.2.0/tests/test_usage.py 2023-10-21
21:16:57.000000000 +0200
+++ new/python_crontab-3.3.0/tests/test_usage.py 2025-07-13
21:28:33.000000000 +0200
@@ -78,6 +78,21 @@
self.assertEqual(cron.render(), BASIC)
self.assertEqual(repr(cron), "<User CronTab 'basic'>")
+ def test_02_user_bad_command(self):
+ # Test bad cron command
+ cron = crontab.CronTab(user='basic')
+ cron.cron_command = 'wibble/no/no/no/yes'
+ with self.assertRaises(IOError):
+ cron.read()
+ with self.assertRaises(IOError):
+ cron.write()
+
+ def test_02_user_self(self):
+ tab = crontab.CronTab(user='foo')
+ self.assertEqual(tab.user_opt, {'u': 'foo'})
+ tab = crontab.CronTab(user=crontab.current_user())
+ self.assertEqual(tab.user_opt, {})
+
def test_03_usage(self):
"""Dont modify crontab"""
cron = crontab.CronTab(tab='')
@@ -199,11 +214,23 @@
"""Rendering can be done without specials"""
cronitem = crontab.CronItem('true')
cronitem.setall('0 0 * * *')
- self.assertEqual(cronitem.render(specials=True), '@daily true')
- self.assertEqual(cronitem.render(specials=None), '0 0 * * * true')
+ crontab.SPECIALS_CONVERSION = True
+ self.assertEqual(cronitem.render(), '@daily true')
+ crontab.SPECIALS_CONVERSION = False
+ self.assertEqual(cronitem.render(), '0 0 * * * true')
+ crontab.SPECIALS_CONVERSION = None
+ self.assertEqual(cronitem.render(), '0 0 * * * true')
+
+ def test_22_slice_special_convert(self):
+ """Render of specials global control"""
+ cronitem = crontab.CronItem('true')
cronitem.setall('@daily')
- self.assertEqual(cronitem.render(specials=None), '@daily true')
- self.assertEqual(cronitem.render(specials=False), '0 0 * * * true')
+ crontab.SPECIALS_CONVERSION = True
+ self.assertEqual(cronitem.render(), '@daily true')
+ crontab.SPECIALS_CONVERSION = False
+ self.assertEqual(cronitem.render(), '0 0 * * * true')
+ crontab.SPECIALS_CONVERSION = None
+ self.assertEqual(cronitem.render(), '@daily true')
def test_25_process(self):
"""Test opening pipes"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_crontab-3.2.0/tests/test_utf8.py
new/python_crontab-3.3.0/tests/test_utf8.py
--- old/python_crontab-3.2.0/tests/test_utf8.py 2023-10-21 21:16:57.000000000
+0200
+++ new/python_crontab-3.3.0/tests/test_utf8.py 2025-07-13 21:28:32.000000000
+0200
@@ -45,7 +45,7 @@
def test_02_write(self):
"""Write/Read UTF-8 Filename"""
- self.assertEqual(locale.getpreferredencoding(), 'UTF-8')
+ self.assertEqual(locale.getpreferredencoding().lower(), 'utf-8')
self.crontab.write(filename)
crontab = CronTab(tabfile=filename)
self.assertTrue(crontab)