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)

Reply via email to