Sfoglia il codice sorgente

HUE-9378 [core] Removing python-crontab lib

As GPL. Used by celery beat.
Romain 5 anni fa
parent
commit
505a84e82f
37 ha cambiato i file con 0 aggiunte e 5290 eliminazioni
  1. 0 1
      desktop/core/ext-py/python-crontab-2.3.6/AUTHORS
  2. 0 165
      desktop/core/ext-py/python-crontab-2.3.6/COPYING
  3. 0 10
      desktop/core/ext-py/python-crontab-2.3.6/MANIFEST.in
  4. 0 430
      desktop/core/ext-py/python-crontab-2.3.6/PKG-INFO
  5. 0 403
      desktop/core/ext-py/python-crontab-2.3.6/README.rst
  6. 0 123
      desktop/core/ext-py/python-crontab-2.3.6/cronlog.py
  7. 0 1346
      desktop/core/ext-py/python-crontab-2.3.6/crontab.py
  8. 0 145
      desktop/core/ext-py/python-crontab-2.3.6/crontabs.py
  9. 0 4
      desktop/core/ext-py/python-crontab-2.3.6/setup.cfg
  10. 0 79
      desktop/core/ext-py/python-crontab-2.3.6/setup.py
  11. 0 1
      desktop/core/ext-py/python-crontab-2.3.6/tests/__init__.py
  12. 0 7
      desktop/core/ext-py/python-crontab-2.3.6/tests/data/basic.log
  13. 0 4
      desktop/core/ext-py/python-crontab-2.3.6/tests/data/crontab
  14. 0 50
      desktop/core/ext-py/python-crontab-2.3.6/tests/data/crontest
  15. 0 3
      desktop/core/ext-py/python-crontab-2.3.6/tests/data/specials.tab
  16. 0 5
      desktop/core/ext-py/python-crontab-2.3.6/tests/data/specials_enc.tab
  17. 0 32
      desktop/core/ext-py/python-crontab-2.3.6/tests/data/test.log
  18. 0 17
      desktop/core/ext-py/python-crontab-2.3.6/tests/data/test.tab
  19. 0 120
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_compatibility.py
  20. 0 89
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_croniter.py
  21. 0 112
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_crontabs.py
  22. 0 66
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_description.py
  23. 0 121
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_enums.py
  24. 0 220
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_env.py
  25. 0 109
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_every.py
  26. 0 161
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_frequency.py
  27. 0 367
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_interaction.py
  28. 0 161
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_log.py
  29. 0 136
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_range.py
  30. 0 154
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_removal.py
  31. 0 113
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_scheduler.py
  32. 0 122
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_system_cron.py
  33. 0 215
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_usage.py
  34. 0 116
      desktop/core/ext-py/python-crontab-2.3.6/tests/test_utf8.py
  35. 0 81
      desktop/core/ext-py/python-crontab-2.3.6/tests/utils.py
  36. 0 1
      desktop/core/requirements.txt
  37. 0 1
      desktop/core/requirements_py3.txt

+ 0 - 1
desktop/core/ext-py/python-crontab-2.3.6/AUTHORS

@@ -1 +0,0 @@
-Martin Owens (doctormo@gmail.com)

+ 0 - 165
desktop/core/ext-py/python-crontab-2.3.6/COPYING

@@ -1,165 +0,0 @@
-                   GNU LESSER GENERAL PUBLIC LICENSE
-                       Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
-  This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
-  0. Additional Definitions.
-
-  As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
-  "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
-  An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
-  A "Combined Work" is a work produced by combining or linking an
-Application with the Library.  The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
-  The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
-  The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
-  1. Exception to Section 3 of the GNU GPL.
-
-  You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
-  2. Conveying Modified Versions.
-
-  If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
-   a) under this License, provided that you make a good faith effort to
-   ensure that, in the event an Application does not supply the
-   function or data, the facility still operates, and performs
-   whatever part of its purpose remains meaningful, or
-
-   b) under the GNU GPL, with none of the additional permissions of
-   this License applicable to that copy.
-
-  3. Object Code Incorporating Material from Library Header Files.
-
-  The object code form of an Application may incorporate material from
-a header file that is part of the Library.  You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
-   a) Give prominent notice with each copy of the object code that the
-   Library is used in it and that the Library and its use are
-   covered by this License.
-
-   b) Accompany the object code with a copy of the GNU GPL and this license
-   document.
-
-  4. Combined Works.
-
-  You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
-   a) Give prominent notice with each copy of the Combined Work that
-   the Library is used in it and that the Library and its use are
-   covered by this License.
-
-   b) Accompany the Combined Work with a copy of the GNU GPL and this license
-   document.
-
-   c) For a Combined Work that displays copyright notices during
-   execution, include the copyright notice for the Library among
-   these notices, as well as a reference directing the user to the
-   copies of the GNU GPL and this license document.
-
-   d) Do one of the following:
-
-       0) Convey the Minimal Corresponding Source under the terms of this
-       License, and the Corresponding Application Code in a form
-       suitable for, and under terms that permit, the user to
-       recombine or relink the Application with a modified version of
-       the Linked Version to produce a modified Combined Work, in the
-       manner specified by section 6 of the GNU GPL for conveying
-       Corresponding Source.
-
-       1) Use a suitable shared library mechanism for linking with the
-       Library.  A suitable mechanism is one that (a) uses at run time
-       a copy of the Library already present on the user's computer
-       system, and (b) will operate properly with a modified version
-       of the Library that is interface-compatible with the Linked
-       Version.
-
-   e) Provide Installation Information, but only if you would otherwise
-   be required to provide such information under section 6 of the
-   GNU GPL, and only to the extent that such information is
-   necessary to install and execute a modified version of the
-   Combined Work produced by recombining or relinking the
-   Application with a modified version of the Linked Version. (If
-   you use option 4d0, the Installation Information must accompany
-   the Minimal Corresponding Source and Corresponding Application
-   Code. If you use option 4d1, you must provide the Installation
-   Information in the manner specified by section 6 of the GNU GPL
-   for conveying Corresponding Source.)
-
-  5. Combined Libraries.
-
-  You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
-   a) Accompany the combined library with a copy of the same work based
-   on the Library, uncombined with any other library facilities,
-   conveyed under the terms of this License.
-
-   b) Give prominent notice with the combined library that part of it
-   is a work based on the Library, and explaining where to find the
-   accompanying uncombined form of the same work.
-
-  6. Revised Versions of the GNU Lesser General Public License.
-
-  The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
-  Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
-  If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.

+ 0 - 10
desktop/core/ext-py/python-crontab-2.3.6/MANIFEST.in

@@ -1,10 +0,0 @@
-include AUTHORS
-include COPYING
-include README.rst
-include MANIFEST.in
-include ChangeLog
-include setup.py
-include crontab.py
-include cronlog.py
-include tests/*.py
-include tests/data/*

+ 0 - 430
desktop/core/ext-py/python-crontab-2.3.6/PKG-INFO

@@ -1,430 +0,0 @@
-Metadata-Version: 2.1
-Name: python-crontab
-Version: 2.3.6
-Summary: Python Crontab API
-Home-page: https://gitlab.com/doctormo/python-crontab/
-Author: Martin Owens
-Author-email: doctormo@gmail.com
-License: LGPLv3
-Description: Python Crontab
-        --------------
-        
-        .. image:: https://gitlab.com/doctormo/python-crontab/raw/master/branding.svg
-        
-        .. image:: https://badge.fury.io/py/python-crontab.svg
-            :target: https://badge.fury.io/py/python-crontab
-        .. image:: https://img.shields.io/badge/License-LGPL%20v3-blue.svg
-            :target: https://gitlab.com/doctormo/python-crontab/raw/master/COPYING
-        
-        Bug Reports and Development
-        ===========================
-        
-        Please report any problems to the `GitLab issues tracker <https://gitlab.com/doctormo/python-crontab/issues>`_. Please use Git and push patches to the `GitLab project code hosting <https://gitlab.com/doctormo/python-crontab>`_.
-        
-        **Note:** If you get the error ``TypeError: __init__() takes exactly 2 arguments`` when using CronTab, you have the wrong module installed. You need to install ``python-crontab`` and not ``crontab`` from pypi or your local package manager and try again.
-        
-        Description
-        ===========
-        
-        Crontab module for reading and writing crontab files and accessing the system cron
-        automatically and simply using a direct API.
-        
-        Comparing the `below chart <http://en.wikipedia.org/wiki/Cron#CRON_expression>`_
-        you will note that W, L, # and ? symbols are not supported as they are not
-        standard Linux or SystemV crontab format.
-        
-        +-------------+-----------+-----------------+-------------------+-------------+
-        |Field Name   |Mandatory  |Allowed Values   |Special Characters |Extra Values |
-        +=============+===========+=================+===================+=============+
-        |Minutes      |Yes        |0-59             |\* / , -           | < >         |
-        +-------------+-----------+-----------------+-------------------+-------------+
-        |Hours        |Yes        |0-23             |\* / , -           | < >         |
-        +-------------+-----------+-----------------+-------------------+-------------+
-        |Day of month |Yes        |1-31             |\* / , -           | < >         |
-        +-------------+-----------+-----------------+-------------------+-------------+
-        |Month        |Yes        |1-12 or JAN-DEC  |\* / , -           | < >         |
-        +-------------+-----------+-----------------+-------------------+-------------+
-        |Day of week  |Yes        |0-6 or SUN-SAT   |\* / , -           | < >         |
-        +-------------+-----------+-----------------+-------------------+-------------+
-        
-        Extra Values are '<' for minimum value, such as 0 for minutes or 1 for months.
-        And '>' for maximum value, such as 23 for hours or 12 for months.
-        
-        Supported special cases allow crontab lines to not use fields.
-        These are the supported aliases which are not available in SystemV mode:
-        
-        =========== ============
-        Case        Meaning    
-        =========== ============
-        @reboot     Every boot 
-        @hourly     0 * * * *  
-        @daily      0 0 * * *  
-        @weekly     0 0 * * 0  
-        @monthly    0 0 1 * *  
-        @yearly     0 0 1 1 *  
-        @annually   0 0 1 1 *  
-        @midnight   0 0 * * *  
-        =========== ============
-        
-        How to Use the Module
-        =====================
-        
-        **Note:** Several users have reported their new crontabs not saving automatically or that the module doesn't do anything. You **MUST** use write() if you want your edits to be saved out. See below for full details on the use of the write function.
-        
-        Getting access to a crontab can happen in five ways, three system methods that
-        will work only on Unix and require you to have the right permissions::
-        
-            from crontab import CronTab
-        
-            empty_cron    = CronTab()
-            my_user_cron  = CronTab(user=True)
-            users_cron    = CronTab(user='username')
-        
-        And two ways from non-system sources that will work on Windows too::
-        
-            file_cron = CronTab(tabfile='filename.tab')
-            mem_cron = CronTab(tab="""
-              * * * * * command
-            """)
-        
-        Special per-command user flag for vixie cron format (new in 1.9)::
-        
-            system_cron = CronTab(tabfile='/etc/crontab', user=False)
-            job = system_cron[0]
-            job.user != None
-            system_cron.new(command='new_command', user='root')
-        
-        Creating a new job is as simple as::
-        
-            job  = cron.new(command='/usr/bin/echo')
-        
-        And setting the job's time restrictions::
-        
-            job.minute.during(5,50).every(5)
-            job.hour.every(4)
-            job.day.on(4, 5, 6)
-        
-            job.dow.on('SUN')
-            job.dow.on('SUN', 'FRI')
-            job.month.during('APR', 'NOV')
-        
-        Each time restriction will clear the previous restriction::
-        
-            job.hour.every(10) # Set to * */10 * * *
-            job.hour.on(2)     # Set to * 2 * * *
-        
-        Appending restrictions is explicit::
-        
-            job.hour.every(10)  # Set to * */10 * * *
-            job.hour.also.on(2) # Set to * 2,*/10 * * *
-        
-        Setting all time slices at once::
-        
-            job.setall(2, 10, '2-4', '*/2', None)
-            job.setall('2 10 * * *')
-        
-        Setting the slice to a python date object::
-        
-            job.setall(time(10, 2))
-            job.setall(date(2000, 4, 2))
-            job.setall(datetime(2000, 4, 2, 10, 2))
-        
-        Run a jobs command. Running the job here will not effect it's
-        existing schedule with another crontab process::
-        
-            job_standard_output = job.run()
-        
-        Creating a job with a comment::
-        
-            job = cron.new(command='/foo/bar', comment='SomeID')
-        
-        Get the comment or command for a job::
-        
-            command = job.command
-            comment = job.comment
-        
-        Modify the comment or command on a job::
-        
-            job.set_command("new_script.sh")
-            job.set_comment("New ID or comment here")
-        
-        Disabled or Enable Job::
-        
-            job.enable()
-            job.enable(False)
-            False == job.is_enabled()
-        
-        Validity Check::
-        
-            True == job.is_valid()
-        
-        Use a special syntax::
-        
-            job.every_reboot()
-        
-        Find an existing job by command sub-match or regular expression::
-        
-            iter = cron.find_command('bar') # matches foobar1
-            iter = cron.find_command(re.compile(r'b[ab]r$'))
-        
-        Find an existing job by comment exact match or regular expression::
-        
-            iter = cron.find_comment('ID or some text')
-            iter = cron.find_comment(re.compile(' or \w'))
-        
-        Find an existing job by schedule::
-        
-            iter = cron.find_time(2, 10, '2-4', '*/2', None)
-            iter = cron.find_time("*/2 * * * *")
-        
-        Clean a job of all rules::
-        
-            job.clear()
-        
-        Iterate through all jobs, this includes disabled (commented out) cron jobs::
-        
-            for job in cron:
-                print job
-        
-        Iterate through all lines, this includes all comments and empty lines::
-        
-            for line in cron.lines:
-                print line
-        
-        Remove Items::
-        
-            cron.remove( job )
-            cron.remove_all('echo')
-            cron.remove_all(comment='foo')
-            cron.remove_all(time='*/2')
-        
-        Clear entire cron of all jobs::
-        
-            cron.remove_all()
-        
-        Write CronTab back to system or filename::
-        
-            cron.write()
-        
-        Write CronTab to new filename::
-        
-            cron.write( 'output.tab' )
-        
-        Write to this user's crontab (unix only)::
-        
-            cron.write_to_user( user=True )
-        
-        Write to some other user's crontab::
-        
-            cron.write_to_user( user='bob' )
-        
-        Validate a cron time string::
-        
-            from crontab import CronSlices
-            bool = CronSlices.is_valid('0/2 * * * *')
-        
-        
-        Environment Variables
-        =====================
-        
-        Some versions of vixie cron support variables outside of the command line.
-        Sometimes just update the envronment when commands are run, the Cronie fork
-        of vixie cron also supports CRON_TZ which looks like a regular variable but
-        actually changes the times the jobs are run at.
-        
-        Very old vixie crons don't support per-job variables, but most do.
-        
-        Iterate through cron level environment variables::
-        
-            for (name, value) in cron.env.items():
-                print name
-                print value
-        
-        Create new or update cron level environment variables::
-        
-            print cron.env['SHELL']
-            cron.env['SHELL'] = '/bin/bash'
-            print cron.env
-        
-        Each job can also have a list of environment variables::
-        
-            for job in cron:
-                job.env['NEW_VAR'] = 'A'
-                print job.env
-        
-        
-        Proceeding Unit Confusion
-        =========================
-        
-        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.
-        
-        There is a special 'every' method on a job to clear the job's existing schedule
-        and replace it with a simple single unit::
-        
-            job.every(4).hours()  == '0 */4 * * *'
-            job.every().dom()     == '0 0 * * *'
-            job.every().month()   == '0 0 0 * *'
-            job.every(2).dows()   == '0 0 * * */2'
-        
-        This is a convenience method only, it does normal things with the existing api.
-        
-        Running the Scheduler
-        =====================
-        
-        The module is able to run a cron tab as a daemon as long as the optional
-        croniter module is installed; each process will block and errors will
-        be logged (new in 2.0).
-        
-        (note this functionality is new and not perfect, if you find bugs report them!)
-        
-        Running the scheduler::
-        
-            tab = CronTab(tabfile='MyScripts.tab')
-            for result in tab.run_scheduler():
-                print "This was printed to stdout by the process."
-        
-        Do not do this, it won't work because it returns generator function::
-        
-            tab.run_scheduler()
-        
-        Timeout and cadence can be changed for testing or error management::
-        
-            for result in tab.run_scheduler(timeout=600):
-                print "Will run jobs every 1 minutes for ten minutes from now()"
-        
-            for result in tab.run_scheduler(cadence=1, warp=True):
-                print "Will run jobs every 1 second, counting each second as 1 minute"
-        
-        Frequency Calculation
-        =====================
-        
-        Every job's schedule has a frequency. We can attempt to calculate the number
-        of times a job would execute in a give amount of time. We have three simple
-        methods::
-        
-            job.setall("1,2 1,2 * * *")
-            job.frequency_per_day() == 4
-        
-        The per year frequency method will tell you how many days a year the
-        job would execute::
-        
-            job.setall("* * 1,2 1,2 *")
-            job.frequency_per_year(year=2010) == 4
-        
-        These are combined to give the number of times a job will execute in any year::
-        
-            job.setall("1,2 1,2 1,2 1,2 *")
-            job.frequency(year=2010) == 16
-        
-        Frequency can be quickly checked using python built-in operators::
-        
-            job < "*/2 * * * *"
-            job > job2
-            job.slices == "*/5"
-        
-        Log Functionality
-        =================
-        
-        The log functionality will read a cron log backwards to find you the last run
-        instances of your crontab and cron jobs.
-        
-        The crontab will limit the returned entries to the user the crontab is for::
-        
-            cron = CronTab(user='root')
-        
-            for d in cron.log:
-                print d['pid'] + " - " + d['date']
-        
-        Each job can return a log iterator too, these are filtered so you can see when
-        the last execution was::
-        
-            for d in cron.find_command('echo')[0].log:
-                print d['pid'] + " - " + d['date']
-        
-        All System CronTabs Functionality
-        =================================
-        
-        The crontabs (note the plural) module can attempt to find all crontabs on the
-        system. This works well for Linux systems with known locations for cron files
-        and user spolls. It will even extract anacron jobs so you can get a picture
-        of all the jobs running on your system::
-        
-            from crontabs import CronTabs
-            
-            for cron in CronTabs():
-                print repr(cron)
-        
-        All jobs can be brought together to run various searches, all jobs are added
-        to a CronTab object which can be used as documented above::
-        
-           jobs = CronTabs().all.find_command('foo')
-        
-        Schedule Functionality
-        ======================
-        
-        If you have the croniter python module installed, you will have access to a
-        schedule on each job. For example if you want to know when a job will next run::
-        
-            schedule = job.schedule(date_from=datetime.now())
-        
-        This creates a schedule croniter based on the job from the time specified. The
-        default date_from is the current date/time if not specified. Next we can get
-        the datetime of the next job::
-        
-            datetime = schedule.get_next()
-        
-        Or the previous::
-        
-            datetime = schedule.get_prev()
-        
-        The get methods work in the same way as the default croniter, except that they
-        will return datetime objects by default instead of floats. If you want the
-        original functionality, pass float into the method when calling::
-        
-            datetime = schedule.get_current(float)
-        
-        If you don't have the croniter module installed, you'll get an ImportError when
-        you first try using the schedule function on your cron job object.
-        
-        Descriptor Functionality
-        ========================
-        
-        If you have the cron-descriptor module installed, you will be able to ask for a
-        translated string which describes the frequency of the job in the current
-        locale language. This should be mostly human readable.
-        
-        
-            print(job.description(use_24hour_time_format=True))
-        
-        See cron-descriptor for details of the supported languages and options.
-        
-        Extra Support
-        =============
-        
-         - Support for vixie cron with username addition with user flag
-         - Support for SunOS, AIX & HP with compatibility 'SystemV' mode.
-         - Python 3.5.2 and Python 2.7 tested, python 2.6 removed from support.
-         - Windows support works for non-system crontabs only.
-           ( see mem_cron and file_cron examples above for usage )
-        
-Platform: linux
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Development Status :: 6 - Mature
-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
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3.5
-Provides: crontab
-Provides: crontabs
-Provides: cronlog
-Provides-Extra: cron-description
-Provides-Extra: cron-schedule

+ 0 - 403
desktop/core/ext-py/python-crontab-2.3.6/README.rst

@@ -1,403 +0,0 @@
-Python Crontab
---------------
-
-.. image:: https://gitlab.com/doctormo/python-crontab/raw/master/branding.svg
-
-.. image:: https://badge.fury.io/py/python-crontab.svg
-    :target: https://badge.fury.io/py/python-crontab
-.. image:: https://img.shields.io/badge/License-LGPL%20v3-blue.svg
-    :target: https://gitlab.com/doctormo/python-crontab/raw/master/COPYING
-
-Bug Reports and Development
-===========================
-
-Please report any problems to the `GitLab issues tracker <https://gitlab.com/doctormo/python-crontab/issues>`_. Please use Git and push patches to the `GitLab project code hosting <https://gitlab.com/doctormo/python-crontab>`_.
-
-**Note:** If you get the error ``TypeError: __init__() takes exactly 2 arguments`` when using CronTab, you have the wrong module installed. You need to install ``python-crontab`` and not ``crontab`` from pypi or your local package manager and try again.
-
-Description
-===========
-
-Crontab module for reading and writing crontab files and accessing the system cron
-automatically and simply using a direct API.
-
-Comparing the `below chart <http://en.wikipedia.org/wiki/Cron#CRON_expression>`_
-you will note that W, L, # and ? symbols are not supported as they are not
-standard Linux or SystemV crontab format.
-
-+-------------+-----------+-----------------+-------------------+-------------+
-|Field Name   |Mandatory  |Allowed Values   |Special Characters |Extra Values |
-+=============+===========+=================+===================+=============+
-|Minutes      |Yes        |0-59             |\* / , -           | < >         |
-+-------------+-----------+-----------------+-------------------+-------------+
-|Hours        |Yes        |0-23             |\* / , -           | < >         |
-+-------------+-----------+-----------------+-------------------+-------------+
-|Day of month |Yes        |1-31             |\* / , -           | < >         |
-+-------------+-----------+-----------------+-------------------+-------------+
-|Month        |Yes        |1-12 or JAN-DEC  |\* / , -           | < >         |
-+-------------+-----------+-----------------+-------------------+-------------+
-|Day of week  |Yes        |0-6 or SUN-SAT   |\* / , -           | < >         |
-+-------------+-----------+-----------------+-------------------+-------------+
-
-Extra Values are '<' for minimum value, such as 0 for minutes or 1 for months.
-And '>' for maximum value, such as 23 for hours or 12 for months.
-
-Supported special cases allow crontab lines to not use fields.
-These are the supported aliases which are not available in SystemV mode:
-
-=========== ============
-Case        Meaning    
-=========== ============
-@reboot     Every boot 
-@hourly     0 * * * *  
-@daily      0 0 * * *  
-@weekly     0 0 * * 0  
-@monthly    0 0 1 * *  
-@yearly     0 0 1 1 *  
-@annually   0 0 1 1 *  
-@midnight   0 0 * * *  
-=========== ============
-
-How to Use the Module
-=====================
-
-**Note:** Several users have reported their new crontabs not saving automatically or that the module doesn't do anything. You **MUST** use write() if you want your edits to be saved out. See below for full details on the use of the write function.
-
-Getting access to a crontab can happen in five ways, three system methods that
-will work only on Unix and require you to have the right permissions::
-
-    from crontab import CronTab
-
-    empty_cron    = CronTab()
-    my_user_cron  = CronTab(user=True)
-    users_cron    = CronTab(user='username')
-
-And two ways from non-system sources that will work on Windows too::
-
-    file_cron = CronTab(tabfile='filename.tab')
-    mem_cron = CronTab(tab="""
-      * * * * * command
-    """)
-
-Special per-command user flag for vixie cron format (new in 1.9)::
-
-    system_cron = CronTab(tabfile='/etc/crontab', user=False)
-    job = system_cron[0]
-    job.user != None
-    system_cron.new(command='new_command', user='root')
-
-Creating a new job is as simple as::
-
-    job  = cron.new(command='/usr/bin/echo')
-
-And setting the job's time restrictions::
-
-    job.minute.during(5,50).every(5)
-    job.hour.every(4)
-    job.day.on(4, 5, 6)
-
-    job.dow.on('SUN')
-    job.dow.on('SUN', 'FRI')
-    job.month.during('APR', 'NOV')
-
-Each time restriction will clear the previous restriction::
-
-    job.hour.every(10) # Set to * */10 * * *
-    job.hour.on(2)     # Set to * 2 * * *
-
-Appending restrictions is explicit::
-
-    job.hour.every(10)  # Set to * */10 * * *
-    job.hour.also.on(2) # Set to * 2,*/10 * * *
-
-Setting all time slices at once::
-
-    job.setall(2, 10, '2-4', '*/2', None)
-    job.setall('2 10 * * *')
-
-Setting the slice to a python date object::
-
-    job.setall(time(10, 2))
-    job.setall(date(2000, 4, 2))
-    job.setall(datetime(2000, 4, 2, 10, 2))
-
-Run a jobs command. Running the job here will not effect it's
-existing schedule with another crontab process::
-
-    job_standard_output = job.run()
-
-Creating a job with a comment::
-
-    job = cron.new(command='/foo/bar', comment='SomeID')
-
-Get the comment or command for a job::
-
-    command = job.command
-    comment = job.comment
-
-Modify the comment or command on a job::
-
-    job.set_command("new_script.sh")
-    job.set_comment("New ID or comment here")
-
-Disabled or Enable Job::
-
-    job.enable()
-    job.enable(False)
-    False == job.is_enabled()
-
-Validity Check::
-
-    True == job.is_valid()
-
-Use a special syntax::
-
-    job.every_reboot()
-
-Find an existing job by command sub-match or regular expression::
-
-    iter = cron.find_command('bar') # matches foobar1
-    iter = cron.find_command(re.compile(r'b[ab]r$'))
-
-Find an existing job by comment exact match or regular expression::
-
-    iter = cron.find_comment('ID or some text')
-    iter = cron.find_comment(re.compile(' or \w'))
-
-Find an existing job by schedule::
-
-    iter = cron.find_time(2, 10, '2-4', '*/2', None)
-    iter = cron.find_time("*/2 * * * *")
-
-Clean a job of all rules::
-
-    job.clear()
-
-Iterate through all jobs, this includes disabled (commented out) cron jobs::
-
-    for job in cron:
-        print job
-
-Iterate through all lines, this includes all comments and empty lines::
-
-    for line in cron.lines:
-        print line
-
-Remove Items::
-
-    cron.remove( job )
-    cron.remove_all('echo')
-    cron.remove_all(comment='foo')
-    cron.remove_all(time='*/2')
-
-Clear entire cron of all jobs::
-
-    cron.remove_all()
-
-Write CronTab back to system or filename::
-
-    cron.write()
-
-Write CronTab to new filename::
-
-    cron.write( 'output.tab' )
-
-Write to this user's crontab (unix only)::
-
-    cron.write_to_user( user=True )
-
-Write to some other user's crontab::
-
-    cron.write_to_user( user='bob' )
-
-Validate a cron time string::
-
-    from crontab import CronSlices
-    bool = CronSlices.is_valid('0/2 * * * *')
-
-
-Environment Variables
-=====================
-
-Some versions of vixie cron support variables outside of the command line.
-Sometimes just update the envronment when commands are run, the Cronie fork
-of vixie cron also supports CRON_TZ which looks like a regular variable but
-actually changes the times the jobs are run at.
-
-Very old vixie crons don't support per-job variables, but most do.
-
-Iterate through cron level environment variables::
-
-    for (name, value) in cron.env.items():
-        print name
-        print value
-
-Create new or update cron level environment variables::
-
-    print cron.env['SHELL']
-    cron.env['SHELL'] = '/bin/bash'
-    print cron.env
-
-Each job can also have a list of environment variables::
-
-    for job in cron:
-        job.env['NEW_VAR'] = 'A'
-        print job.env
-
-
-Proceeding Unit Confusion
-=========================
-
-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.
-
-There is a special 'every' method on a job to clear the job's existing schedule
-and replace it with a simple single unit::
-
-    job.every(4).hours()  == '0 */4 * * *'
-    job.every().dom()     == '0 0 * * *'
-    job.every().month()   == '0 0 0 * *'
-    job.every(2).dows()   == '0 0 * * */2'
-
-This is a convenience method only, it does normal things with the existing api.
-
-Running the Scheduler
-=====================
-
-The module is able to run a cron tab as a daemon as long as the optional
-croniter module is installed; each process will block and errors will
-be logged (new in 2.0).
-
-(note this functionality is new and not perfect, if you find bugs report them!)
-
-Running the scheduler::
-
-    tab = CronTab(tabfile='MyScripts.tab')
-    for result in tab.run_scheduler():
-        print "This was printed to stdout by the process."
-
-Do not do this, it won't work because it returns generator function::
-
-    tab.run_scheduler()
-
-Timeout and cadence can be changed for testing or error management::
-
-    for result in tab.run_scheduler(timeout=600):
-        print "Will run jobs every 1 minutes for ten minutes from now()"
-
-    for result in tab.run_scheduler(cadence=1, warp=True):
-        print "Will run jobs every 1 second, counting each second as 1 minute"
-
-Frequency Calculation
-=====================
-
-Every job's schedule has a frequency. We can attempt to calculate the number
-of times a job would execute in a give amount of time. We have three simple
-methods::
-
-    job.setall("1,2 1,2 * * *")
-    job.frequency_per_day() == 4
-
-The per year frequency method will tell you how many days a year the
-job would execute::
-
-    job.setall("* * 1,2 1,2 *")
-    job.frequency_per_year(year=2010) == 4
-
-These are combined to give the number of times a job will execute in any year::
-
-    job.setall("1,2 1,2 1,2 1,2 *")
-    job.frequency(year=2010) == 16
-
-Frequency can be quickly checked using python built-in operators::
-
-    job < "*/2 * * * *"
-    job > job2
-    job.slices == "*/5"
-
-Log Functionality
-=================
-
-The log functionality will read a cron log backwards to find you the last run
-instances of your crontab and cron jobs.
-
-The crontab will limit the returned entries to the user the crontab is for::
-
-    cron = CronTab(user='root')
-
-    for d in cron.log:
-        print d['pid'] + " - " + d['date']
-
-Each job can return a log iterator too, these are filtered so you can see when
-the last execution was::
-
-    for d in cron.find_command('echo')[0].log:
-        print d['pid'] + " - " + d['date']
-
-All System CronTabs Functionality
-=================================
-
-The crontabs (note the plural) module can attempt to find all crontabs on the
-system. This works well for Linux systems with known locations for cron files
-and user spolls. It will even extract anacron jobs so you can get a picture
-of all the jobs running on your system::
-
-    from crontabs import CronTabs
-    
-    for cron in CronTabs():
-        print repr(cron)
-
-All jobs can be brought together to run various searches, all jobs are added
-to a CronTab object which can be used as documented above::
-
-   jobs = CronTabs().all.find_command('foo')
-
-Schedule Functionality
-======================
-
-If you have the croniter python module installed, you will have access to a
-schedule on each job. For example if you want to know when a job will next run::
-
-    schedule = job.schedule(date_from=datetime.now())
-
-This creates a schedule croniter based on the job from the time specified. The
-default date_from is the current date/time if not specified. Next we can get
-the datetime of the next job::
-
-    datetime = schedule.get_next()
-
-Or the previous::
-
-    datetime = schedule.get_prev()
-
-The get methods work in the same way as the default croniter, except that they
-will return datetime objects by default instead of floats. If you want the
-original functionality, pass float into the method when calling::
-
-    datetime = schedule.get_current(float)
-
-If you don't have the croniter module installed, you'll get an ImportError when
-you first try using the schedule function on your cron job object.
-
-Descriptor Functionality
-========================
-
-If you have the cron-descriptor module installed, you will be able to ask for a
-translated string which describes the frequency of the job in the current
-locale language. This should be mostly human readable.
-
-
-    print(job.description(use_24hour_time_format=True))
-
-See cron-descriptor for details of the supported languages and options.
-
-Extra Support
-=============
-
- - Support for vixie cron with username addition with user flag
- - Support for SunOS, AIX & HP with compatibility 'SystemV' mode.
- - Python 3.5.2 and Python 2.7 tested, python 2.6 removed from support.
- - Windows support works for non-system crontabs only.
-   ( see mem_cron and file_cron examples above for usage )

+ 0 - 123
desktop/core/ext-py/python-crontab-2.3.6/cronlog.py

@@ -1,123 +0,0 @@
-#
-# Copyright 2013, Martin Owens <doctormo@gmail.com>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Access logs in known locations to find information about them.
-"""
-
-import os
-import re
-import codecs
-import platform
-
-PY3 = platform.python_version()[0] == '3'
-
-if PY3:
-     # pylint: disable=W0622
-     unicode = str
-     basestring = str
-
-from dateutil import parser as dateparse
-
-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):
-        self.filename = filename
-        self.mass = mass
-        self.size = -1
-        self.read = -1
-        self.pipe = None
-
-    def __enter__(self):
-        self.size = os.stat(self.filename)[6]
-        self.pipe = codecs.open(self.filename, 'r', encoding='utf-8')
-        return self
-
-    def __exit__(self, error_type, value, traceback):
-        self.pipe.close()
-
-    def __iter__(self):
-        if self.pipe is None:
-            with self as reader:
-                for (offset, line) in reader.readlines():
-                    yield line
-        else:
-            for (offset, line) in self.readlines():
-                yield line
-
-    def readlines(self, until=0):
-        """Iterator for reading lines from a file backwards"""
-        if not self.pipe or self.pipe.closed:
-            raise IOError("Can't readline, no opened file.")
-        # Always seek to the end of the file, this accounts for file updates
-        # that happen during our running process.
-        location = self.size
-        halfline = ''
-
-        while location > until:
-            location -= self.mass
-            mass = self.mass
-            if location < 0:
-                mass = self.mass + location
-                location = 0
-            self.pipe.seek(location)
-            line = self.pipe.read(mass) + halfline
-            data = line.split('\n')
-            if location != 0:
-                halfline = data.pop(0)
-            loc = location + mass
-            data.reverse()
-            for line in data:
-                if line.strip() == '':
-                    continue
-                yield (loc, line)
-                loc -= len(line)
-
-
-
-class CronLog(LogReader):
-    """Use the LogReader to make a Cron specific log reader"""
-    def __init__(self, filename='/var/log/syslog', user=None):
-        LogReader.__init__(self, filename)
-        self.user = user
-
-    def for_program(self, command):
-        """Return log entries for this specific command name"""
-        return ProgramLog(self, command)
-
-    def __iter__(self):
-        for line in super(CronLog, self).__iter__():
-            match = re.match(MATCHER, unicode(line))
-            datum = match and match.groupdict()
-            if datum and (not self.user or datum['user'] == self.user):
-                datum['date'] = dateparse.parse(datum['date'])
-                yield datum
-
-
-class ProgramLog(object):
-    """Specific log control for a single command/program"""
-    def __init__(self, log, command):
-        self.log = log
-        self.command = command
-
-    def __iter__(self):
-        for entry in self.log:
-            if entry['cmd'] == unicode(self.command):
-                yield entry
-

+ 0 - 1346
desktop/core/ext-py/python-crontab-2.3.6/crontab.py

@@ -1,1346 +0,0 @@
-#
-# Copyright 2017, Martin Owens <doctormo@gmail.com>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-# pylint: disable=logging-format-interpolation,too-many-lines
-"""
-from crontab import CronTab
-import sys
-
-# Create a new non-installed crontab
-cron = CronTab(tab='')
-job  = cron.new(command='/usr/bin/echo')
-
-job.minute.during(5,50).every(5)
-job.hour.every(4)
-
-job.dow.on('SUN')
-job.month.during('APR', 'JUN')
-job.month.also.during('OCT', 'DEC')
-
-job.every(2).days()
-job.setall(1, 12, None, None, None)
-
-job2 = cron.new(command='/foo/bar', comment='SomeID')
-job2.every_reboot()
-
-jobs = list(cron.find_command('bar'))
-job3 = jobs[0]
-job3.clear()
-job3.minute.every(1)
-
-sys.stdout.write(str(cron.render()))
-
-job3.enable(False)
-
-for job4 in cron.find_command('echo'):
-    sys.stdout.write(job4)
-
-for job5 in cron.find_comment('SomeID'):
-    sys.stdout.write(job5)
-
-for job6 in cron:
-    sys.stdout.write(job6)
-
-for job7 in cron:
-    job7.every(3).hours()
-    sys.stdout.write(job7)
-    job7.every().dow()
-
-cron.remove_all(command='/foo/bar')
-cron.remove_all(comment='This command')
-cron.remove_all(time='* * * * *')
-cron.remove_all()
-
-output = cron.render()
-
-cron.write()
-
-cron.write(filename='/tmp/output.txt')
-
-#cron.write_to_user(user=True)
-
-#cron.write_to_user(user='root')
-
-# Croniter Extentions allow you to ask for the scheduled job times, make
-# sure you have croniter installed, it's not a hard dependancy.
-
-job3.schedule().get_next()
-job3.schedule().get_prev()
-
-"""
-
-import os
-import re
-import shlex
-
-import types
-import codecs
-import logging
-import tempfile
-import platform
-import subprocess as sp
-
-from time import sleep
-from datetime import time, date, datetime, timedelta
-
-try:
-    from collections import OrderedDict
-except ImportError:
-    # python 2.6 and below causes this error
-    try:
-        from ordereddict import OrderedDict
-    except ImportError:
-        raise ImportError("OrderedDict is required for python-crontab, you can"
-                          " install ordereddict 1.1 from pypi for python2.6")
-
-__pkgname__ = 'python-crontab'
-__version__ = '2.3.6'
-
-ITEMREX = re.compile(r'^\s*([^@#\s]+)\s+([^@#\s]+)\s+([^@#\s]+)\s+([^@#\s]+)'
-                     r'\s+([^@#\s]+)\s+([^\n]*?)(\s+#\s*([^\n]*)|$)')
-SPECREX = re.compile(r'^\s*@(\w+)\s([^#\n]*)(\s+#\s*([^\n]*)|$)')
-DEVNULL = ">/dev/null 2>&1"
-
-WEEK_ENUM = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
-
-MONTH_ENUM = [None, 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug',
-              'sep', 'oct', 'nov', 'dec']
-
-SPECIALS = {"reboot":   '@reboot',
-            "hourly":   '0 * * * *',
-            "daily":    '0 0 * * *',
-            "weekly":   '0 0 * * 0',
-            "monthly":  '0 0 1 * *',
-            "yearly":   '0 0 1 1 *',
-            "annually": '0 0 1 1 *',
-            "midnight": '0 0 * * *'}
-
-SPECIAL_IGNORE = ['midnight', 'annually']
-
-S_INFO = [
-    {'max': 59, 'min': 0, 'name': 'Minutes'},
-    {'max': 23, 'min': 0, 'name': 'Hours'},
-    {'max': 31, 'min': 1, 'name': 'Day of Month'},
-    {'max': 12, 'min': 1, 'name': 'Month', 'enum': MONTH_ENUM},
-    {'max': 6, 'min': 0, 'name': 'Day of Week', 'enum': WEEK_ENUM},
-]
-
-# Detect Python3 and which OS for temperments.
-PY3 = platform.python_version()[0] == '3'
-WINOS = platform.system() == 'Windows'
-SYSTEMV = not WINOS and os.uname()[0] in ["SunOS", "AIX", "HP-UX"]
-SYSTEMV = not WINOS and (
-    os.uname()[0] in ["SunOS", "AIX", "HP-UX"]
-    or
-    os.uname()[4] in ["mips"]
-)
-
-# Switch this on if you want your crontabs to have zero padding.
-ZERO_PAD = False
-
-LOG = logging.getLogger('crontab')
-
-CRONCMD = "/usr/bin/crontab"
-SHELL = os.environ.get('SHELL', '/bin/sh')
-# The shell won't actually work on windows here, but
-# it should be updated later in the below conditional.
-
-# pylint: disable=W0622,invalid-name,too-many-public-methods
-# pylint: disable=function-redefined,too-many-instance-attributes
-current_user = lambda: None
-if not WINOS:
-    import pwd
-    def current_user():
-        """Returns the username of the current user"""
-        return pwd.getpwuid(os.getuid())[0]
-
-if PY3:
-    unicode = str
-    basestring = str
-
-def open_pipe(cmd, *args, **flags):
-    """Runs a program and orders the arguments for compatability.
-
-    a. keyword args are flags and always appear /before/ arguments for bsd
-    """
-    cmd_args = tuple(shlex.split(cmd))
-    env = flags.pop('env', None)
-    for (key, value) in flags.items():
-        if len(key) == 1:
-            cmd_args += ("-%s" % key),
-            if value is not None:
-                cmd_args += unicode(value),
-        else:
-            cmd_args += ("--%s=%s" % (key, value)),
-    args = tuple(arg for arg in (cmd_args + tuple(args)) if arg)
-    return sp.Popen(args, stdout=sp.PIPE, stderr=sp.PIPE, env=env)
-
-def _unicode(text):
-    """Convert to the best string format for this python version"""
-    if isinstance(text, str) and not PY3:
-        return unicode(text, 'utf-8')
-    if isinstance(text, bytes) and PY3:
-        return text.decode('utf-8')
-    return text
-
-
-class CronTab(object):
-    """
-    Crontab object which can access any time based cron using the standard.
-
-    user    - Set the user of the crontab (default: None)
-      * 'user' = Load from $username's crontab (instead of tab or tabfile)
-      * None   = Don't load anything from any user crontab.
-      * True   = Load from current $USER's crontab (unix only)
-      * False  = This is a system crontab, each command has a username
-
-    tab     - Use a string variable as the crontab instead of installed crontab
-    tabfile - Use a file for the crontab instead of installed crontab
-    log     - Filename for logfile instead of /var/log/syslog
-
-    """
-    def __init__(self, user=None, tab=None, tabfile=None, log=None):
-        self.lines = None
-        self.crons = None
-        self.filen = None
-        self.env = None
-        self._parked_env = OrderedDict()
-        # Protect windows users
-        self.root = not WINOS and os.getuid() == 0
-        # Storing user flag / username
-        self._user = user
-        # Load string or filename as inital crontab
-        self.intab = tab
-        self.read(tabfile)
-        self._log = log
-
-    @property
-    def log(self):
-        """Returns the CronLog object for this tab (user or root tab only)"""
-        from cronlog import CronLog
-        if self._log is None or isinstance(self._log, basestring):
-            self._log = CronLog(self._log, user=self.user or 'root')
-        return self._log
-
-    @property
-    def user(self):
-        """Return user's username of this crontab if applicable"""
-        if self._user is True:
-            return current_user()
-        return self._user
-
-    @property
-    def user_opt(self):
-        """Returns the user option for the crontab commandline"""
-        # Fedora and Mac require the current user to not specify
-        # But Ubuntu/Debian doesn't care. Be careful here.
-        if self._user and self._user is not True:
-            if self._user != current_user():
-                return {'u': self._user}
-        return {}
-
-    def __setattr__(self, name, value):
-        """Catch setting crons and lines directly"""
-        if name == 'lines' and value:
-            for line in value:
-                self.append(CronItem.from_line(line, cron=self), line, read=True)
-        elif name == 'crons' and value:
-            raise AttributeError("You can NOT set crons attribute directly")
-        else:
-            super(CronTab, self).__setattr__(name, value)
-
-    def read(self, filename=None):
-        """
-        Read in the crontab from the system into the object, called
-        automatically when listing or using the object. use for refresh.
-        """
-        self.crons = []
-        self.lines = []
-        self.env = OrderedVariableList()
-        lines = []
-
-        if self.intab is not None:
-            lines = self.intab.split('\n')
-
-        elif filename:
-            self.filen = filename
-            with codecs.open(filename, 'r', encoding='utf-8') as fhl:
-                lines = fhl.readlines()
-
-        elif self.user:
-            (out, err) = open_pipe(CRONCMD, l='', **self.user_opt).communicate()
-            if err and 'no crontab for' in unicode(err):
-                pass
-            elif err:
-                raise IOError("Read crontab %s: %s" % (self.user, err))
-            lines = out.decode('utf-8').split("\n")
-
-        self.lines = lines
-
-    def append(self, item, line='', read=False):
-        """Append a CronItem object to this CronTab"""
-        if item.is_valid():
-            item.env.update(self._parked_env)
-            self._parked_env = OrderedDict()
-            if read and not item.comment and self.lines and \
-              self.lines[-1] and self.lines[-1][0] == '#':
-                item.set_comment(self.lines.pop()[1:].strip())
-
-            self.crons.append(item)
-            self.lines.append(item)
-        elif '=' in line:
-            if ' ' not in line or line.index('=') < line.index(' '):
-                (name, value) = line.split('=', 1)
-                value = value.strip()
-                for quot in "\"'":
-                    if value[0] == quot and value[-1] == quot:
-                        value = value.strip(quot)
-                        break
-                self._parked_env[name.strip()] = value
-        else:
-            if not self.crons and self._parked_env:
-                self.env.update(self._parked_env)
-                self._parked_env = OrderedDict()
-            self.lines.append(line.replace('\n', ''))
-
-    def write(self, filename=None, user=None, errors=False):
-        """Write the crontab to it's source or a given filename."""
-        if filename:
-            self.filen = filename
-        elif user is not None:
-            self.filen = None
-            self.intab = None
-            self._user = user
-
-        # Add to either the crontab or the internal tab.
-        if self.intab is not None:
-            self.intab = self.render()
-            # And that's it if we never saved to a file
-            if not self.filen:
-                return
-
-        if self.filen:
-            fileh = open(self.filen, 'wb')
-        else:
-            filed, path = tempfile.mkstemp()
-            fileh = os.fdopen(filed, 'wb')
-
-        fileh.write(self.render(errors=errors).encode('utf-8'))
-        fileh.close()
-
-        if not self.filen:
-            # Add the entire crontab back to the user crontab
-            if self.user:
-                proc = open_pipe(CRONCMD, path, **self.user_opt)
-                # This could do with being cleaned up quite a bit
-                proc.wait()
-                proc.stdout.close()
-                proc.stderr.close()
-                os.unlink(path)
-            else:
-                os.unlink(path)
-                raise IOError("Please specify user or filename to write.")
-
-    def write_to_user(self, user=True):
-        """Write the crontab to a user (or root) instead of a file."""
-        return self.write(user=user)
-
-    def run_pending(self, **kwargs):
-        """Run all commands in this crontab if pending (generator)"""
-        for job in self:
-            ret = job.run_pending(**kwargs)
-            if ret not in [None, -1]:
-                yield ret
-
-    def run_scheduler(self, timeout=-1, **kwargs):
-        """Run the CronTab as an internal scheduler (generator)"""
-        count = 0
-        while count != timeout:
-            now = datetime.now()
-            if 'warp' in kwargs:
-                now += timedelta(seconds=count * 60)
-            for value in self.run_pending(now=now):
-                yield value
-
-            sleep(kwargs.get('cadence', 60))
-            count += 1
-
-    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?
-        """
-        crons = []
-        for line in self.lines:
-            if isinstance(line, (unicode, str)):
-                if line.strip().startswith('#') or not line.strip():
-                    crons.append(line)
-                elif not errors:
-                    crons.append('# DISABLED LINE\n# ' + line)
-                else:
-                    raise ValueError("Invalid line: %s" % line)
-            elif isinstance(line, CronItem):
-                if not line.is_valid() and not errors:
-                    line.enabled = False
-                crons.append(unicode(line))
-
-        # Environment variables are attached to cron lines so order will
-        # always work no matter how you add lines in the middle of the stack.
-        result = unicode(self.env) + u'\n'.join(crons)
-        if result and result[-1] not in (u'\n', u'\r'):
-            result += u'\n'
-        return result
-
-    def new(self, command='', comment='', user=None):
-        """
-        Create a new cron with a command and comment.
-
-        Returns the new CronItem object.
-        """
-        if not user and self.user is False:
-            raise ValueError("User is required for system crontabs.")
-        item = CronItem(command, comment, user=user, cron=self)
-        self.append(item)
-        return item
-
-    def find_command(self, command):
-        """Return an iter of jobs matching any part of the command."""
-        for job in list(self.crons):
-            if isinstance(command, type(ITEMREX)):
-                if command.findall(job.command):
-                    yield job
-            elif command in job.command:
-                yield job
-
-    def find_comment(self, comment):
-        """Return an iter of jobs that match the comment field exactly."""
-        for job in list(self.crons):
-            if isinstance(comment, type(ITEMREX)):
-                if comment.findall(job.comment):
-                    yield job
-            elif comment == job.comment:
-                yield job
-
-    def find_time(self, *args):
-        """Return an iter of jobs that match this time pattern"""
-        for job in list(self.crons):
-            if job.slices == CronSlices(*args):
-                yield job
-
-    @property
-    def commands(self):
-        """Return a generator of all unqiue commands used in this crontab"""
-        returned = []
-        for cron in self.crons:
-            if cron.command not in returned:
-                yield cron.command
-                returned.append(cron.command)
-
-    @property
-    def comments(self):
-        """Return a generator of all unique comments/Id used in this crontab"""
-        returned = []
-        for cron in self.crons:
-            if cron.comment and cron.comment not in returned:
-                yield cron.comment
-                returned.append(cron.comment)
-
-    def remove_all(self, *args, **kwargs):
-        """Removes all crons using the stated command OR that have the
-        stated comment OR removes everything if no arguments specified.
-
-           command - Remove all with this command
-           comment - Remove all with this comment or ID
-           time    - Remove all with this time code
-        """
-        if args:
-            raise AttributeError("Invalid use: remove_all(command='cmd')")
-        if 'command' in kwargs:
-            return self.remove(*self.find_command(kwargs['command']))
-        elif 'comment' in kwargs:
-            return self.remove(*self.find_comment(kwargs['comment']))
-        elif 'time' in kwargs:
-            return self.remove(*self.find_time(kwargs['time']))
-        return self.remove(*self.crons[:])
-
-    def remove(self, *items):
-        """Remove a selected cron from the crontab."""
-        result = 0
-        for item in items:
-            if isinstance(item, (list, tuple, types.GeneratorType)):
-                for subitem in item:
-                    result += self._remove(subitem)
-            elif isinstance(item, CronItem):
-                result += self._remove(item)
-            else:
-                raise TypeError("You may only remove CronItem objects, "\
-                    "please use remove_all() to specify by name, id, etc.")
-        return result
-
-    def _remove(self, item):
-        """Internal removal of an item"""
-        # Manage siblings when items are deleted
-        for sibling in self.lines[self.lines.index(item)+1:]:
-            if isinstance(sibling, CronItem):
-                env = sibling.env
-                sibling.env = item.env
-                sibling.env.update(env)
-                sibling.env.job = sibling
-                break
-            elif sibling == '':
-                self.lines.remove(sibling)
-            else:
-                break
-
-        self.crons.remove(item)
-        self.lines.remove(item)
-        return 1
-
-    def __repr__(self):
-        kind = 'System ' if self._user is False else ''
-        if self.filen:
-            return "<%sCronTab '%s'>" % (kind, self.filen)
-        elif self.user and not self.user_opt:
-            return "<My CronTab>"
-        elif self.user:
-            return "<User CronTab '%s'>" % self.user
-        return "<Unattached %sCronTab>" % kind
-
-    def __iter__(self):
-        """Return generator so we can track jobs after removal"""
-        for job in list(self.crons.__iter__()):
-            yield job
-
-    def __getitem__(self, i):
-        return self.crons[i]
-
-    def __unicode__(self):
-        return self.render()
-
-    def __len__(self):
-        return len(self.crons)
-
-    def __str__(self):
-        return self.render()
-
-
-class CronItem(object):
-    """
-    An item which objectifies a single line of a crontab and
-    May be considered to be a cron job object.
-    """
-    def __init__(self, command='', comment='', user=None, cron=None):
-        self.cron = cron
-        self.user = user
-        self.valid = False
-        self.enabled = True
-        self.special = False
-        self.comment = None
-        self.command = None
-        self.last_run = None
-        self.env = OrderedVariableList(job=self)
-
-        # Marker labels Ansible jobs etc
-        self.marker = None
-        self.pre_comment = False
-        self._log = None
-
-        # Initalise five cron slices using static info.
-        self.slices = CronSlices()
-
-        self.set_comment(comment)
-
-        if command:
-            self.set_command(command)
-            self.valid = True
-
-    @classmethod
-    def from_line(cls, line, user=None, cron=None):
-        """Generate CronItem from a cron-line and parse out command and comment"""
-        obj = cls(user=user, cron=cron)
-        obj.parse(line.strip())
-        return obj
-
-    def delete(self):
-        """Delete this item and remove it from it's parent"""
-        if not self.cron:
-            raise UnboundLocalError("Cron item is not in a crontab!")
-        else:
-            self.cron.remove(self)
-
-    def set_command(self, cmd):
-        """Set the command and filter as needed"""
-        self.command = cmd.strip()
-
-    def set_comment(self, cmt):
-        """Set the comment and don't filter"""
-        if cmt and cmt[:8] == 'Ansible:':
-            self.marker = 'Ansible'
-            self.pre_comment = True
-            self.comment = cmt[8:].lstrip()
-        else:
-            self.comment = cmt
-
-    def parse(self, line):
-        """Parse a cron line string and save the info as the objects."""
-        line = _unicode(line)
-        if not line or line[0] == '#':
-            self.enabled = False
-            line = line[1:].strip()
-        # We parse all lines so we can detect disabled entries.
-        self._set_parse(ITEMREX.findall(line))
-        self._set_parse(SPECREX.findall(line))
-
-    def _set_parse(self, result):
-        """Set all the parsed variables into the item"""
-        if not result:
-            return
-        self.comment = result[0][-1]
-        if self.cron.user is False:
-            # Special flag to look for per-command user
-            ret = result[0][-3].split(None, 1)
-            self.set_command(ret[-1])
-            if len(ret) == 2:
-                self.user = ret[0]
-            else:
-                self.valid = False
-                self.enabled = False
-                LOG.error(str("Missing user or command in system cron line."))
-        else:
-            self.set_command(result[0][-3])
-        try:
-            self.setall(*result[0][:-3])
-            self.valid = True
-        except (ValueError, KeyError) as err:
-            if self.enabled:
-                LOG.error(str(err))
-            self.valid = False
-            self.enabled = False
-
-    def enable(self, enabled=True):
-        """Set if this cron job is enabled or not"""
-        if enabled in [True, False]:
-            self.enabled = enabled
-        return self.enabled
-
-    def is_enabled(self):
-        """Return true if this job is enabled (not commented out)"""
-        return self.enabled
-
-    def is_valid(self):
-        """Return true if this job is valid"""
-        return self.valid
-
-    def render(self):
-        """Render this set cron-job to a string"""
-        self.command = _unicode(self.command)
-        user = ''
-        if self.cron and self.cron.user is False:
-            if not self.user:
-                raise ValueError("Job to system-cron format, no user set!")
-            user = self.user + ' '
-        result = u"%s %s%s" % (unicode(self.slices), user, self.command)
-        if self.comment:
-            comment = self.comment = _unicode(self.comment)
-            if self.marker:
-                comment = u"#%s: %s" % (self.marker, comment)
-            else:
-                comment = u"# " + comment
-
-            if SYSTEMV or self.pre_comment:
-                result = comment + "\n" + result
-            else:
-                result += ' ' + comment
-
-        if not self.enabled:
-            result = u"# " + result
-        return unicode(self.env) + result
-
-    def every_reboot(self):
-        """Set to every reboot instead of a time pattern: @reboot"""
-        self.clear()
-        return self.slices.setall('@reboot')
-
-    def every(self, unit=1):
-        """
-        Replace existing time pattern with a single unit, setting all lower
-        units to first value in valid range.
-
-        For instance job.every(3).days() will be `0 0 */3 * *`
-        while job.day().every(3) would be `* * */3 * *`
-
-        Many of these patterns exist as special tokens on Linux, such as
-        `@midnight` and `@hourly`
-        """
-        return Every(self.slices, unit)
-
-    def setall(self, *args):
-        """Replace existing time pattern with these five values given as args:
-
-           job.setall("1 2 * * *")
-           job.setall(1, 2) == '1 2 * * *'
-           job.setall(0, 0, None, '>', 'SUN') == '0 0 * 12 SUN'
-        """
-        return self.slices.setall(*args)
-
-    def clear(self):
-        """Clear the special and set values"""
-        return self.slices.clear()
-
-    def frequency(self, year=None):
-        """Returns the number of times this item will execute in a given year
-           (defaults to this year)
-        """
-        return self.slices.frequency(year=year)
-
-    def frequency_per_year(self, year=None):
-        """Returns the number of /days/ this item will execute on in a year
-           (defaults to this year)
-        """
-        return self.slices.frequency_per_year(year=year)
-
-    def frequency_per_day(self):
-        """Returns the number of time this item will execute in any day"""
-        return self.slices.frequency_per_day()
-
-    def frequency_per_hour(self):
-        """Returns the number of times this item will execute in any hour"""
-        return self.slices.frequency_per_hour()
-
-    def run_pending(self, now=None):
-        """Runs the command if scheduled"""
-        now = now or datetime.now()
-        if self.is_enabled():
-            if self.last_run is None:
-                self.last_run = now
-
-            next_time = self.schedule(self.last_run).get_next()
-            if next_time < now:
-                self.last_run = now
-                return self.run()
-        return -1
-
-    def run(self):
-        """Runs the given command as a pipe"""
-        env = os.environ.copy()
-        env.update(self.env.all())
-        shell = self.env.get('SHELL', SHELL)
-        (out, err) = open_pipe(shell, '-c', self.command, env=env).communicate()
-        if err:
-            LOG.error(err.decode("utf-8"))
-        return out.decode("utf-8").strip()
-
-    def schedule(self, date_from=None):
-        """Return a croniter schedule if available."""
-        if not date_from:
-            date_from = datetime.now()
-        try:
-            # Croniter is an optional import
-            from croniter.croniter import croniter
-        except ImportError:
-            raise ImportError("Croniter not available. Please install croniter"
-                              " python module via pip or your package manager")
-        return croniter(self.slices.clean_render(), date_from, ret_type=datetime)
-
-    def description(self, **kw):
-        """
-        Returns a description of the crontab's schedule (if available)
-
-        **kw - Keyword arguments to pass to cron_descriptor (see docs)
-        """
-        try:
-            from cron_descriptor import ExpressionDescriptor
-        except ImportError:
-            raise ImportError("cron_descriptor not available. Please install"\
-              "cron_descriptor python module via pip or your package manager")
-
-        exdesc = ExpressionDescriptor(self.slices.clean_render(), **kw)
-        return exdesc.get_description()
-
-    @property
-    def log(self):
-        """Return a cron log specific for this job only"""
-        if not self._log and self.cron:
-            self._log = self.cron.log.for_program(self.command)
-        return self._log
-
-    @property
-    def minute(self):
-        """Return the minute slice"""
-        return self.slices[0]
-
-    @property
-    def minutes(self):
-        """Same as minute"""
-        return self.minute
-
-    @property
-    def hour(self):
-        """Return the hour slice"""
-        return self.slices[1]
-
-    @property
-    def hours(self):
-        """Same as hour"""
-        return self.hour
-
-    @property
-    def day(self):
-        """Return the day slice"""
-        return self.dom
-
-    @property
-    def dom(self):
-        """Return the day-of-the month slice"""
-        return self.slices[2]
-
-    @property
-    def month(self):
-        """Return the month slice"""
-        return self.slices[3]
-
-    @property
-    def months(self):
-        """Same as month"""
-        return self.month
-
-    @property
-    def dow(self):
-        """Return the day of the week slice"""
-        return self.slices[4]
-
-    def __repr__(self):
-        return "<CronItem '%s'>" % unicode(self)
-
-    def __len__(self):
-        return len(unicode(self))
-
-    def __getitem__(self, key):
-        return self.slices[key]
-
-    def __lt__(self, value):
-        return self.frequency() < CronSlices(value).frequency()
-
-    def __gt__(self, value):
-        return self.frequency() > CronSlices(value).frequency()
-
-    def __str__(self):
-        return self.__unicode__()
-
-    def __unicode__(self):
-        if not self.is_valid() and self.enabled:
-            raise ValueError('Refusing to render invalid crontab.'
-                             ' Disable to continue.')
-        return self.render()
-
-
-class Every(object):
-    """Provide an interface to the job.every() method:
-        Available Calls:
-          minute, minutes, hour, hours, dom, doms, month, months, dow, dows
-
-       Once run all units will be cleared (set to *) then proceeding units
-       will be set to '0' and the target unit will be set as every x units.
-    """
-    def __init__(self, item, units):
-        self.slices = item
-        self.unit = units
-        for (key, name) in enumerate(['minute', 'hour', 'dom', 'month', 'dow',
-                                      'min', 'hour', 'day', 'moon', 'weekday']):
-            setattr(self, name, self.set_attr(key % 5))
-            setattr(self, name+'s', self.set_attr(key % 5))
-
-    def set_attr(self, target):
-        """Inner set target, returns function"""
-        def innercall():
-            """Returned inner call for setting slice targets"""
-            self.slices.clear()
-            # Day-of-week is actually a level 2 set, not level 4.
-            for key in range(target == 4 and 2 or target):
-                self.slices[key].on('<')
-            self.slices[target].every(self.unit)
-        return innercall
-
-    def year(self):
-        """Special every year target"""
-        if self.unit > 1:
-            raise ValueError("Invalid value '%s', outside 1 year" % self.unit)
-        self.slices.setall('@yearly')
-
-
-class CronSlices(list):
-    """Controls a list of five time 'slices' which reprisent:
-        minute frequency, hour frequency, day of month frequency,
-        month requency and finally day of the week frequency.
-     """
-    def __init__(self, *args):
-        super(CronSlices, self).__init__([CronSlice(info) for info in S_INFO])
-        self.special = None
-        self.setall(*args)
-        self.is_valid = self.is_self_valid
-
-    def is_self_valid(self, *args):
-        """Object version of is_valid"""
-        return CronSlices.is_valid(*(args or (self,)))
-
-    @classmethod
-    def is_valid(cls, *args): #pylint: disable=method-hidden
-        """Returns true if the arguments are valid cron pattern"""
-        try:
-            return bool(cls(*args))
-        except (ValueError, KeyError):
-            return False
-
-    def setall(self, *slices):
-        """Parses the various ways date/time frequency can be specified"""
-        self.clear()
-        if len(slices) == 1:
-            (slices, self.special) = self._parse_value(slices[0])
-            if slices[0] == '@reboot':
-                return
-        if id(slices) == id(self):
-            raise AssertionError("Can not set cron to itself!")
-        for set_a, set_b in zip(self, slices):
-            set_a.parse(set_b)
-
-    @staticmethod
-    def _parse_value(value):
-        """Parse a single value into an array of slices"""
-        if isinstance(value, basestring) and value:
-            return CronSlices._parse_str(value)
-        if isinstance(value, CronItem):
-            return value.slices, None
-        elif isinstance(value, datetime):
-            return [value.minute, value.hour, value.day, value.month, '*'], None
-        elif isinstance(value, time):
-            return [value.minute, value.hour, '*', '*', '*'], None
-        elif isinstance(value, date):
-            return [0, 0, value.day, value.month, '*'], None
-            # It might be possible to later understand timedelta objects
-            # but there's no convincing mathematics to do the conversion yet.
-        elif not isinstance(value, (list, tuple)):
-            raise ValueError("Unknown type: {}".format(type(value).__name__))
-        return value, None
-
-    @staticmethod
-    def _parse_str(value):
-        """Parse a string which contains slice information"""
-        key = value.lstrip('@').lower()
-        if value.count(' ') == 4:
-            return value.strip().split(' '), None
-        elif key in SPECIALS.keys():
-            return SPECIALS[key].split(' '), '@' + key
-        elif value.startswith('@'):
-            raise ValueError("Unknown special '{}'".format(value))
-        return [value], None
-
-    def clean_render(self):
-        """Return just numbered parts of this crontab"""
-        return ' '.join([unicode(s) for s in self])
-
-    def render(self):
-        "Return just the first part of a cron job (the numbers or special)"
-        slices = self.clean_render()
-        if self.special:
-            return self.special
-        elif not SYSTEMV:
-            for (name, value) in SPECIALS.items():
-                if value == slices and name not in SPECIAL_IGNORE:
-                    return "@%s" % name
-        return slices
-
-    def clear(self):
-        """Clear the special and set values"""
-        self.special = None
-        for item in self:
-            item.clear()
-
-    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 times this item will execute
-           in a given year (default is this year)"""
-        result = 0
-        if not year:
-            year = date.today().year
-
-        weekdays = list(self[4])
-
-        for month in self[3]:
-            for day in self[2]:
-                try:
-                    if date(year, month, day).weekday() in weekdays:
-                        result += 1
-                except ValueError:
-                    continue
-        return result
-
-    def frequency_per_day(self):
-        """Returns the number of times this item will execute in any day"""
-        return len(self[0]) * len(self[1])
-
-    def frequency_per_hour(self):
-        """Returns the number of times this item will execute in any hour"""
-        return len(self[0])
-
-    def __str__(self):
-        return self.render()
-
-    def __eq__(self, arg):
-        return self.render() == CronSlices(arg).render()
-
-
-class SundayError(KeyError):
-    """Sunday was specified as 7 instead of 0"""
-    pass
-
-class Also(object):
-    """Link range values together (appending instead of replacing)"""
-    def __init__(self, obj):
-        self.obj = obj
-
-    def every(self, *a):
-        """Also every one of these"""
-        return self.obj.every(*a, also=True)
-
-    def on(self, *a):
-        """Also on these"""
-        return self.obj.on(*a, also=True)
-
-    def during(self, *a):
-        """Also during these"""
-        return self.obj.during(*a, also=True)
-
-class CronSlice(object):
-    """Cron slice object which shows a time pattern"""
-    def __init__(self, info, value=None):
-        if isinstance(info, int):
-            info = S_INFO[info]
-        self.min = info.get('min', None)
-        self.max = info.get('max', None)
-        self.name = info.get('name', None)
-        self.enum = info.get('enum', None)
-        self.parts = []
-        if value:
-            self.parse(value)
-
-    def parse(self, value):
-        """Set values into the slice."""
-        self.clear()
-        if value is not None:
-            for part in unicode(value).split(','):
-                if part.find("/") > 0 or part.find("-") > 0 or part == '*':
-                    self.parts += self.get_range(part)
-                    continue
-                self.parts.append(self.parse_value(part, sunday=0))
-
-    def render(self, resolve=False):
-        """Return the slice rendered as a crontab.
-
-        resolve - return integer values instead of enums (default False)
-
-        """
-        if not self.parts:
-            return '*'
-        return _render_values(self.parts, ',', resolve)
-
-    def __repr__(self):
-        return "<CronSlice '%s'>" % unicode(self)
-
-    def __eq__(self, value):
-        return unicode(self) == unicode(value)
-
-    def __str__(self):
-        return self.__unicode__()
-
-    def __unicode__(self):
-        return self.render()
-
-    def every(self, n_value, also=False):
-        """Set the every X units value"""
-        if not also:
-            self.clear()
-        self.parts += self.get_range(int(n_value))
-        return self.parts[-1]
-
-    def on(self, *n_value, **opts):
-        """Set the time values to the specified placements."""
-        if not opts.get('also', False):
-            self.clear()
-        for set_a in n_value:
-            self.parts += self.parse_value(set_a, sunday=0),
-        return self.parts
-
-    def during(self, vfrom, vto, also=False):
-        """Set the During value, which sets a range"""
-        if not also:
-            self.clear()
-        self.parts += self.get_range(unicode(vfrom) + '-' + unicode(vto))
-        return self.parts[-1]
-
-    @property
-    def also(self):
-        """Appends rather than replaces the new values"""
-        return Also(self)
-
-    def clear(self):
-        """clear the slice ready for new vaues"""
-        self.parts = []
-
-    def get_range(self, *vrange):
-        """Return a cron range for this slice"""
-        ret = CronRange(self, *vrange)
-        if ret.dangling is not None:
-            return [ret.dangling, ret]
-        return [ret]
-
-    def __iter__(self):
-        """Return the entire element as an iterable"""
-        ret = {}
-        # An empty part means '*' which is every(1)
-        if not self.parts:
-            self.every(1)
-        for part in self.parts:
-            if isinstance(part, CronRange):
-                for bit in part.range():
-                    ret[bit] = 1
-            else:
-                ret[int(part)] = 1
-        for val in ret:
-            yield val
-
-    def __len__(self):
-        """Returns the number of times this slice happens in it's range"""
-        return len(list(self.__iter__()))
-
-    def parse_value(self, val, sunday=None):
-        """Parse the value of the cron slice and raise any errors needed"""
-        if val == '>':
-            val = self.max
-        elif val == '<':
-            val = self.min
-        try:
-            out = get_cronvalue(val, self.enum)
-        except ValueError:
-            raise ValueError("Unrecognised %s: '%s'" % (self.name, val))
-        except KeyError:
-            raise KeyError("No enumeration for %s: '%s'" % (self.name, val))
-
-        if self.max == 6 and int(out) == 7:
-            if sunday is not None:
-                return sunday
-            raise SundayError("Detected Sunday as 7 instead of 0!")
-
-        if int(out) < self.min or int(out) > self.max:
-            raise ValueError("'{1}', not in {0.min}-{0.max} for {0.name}".format(self, val))
-        return out
-
-
-def get_cronvalue(value, enums):
-    """Returns a value as int (pass-through) or a special enum value"""
-    if isinstance(value, int):
-        return value
-    elif unicode(value).isdigit():
-        return int(str(value))
-    if not enums:
-        raise KeyError("No enumeration allowed")
-    return CronValue(unicode(value), enums)
-
-
-class CronValue(object): # pylint: disable=too-few-public-methods
-    """Represent a special value in the cron line"""
-    def __init__(self, value, enums):
-        self.text = value
-        self.value = enums.index(value.lower())
-
-    def __lt__(self, value):
-        return self.value < int(value)
-
-    def __repr__(self):
-        return unicode(self)
-
-    def __str__(self):
-        return self.text
-
-    def __int__(self):
-        return self.value
-
-
-def _render_values(values, sep=',', resolve=False):
-    """Returns a rendered list, sorted and optionally resolved"""
-    if len(values) > 1:
-        values.sort()
-    return sep.join([_render(val, resolve) for val in values])
-
-
-def _render(value, resolve=False):
-    """Return a single value rendered"""
-    if isinstance(value, CronRange):
-        return value.render(resolve)
-    if resolve:
-        return str(int(value))
-    return unicode(u'{:02d}'.format(value) if ZERO_PAD else value)
-
-
-class CronRange(object):
-    """A range between one value and another for a time range."""
-    def __init__(self, vslice, *vrange):
-        # holds an extra dangling entry, for example sundays.
-        self.dangling = None
-        self.slice = vslice
-        self.cron = None
-        self.seq = 1
-
-        if not vrange:
-            self.all()
-        elif isinstance(vrange[0], basestring):
-            self.parse(vrange[0])
-        elif isinstance(vrange[0], (int, CronValue)):
-            if len(vrange) == 2:
-                (self.vfrom, self.vto) = vrange
-            else:
-                self.seq = vrange[0]
-                self.all()
-
-    def parse(self, value):
-        """Parse a ranged value in a cronjob"""
-        if value.count('/') == 1:
-            value, seq = value.split('/')
-            try:
-                self.seq = self.slice.parse_value(seq)
-            except SundayError:
-                self.seq = 1
-                value = "0-0"
-            if self.seq < 1 or self.seq > self.slice.max:
-                raise ValueError("Sequence can not be divided by zero or max")
-        if value.count('-') == 1:
-            vfrom, vto = value.split('-')
-            self.vfrom = self.slice.parse_value(vfrom, sunday=0)
-            try:
-                self.vto = self.slice.parse_value(vto)
-            except SundayError:
-                if self.vfrom == 1:
-                    self.vfrom = 0
-                else:
-                    self.dangling = 0
-                self.vto = self.slice.parse_value(vto, sunday=6)
-            if self.vto < self.vfrom:
-                LOG.warning("Bad range '{0.vfrom}-{0.vto}'".format(self))
-        elif value == '*':
-            self.all()
-        else:
-            raise ValueError('Unknown cron range value "%s"' % value)
-
-    def all(self):
-        """Set this slice to all units between the miniumum and maximum"""
-        self.vfrom = self.slice.min
-        self.vto = self.slice.max
-
-    def render(self, resolve=False):
-        """Render the ranged value for a cronjob"""
-        value = '*'
-        if int(self.vfrom) > self.slice.min or int(self.vto) < self.slice.max:
-            if self.vfrom == self.vto:
-                value = unicode(self.vfrom)
-            else:
-                value = _render_values([self.vfrom, self.vto], '-', resolve)
-        if self.seq != 1:
-            value += "/%d" % self.seq
-        if value != '*' and SYSTEMV:
-            value = ','.join([unicode(val) for val in self.range()])
-        return value
-
-    def range(self):
-        """Returns the range of this cron slice as a iterable list"""
-        return range(int(self.vfrom), int(self.vto)+1, self.seq)
-
-    def every(self, value):
-        """Set the sequence value for this range."""
-        self.seq = int(value)
-
-    def __lt__(self, value):
-        return int(self.vfrom) < int(value)
-
-    def __gt__(self, value):
-        return int(self.vto) > int(value)
-
-    def __int__(self):
-        return int(self.vfrom)
-
-    def __str__(self):
-        return self.__unicode__()
-
-    def __unicode__(self):
-        return self.render()
-
-
-class OrderedVariableList(OrderedDict):
-    """An ordered dictionary with a linked list containing
-    the previous OrderedVariableList which this list depends.
-
-    Duplicates in this list are weeded out in favour of the previous
-    list in the chain.
-
-    This is all in aid of the ENV variables list which must exist one
-    per job in the chain.
-    """
-    def __init__(self, *args, **kw):
-        self.job = kw.pop('job', None)
-        super(OrderedVariableList, self).__init__(*args, **kw)
-
-    @property
-    def previous(self):
-        """Returns the previous env in the list of jobs in the cron"""
-        if self.job is not None and self.job.cron is not None:
-            index = self.job.cron.crons.index(self.job)
-            if index == 0:
-                return self.job.cron.env
-            return self.job.cron[index-1].env
-        return None
-
-    def all(self):
-        """
-        Returns the full dictionary, everything from this dictionary
-        plus all those in the chain above us.
-        """
-        if self.job is not None:
-            ret = self.previous.all().copy()
-            ret.update(self)
-            return ret
-        return self.copy()
-
-    def __getitem__(self, key):
-        previous = self.previous
-        if key in self:
-            return super(OrderedVariableList, self).__getitem__(key)
-        elif previous is not None:
-            return previous.all()[key]
-        raise KeyError("Environment Variable '%s' not found." % key)
-
-    def __str__(self):
-        """Constructs to variable list output used in cron jobs"""
-        ret = []
-        for key, value in self.items():
-            if self.previous:
-                if self.previous.all().get(key, None) == value:
-                    continue
-            if ' ' in unicode(value) or value == '':
-                value = '"%s"' % value
-            ret.append("%s=%s" % (key, unicode(value)))
-        ret.append('')
-        return "\n".join(ret)

+ 0 - 145
desktop/core/ext-py/python-crontab-2.3.6/crontabs.py

@@ -1,145 +0,0 @@
-#
-# Copyright 2016, Martin Owens <doctormo@gmail.com>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-The crontabs manager will list all available crontabs on the system.
-"""
-
-import os
-import sys
-import pwd
-import itertools
-
-from os import stat, access, X_OK
-from pwd import getpwuid
-from crontab import CronTab
-
-class UserSpool(list):
-    """Generates all user crontabs, yields both owned and abandoned tabs"""
-    def __init__(self, loc, tabs=None):
-        for username in self.listdir(loc):
-            tab = self.generate(loc, username)
-            if tab:
-                self.append(tab)
-        if not self:
-            tab = CronTab(user=True)
-            if tab:
-                self.append(tab)
-
-    def listdir(self, loc):
-        try:
-            return os.listdir(loc)
-        except OSError:
-            return []
-
-    def get_owner(self, path):
-        """Returns user file at path"""
-        try:
-            return getpwuid(stat(path).st_uid).pw_name
-        except KeyError:
-            return
-
-    def generate(self, loc, username):
-        path = os.path.join(loc, username)
-        if username != self.get_owner(path):
-            # Abandoned crontab pool entry!
-            return CronTab(tabfile=path)
-        return CronTab(user=username)
-
-
-class SystemTab(list):
-    """Generates all system tabs"""
-    def __init__(self, loc, tabs=None):
-        if os.path.isdir(loc):
-            for item in os.listdir(loc):
-                if item[0] == '.':
-                    continue
-                path = os.path.join(loc, item)
-                self.append(CronTab(user=False, tabfile=path))
-        elif os.path.isfile(loc):
-            self.append(CronTab(user=False, tabfile=loc))
-
-
-class AnaCronTab(list):
-    """Attempts to digest anacron entries (if possible)"""
-    def __init__(self, loc, tabs=None):
-        if tabs and os.path.isdir(loc):
-            self.append(CronTab(user=False))
-            jobs = list(tabs.all.find_command(loc))
-            if jobs:
-                for item in os.listdir(loc):
-                    self.add(loc, item, jobs[0])
-                jobs[0].delete()
-
-    def add(self, loc, item, anajob):
-        path = os.path.join(loc, item)
-        if item in ['0anacron'] or item[0] == '.' or not access(path, X_OK):
-            return
-        job = self[0].new(command=path, user=anajob.user)
-        job.set_comment('Anacron %s' % loc.split('.')[-1])
-        job.setall(anajob)
-        return job
-
-
-# Files are direct, directories are listed (recursively)
-KNOWN_LOCATIONS = [
-  # Known linux locations (Debian, RedHat, etc)
-  (UserSpool, '/var/spool/cron/crontabs/'),
-  (SystemTab, '/etc/crontab'),
-  (SystemTab, '/etc/cron.d/'),
-  # Anacron digestion (we want to know more)
-  (AnaCronTab, '/etc/cron.hourly'),
-  (AnaCronTab, '/etc/cron.daily'),
-  (AnaCronTab, '/etc/cron.weekly'),
-  (AnaCronTab, '/etc/cron.monthly'),
-  # Known MacOSX locations
-   # None
-  # Other (windows, bsd)
-   # None
-]
-
-class CronTabs(list):
-    """Singleton dictionary of all detectable crontabs"""
-    _all = None
-    _self = None
-
-    def __new__(cls, *args, **kw):
-        if not cls._self:
-            cls._self = super(CronTabs, cls).__new__(cls, *args, **kw)
-        return cls._self
-
-    def __init__(self):
-        if not self:
-            for loc in KNOWN_LOCATIONS:
-                self.add(*loc)
-
-    def add(self, cls, *args):
-        for tab in cls(*args, tabs=self):
-            self.append(tab)
-            self._all = None
-
-    @property
-    def all(self):
-        """Return a CronTab object with all jobs (read-only)"""
-        if self._all is None:
-            self._all = CronTab(user=False)
-            for tab in self:
-                for job in tab:
-                    if job.user is None:
-                        job.user = tab.user or 'unknown'
-                    self._all.append(job)
-        return self._all
-

+ 0 - 4
desktop/core/ext-py/python-crontab-2.3.6/setup.cfg

@@ -1,4 +0,0 @@
-[egg_info]
-tag_build = 
-tag_date = 0
-

+ 0 - 79
desktop/core/ext-py/python-crontab-2.3.6/setup.py

@@ -1,79 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2008-2018 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-# pylint: disable=bad-whitespace
-"""Setup the crontab module"""
-
-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.
-if os.path.exists('MANIFEST'):
-    os.remove('MANIFEST')
-
-# Grab description for Pypi
-with open('README.rst') as fhl:
-    description = fhl.read()
-
-# Used for rpm building
-RELEASE = "1"
-
-setup(
-    name             = __pkgname__,
-    version          = __version__,
-    release          = RELEASE,
-    description      = 'Python Crontab API',
-    long_description = description,
-    author           = 'Martin Owens',
-    url              = 'https://gitlab.com/doctormo/python-crontab/',
-    author_email     = 'doctormo@gmail.com',
-    test_suite       = 'tests',
-    platforms        = 'linux',
-    license          = 'LGPLv3',
-    py_modules       = ['crontab', 'crontabs', 'cronlog'],
-    provides         = ['crontab', 'crontabs', 'cronlog'],
-    install_requires = ['python-dateutil'],
-    extras_require   = {
-        'cron-schedule': ['croniter'],
-        'cron-description': ['cron-descriptor'],
-    },
-    classifiers      = [
-        'Development Status :: 5 - Production/Stable',
-        'Development Status :: 6 - Mature',
-        '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',
-        'Programming Language :: Python',
-        'Programming Language :: Python :: 2.7',
-        'Programming Language :: Python :: 3.5',
-    ],
-    options = {
-        'bdist_rpm': {
-            'build_requires': [
-                'python',
-                'python-setuptools',
-            ],
-            'release': RELEASE,
-        },
-    },
-)

+ 0 - 1
desktop/core/ext-py/python-crontab-2.3.6/tests/__init__.py

@@ -1 +0,0 @@
-

+ 0 - 7
desktop/core/ext-py/python-crontab-2.3.6/tests/data/basic.log

@@ -1,7 +0,0 @@
-A really long line which can test log lines ability to put two bits together
-First Line
-
-9
-2
-Sickem
-The End

+ 0 - 4
desktop/core/ext-py/python-crontab-2.3.6/tests/data/crontab

@@ -1,4 +0,0 @@
-
-* * * * * peter parker
-* 2 * * * driver parker
-

+ 0 - 50
desktop/core/ext-py/python-crontab-2.3.6/tests/data/crontest

@@ -1,50 +0,0 @@
-#!/usr/bin/env python
-
-import os
-import sys
-
-def main():
-    """Run this"""
-    args = sys.argv[1:]
-    loc = os.path.dirname(__file__)
-
-    if '-h' in args:
-        print('|'.join(sorted(args)))
-        return
-    elif '-e' in args:
-        sys.stderr.write('|'.join(sorted(args)) + "\n")
-        return
-    elif '-ev' in args:
-        print(os.environ.get('CR_VAR', 'FAILED') + '\n')
-        return
-
-    user = 'user'
-    if '-u' in args:
-        user = args[args.index('-u')+1]
-
-    if '-l' in args:
-        if user == 'error':
-            raise ValueError("Delibrate IO Error")
-        if not os.path.exists(os.path.join(loc, 'spool', user)):
-            sys.stderr.write("no crontab for %s\n" % user)
-            sys.exit(1)
-        fhl = open(os.path.join(loc, 'spool', user), 'r')
-        print(fhl.read())
-        return
-
-    for filename in args:
-        if filename[0] == '-' or filename == user:
-            continue
-        new_name = os.path.join(loc, 'spool', user)
-        if not os.path.exists(filename):
-            raise KeyError("Can't find file: %s" % filename)
-        if os.path.exists(new_name):
-            raise KeyError("Can't write file: %s, exists" % new_name)
-        with open(filename, 'r') as source:
-            with open(new_name, 'w') as output:
-                output.write(source.read())
-
-if __name__ == '__main__':
-    main()
-    sys.exit(0)
-

+ 0 - 3
desktop/core/ext-py/python-crontab-2.3.6/tests/data/specials.tab

@@ -1,3 +0,0 @@
-0 * * * * hourly
-0 0 * * * daily
-0 0 * * 0 weekly

+ 0 - 5
desktop/core/ext-py/python-crontab-2.3.6/tests/data/specials_enc.tab

@@ -1,5 +0,0 @@
-@hourly hourly
-@daily daily
-@midnight midnight
-@weekly weekly
-@reboot reboot

+ 0 - 32
desktop/core/ext-py/python-crontab-2.3.6/tests/data/test.log

@@ -1,32 +0,0 @@
-Apr  4 21:24:01 servername CRON[16490]: (user) CMD (userscript &> /dev/null)
-Apr  4 21:24:01 servername CRON[16489]: (root) CMD (rootscript &> /dev/null)
-Apr  4 21:24:01 servername CRON[16487]: (CRON) info (Cron information item)
-Apr  4 21:25:01 servername CRON[16496]: (user) CMD (userscript &> /dev/null)
-Apr  4 21:25:01 servername CRON[16497]: (root) CMD (shadowscript &> /dev/null)
-Apr  4 21:25:01 servername CRON[16494]: (CRON) info (Cron information item)
-Apr  4 21:26:01 servername CRON[16513]: (user) CMD (userscript &> /dev/null)
-Apr  4 21:26:01 servername CRON[16511]: (CRON) info (Cron information item)
-Apr  4 21:26:01 servername CRON[16514]: (root) CMD (rootscript &> /dev/null)
-Apr  4 21:27:01 servername CRON[16519]: (user) CMD (userscript &> /dev/null)
-Apr  4 21:27:01 servername CRON[16518]: (CRON) info (Cron information item)
-Apr  4 21:28:01 servername CRON[16523]: (user) CMD (userscript &> /dev/null)
-Apr  4 21:28:01 servername CRON[16522]: (root) CMD (rootscript &> /dev/null)
-Apr  4 21:28:01 servername CRON[16520]: (CRON) info (Cron information item)
-Apr  4 21:28:30 servername NOTCRON: Log entry that isn't a cron
-Apr  4 21:28:30 servername NOTCRON: entry in order to test
-Apr  4 21:28:31 servername NOTCRON: that these are ignored
-Apr  4 21:29:01 servername CRON[16539]: (user) CMD (userscript &> /dev/null)
-Apr  4 21:29:01 servername CRON[16538]: (CRON) info (Cron information item)
-Apr  4 21:30:01 servername CRON[16551]: (root) CMD (shadowscript &> /dev/null)
-Apr  4 21:30:01 servername CRON[16552]: (root) CMD (rootscript &> /dev/null)
-Apr  4 21:30:01 servername CRON[16554]: (user) CMD (userscript &> /dev/null)
-Apr  4 21:30:01 servername CRON[16548]: (CRON) info (Cron information item)
-Apr  4 21:31:01 servername CRON[16569]: (user) CMD (userscript &> /dev/null)
-Apr  4 21:31:01 servername CRON[16568]: (CRON) info (Cron information item)
-Apr  4 21:32:01 servername CRON[16573]: (user) CMD (userscript &> /dev/null)
-Apr  4 21:32:01 servername CRON[16574]: (root) CMD (rootscript &> /dev/null)
-Apr  4 21:32:01 servername CRON[16571]: (CRON) info (Cron information item)
-Apr  4 21:33:02 servername CRON[16588]: (user) CMD (userscript &> /dev/null)
-Apr  4 21:33:02 servername CRON[16587]: (CRON) info (Cron information item)
-Apr  4 21:34:01 servername CRON[16591]: (user) CMD (userscript &> /dev/null)
-Apr  4 21:34:01 servername CRON[16592]: (root) CMD (rootscript &> /dev/null)

+ 0 - 17
desktop/core/ext-py/python-crontab-2.3.6/tests/data/test.tab

@@ -1,17 +0,0 @@
-# First Comment
-# Edit this line to test for mistaken checks
-
-# m h dom mon dow user command
-
-*/30 * * * * firstcommand
-* 10-20/3 * * * range
-# Middle Comment
-* * * 10 * byweek # Comment One
-# * * * * * disabled
- 00 5  *   *   *      spaced    # Comment  Two
-
-# monitorCron
-*/59 * * * * python /example_app/testing.py
-
-@reboot rebooted # re-id
-# Last Comment @has this # extra

+ 0 - 120
desktop/core/ext-py/python-crontab-2.3.6/tests/test_compatibility.py

@@ -1,120 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2012 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test crontab interaction.
-"""
-
-import os
-import sys
-
-import unittest
-import crontab
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-TEST_DIR = os.path.dirname(__file__)
-
-INITAL_TAB = """
-# First Comment
-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
-    def setUpClass(cls):
-        crontab.SYSTEMV = True
-
-    @classmethod
-    def tearDownClass(cls):
-        crontab.SYSTEMV = False
-
-    def setUp(self):
-        self.crontab = crontab.CronTab(tab=INITAL_TAB)
-
-    def test_00_enabled(self):
-        """Test Compatability Mode"""
-        self.assertTrue(crontab.SYSTEMV)
-
-    def test_01_addition(self):
-        """New Job Rendering"""
-        job = self.crontab.new('addition1')
-        job.minute.during(0, 3)
-        job.hour.during(21, 23).every(1)
-        job.dom.every(1)
-
-        self.assertEqual(job.render(), '0,1,2,3 21,22,23 * * * addition1')
-
-    def test_02_addition(self):
-        """New Job Rendering"""
-        job = self.crontab.new(command='addition2')
-
-        job.minute.during(4, 9)
-        job.hour.during(2, 10).every(2)
-        job.dom.every(10)
-
-        self.assertNotEqual(job.render(), '4-9 2-10/2 */3 * * addition2')
-        self.assertEqual(job.render(), '4,5,6,7,8,9 2,4,6,8,10 1,11,21,31 * * addition2')
-
-    def test_03_specials(self):
-        """Ignore Special Symbols"""
-        tab = crontab.CronTab(tabfile=os.path.join(TEST_DIR, 'data', 'specials.tab'))
-        self.assertEqual(tab.render(), """0 * * * * hourly
-0 0 * * * daily
-0 0 * * 0 weekly
-""")
-
-    def test_04_comments(self):
-        """Comments should be on their own lines"""
-        self.assertEqual(self.crontab[0].comment, 'First Comment')
-        self.assertEqual(self.crontab.render(), INITAL_TAB)
-        job = self.crontab.new('command', comment="Test comment")
-        self.assertEqual(job.render(), "# Test comment\n* * * * * command")
-
-    def test_05_ansible(self):
-        """Crontab shouldn't break ansible cronjobs"""
-        cron = crontab.CronTab(tab="""
-#Ansible: {job_name}
-* * * * * {command}
-""")
-        self.assertEqual(cron[0].comment, '{job_name}')
-        self.assertEqual(cron[0].command, '{command}')
-        self.assertEqual(str(cron[0]), '#Ansible: {job_name}\n* * * * * {command}')
-
-    def test_06_escaped_chars(self):
-        """Do escaped chars parse correctly when read in"""
-        cron = crontab.CronTab(tab="""
-* * * * * cmd arg_with_\#_character # comment
-""")
-        self.assertEqual(cron[0].command, 'cmd arg_with_\\#_character')
-        self.assertEqual(cron[0].comment, 'comment')
-
-if __name__ == '__main__':
-    test_support.run_unittest(
-       CompatTestCase,
-    )

+ 0 - 89
desktop/core/ext-py/python-crontab-2.3.6/tests/test_croniter.py

@@ -1,89 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2013 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test croniter extention to find out when items will next happen.
-"""
-
-import os
-import sys
-from datetime import datetime
-
-sys.path.insert(0, '../')
-
-import unittest
-import crontab
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-INITAL_TAB = """
-# Basic Comment
-20 * * * * execute # comment
-"""
-
-class CroniterTestCase(unittest.TestCase):
-    """Test basic functionality of crontab."""
-    def setUp(self):
-        self.crontab = crontab.CronTab(tab=INITAL_TAB)
-        self.job = list(self.crontab.find_command('execute'))[0]
-        try:
-            import croniter
-        except ImportError:
-            self.skipTest("Croniter not installed")
-
-    def test_00_nocroniter(self):
-        """No Croniter"""
-        # Remove croniter if imported before.
-        for i in range(1, 4):
-            name = '.'.join((['croniter'] * i))
-            if name in sys.modules:
-                del sys.modules[name]
-
-        old, sys.path = sys.path, []
-        with self.assertRaises(ImportError):
-            self.job.schedule(datetime(2001, 10, 11, 1, 12, 10))
-        sys.path = old
-
-    def test_01_schedule(self):
-        """Get Scheduler"""
-        ct = self.job.schedule(datetime(2009, 10, 11, 5, 12, 10))
-        self.assertTrue(ct)
-
-    def test_02_next(self):
-        """Get Next Scheduled Items"""
-        ct = self.job.schedule(datetime(2000, 10, 11, 5, 12, 10))
-        self.assertEqual(ct.get_next(), datetime(2000, 10, 11, 5, 20, 0))
-        self.assertEqual(ct.get_next(), datetime(2000, 10, 11, 6, 20, 0))
-
-    def test_03_prev(self):
-        """Get Prev Scheduled Items"""
-        ct = self.job.schedule(datetime(2001, 10, 11, 1, 12, 10))
-        self.assertEqual(ct.get_prev(), datetime(2001, 10, 11, 0, 20, 0))
-        self.assertEqual(ct.get_prev(), datetime(2001, 10, 10, 23, 20, 0))
-
-    def test_04_current(self):
-        """Get Current Item"""
-        ct = self.job.schedule(datetime(2001, 10, 11, 1, 12, 10))
-        self.assertEqual(ct.get_current(), datetime(2001, 10, 11, 1, 12, 10))
-        self.assertEqual(ct.get_current(), datetime(2001, 10, 11, 1, 12, 10))
-
-if __name__ == '__main__':
-    test_support.run_unittest(
-       CroniterTestCase,
-    )

+ 0 - 112
desktop/core/ext-py/python-crontab-2.3.6/tests/test_crontabs.py

@@ -1,112 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2016 Martin Owens <doctormo@gmail.com>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test crontabs listing all available crontabs.
-"""
-
-import os
-import sys
-
-import unittest
-import crontab
-import crontabs
-
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-TEST_DIR = os.path.dirname(__file__)
-
-class fake_getpwuid(object):
-    def __init__(self, st):
-        self.pw_name = st
-        if st == 'error':
-            raise KeyError("Expected Error")
-
-class fake_stat(object):
-    def __init__(self, path):
-        self.st_uid = os.path.basename(path).split('_')[0]
-
-crontabs.getpwuid = fake_getpwuid
-crontabs.stat = fake_stat
-
-class AnacronSourceTab(list):
-    """This enables the anacron detection"""
-    slices = "56 4 * * 4"
-    def __init__(self, tabs=None):
-        self.append(crontab.CronTab(user=False, tab="%s root anacron_cmd %s" \
-            % (self.slices, os.path.join(TEST_DIR, 'data', 'anacron'))))
-
-crontabs.KNOWN_LOCATIONS = [
-  (AnacronSourceTab,),
-  (crontabs.UserSpool, os.path.join(TEST_DIR, 'data', 'spool')),
-  (crontabs.UserSpool, os.path.join(TEST_DIR, 'data', 'bad_spool')),
-  (crontabs.SystemTab, os.path.join(TEST_DIR, 'data', 'crontab')),
-  (crontabs.SystemTab, os.path.join(TEST_DIR, 'data', 'crontabs')),
-  (crontabs.AnaCronTab, os.path.join(TEST_DIR, 'data', 'anacron')),
-]
-
-crontab.CRONCMD = "%s %s" % (sys.executable, os.path.join(TEST_DIR, 'data', 'crontest'))
-
-class CronTabsTestCase(unittest.TestCase):
-    """Test use documentation in crontab."""
-    def setUp(self):
-        self.tabs = crontabs.CronTabs()
-
-    def assertInTabs(self, command, *users):
-        jobs = list(self.tabs.all.find_command(command))
-        self.assertEqual(len(jobs), len(users))
-        users = sorted([job.user for job in jobs])
-        self.assertEqual(users, sorted(users))
-        return jobs
-
-    def assertNotInTabs(self, command):
-        return self.assertInTabs(command)
-
-    def test_05_spool(self):
-        """Test a user spool"""
-        self.assertInTabs('do_vlog_brothers', 'hgreen', 'jgreen')
-
-    def test_06_bad_spool(self):
-        """Test no access to spool (non-root)"""
-        # IMPORTANT! This is testing the fact that the bad-spool will load
-        # the user's own crontab, in this instance this is 'user' from the
-        # crontest script. This tab is already loaded by the previous User
-        # spool and so we expect to find two of them.
-        self.assertInTabs('user_command', 'user', 'user')
-
-    def test_10_crontab_dir(self):
-        """Test crontabs loaded from system directory"""
-        self.assertInTabs('baggins', 'bilbo', 'frodo', 'plastic')
-
-    def test_11_crontab_file(self):
-        """Test a single crontab file loaded from system tab"""
-        self.assertInTabs('parker', 'driver', 'peter')
-
-    def test_20_anacron(self):
-        """Anacron digested"""
-        self.assertNotInTabs('anacron_cmd')
-        jobs = self.assertInTabs('an_command.sh', 'root')
-        self.assertEqual(str(jobs[0].slices), AnacronSourceTab.slices)
-        self.assertNotInTabs('not_command.txt')
-        
-
-if __name__ == '__main__':
-    test_support.run_unittest(CronTabsTestCase)
-

+ 0 - 66
desktop/core/ext-py/python-crontab-2.3.6/tests/test_description.py

@@ -1,66 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2016 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test optional crontab description intergration.
-"""
-
-import sys
-sys.path.insert(0, '../')
-
-import unittest
-import crontab
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-INITAL_TAB = """
-# Basic Comment
-20 10-20 */2 * * execute # At 20 minutes past the hour, between 10:00 AM and 08:59 PM, every 2 days
-"""
-
-class DescriptorTestCase(unittest.TestCase):
-    """Test basic functionality of crontab."""
-    def setUp(self):
-        self.crontab = crontab.CronTab(tab=INITAL_TAB)
-        self.job = list(self.crontab.find_command('execute'))[0]
-        try:
-            import cron_descriptor
-        except ImportError:
-            self.skipTest("Cron-descriptor module not installed")
-
-    def test_00_no_module(self):
-        """No module found"""
-        # Remove module if imported already
-        for i in range(1, 4):
-            name = '.'.join((['cron_descriptor'] * i))
-            if name in sys.modules:
-                del sys.modules[name]
-
-        old, sys.path = sys.path, []
-        with self.assertRaises(ImportError):
-            self.job.description()
-        sys.path = old
-
-    def test_01_description(self):
-        """Get Job Description"""
-        self.assertEqual(self.job.description(), self.job.comment)
-
-if __name__ == '__main__':
-    test_support.run_unittest(DescriptorTestCase)
-

+ 0 - 121
desktop/core/ext-py/python-crontab-2.3.6/tests/test_enums.py

@@ -1,121 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2011 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test crontab enumerations.
-"""
-
-import os
-import sys
-
-sys.path.insert(0, '../')
-
-import unittest
-from crontab import CronTab
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-INITAL_TAB = """
-* * * JAN     SAT          enums
-* * * MAR-APR *            ranges
-* * * *       MON,FRI,WED  multiples
-* * * *       *            com1 # Comment One
-* * * *       *            com2 # Comment One
-"""
-
-COMMANDS = [
-    'enums',
-    'ranges',
-    'multiples',
-    'com1', 'com2',
-]
-
-RESULT_TAB = """
-* * * JAN SAT enums
-* * * MAR-APR * ranges
-* * * * MON,WED,FRI multiples
-* * * * * com1 # Comment One
-* * * * * com2 # Comment One
-"""
-
-class EnumTestCase(unittest.TestCase):
-    """Test basic functionality of crontab."""
-    def setUp(self):
-        self.crontab = CronTab(tab=INITAL_TAB)
-
-    def test_01_presevation(self):
-        """All Entries Re-Rendered Correctly"""
-        self.crontab.write()
-        results = RESULT_TAB.split('\n')
-        line_no = 0
-        for line in self.crontab.intab.split('\n'):
-            self.assertEqual(str(line), results[line_no])
-            line_no += 1
-
-    def test_02_simple_enum(self):
-        """Simple Enumerations"""
-        e = list(self.crontab.find_command('enums'))[0]
-        self.assertEqual(e.month, 'JAN')
-        self.assertEqual(e.month.render(True), '1')
-        self.assertEqual(e.dow, 'SAT')
-        self.assertEqual(e.dow.render(True), '6')
-
-    def test_03_enum_range(self):
-        """Enumeration Ranges"""
-        e = list(self.crontab.find_command('ranges'))[0]
-        self.assertEqual(e.month, 'MAR-APR')
-        self.assertEqual(e.month.render(True), '3-4' )
-
-    def test_04_sets(self):
-        """Enumeration Sets"""
-        e = list(self.crontab.find_command('multiples'))[0]
-        self.assertEqual(e.dow, 'MON,WED,FRI')
-        self.assertEqual(e.dow.render(True), '1,3,5' )
-
-    def test_05_create(self):
-        """Create by Enumeration"""
-        job = self.crontab.new(command='new')
-        job.month.on('JAN')
-        job.dow.on('SUN')
-        self.assertEqual(str(job), '* * * JAN SUN new')
-
-    def test_06_create_range(self):
-        """Created Enum Range"""
-        job = self.crontab.new(command='new2')
-        job.month.during('APR', 'NOV').every(2)
-        self.assertEqual(str(job), '* * * APR-NOV/2 * new2')
-
-    def test_07_create_set(self):
-        """Created Enum Set"""
-        job = self.crontab.new(command='new3')
-        job.month.on('APR')
-        job.month.also.on('NOV','JAN')
-        self.assertEqual(str(job), '* * * JAN,APR,NOV * new3')
-
-    def test_08_find_comment(self):
-        """Comment Set"""
-        jobs = list(self.crontab.find_comment('Comment One'))
-        self.assertEqual(len(jobs), 2)
-        for job in jobs:
-            self.assertEqual(job.comment, 'Comment One')
-
-if __name__ == '__main__':
-    test_support.run_unittest(
-       EnumTestCase,
-    )

+ 0 - 220
desktop/core/ext-py/python-crontab-2.3.6/tests/test_env.py

@@ -1,220 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test the creation, reading and writing on environment variables.
-"""
-
-import os
-import sys
-sys.path.insert(0, '../')
-
-from .test_usage import TEST_DIR
-
-import unittest
-from collections import OrderedDict
-
-from crontab import CronTab
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-INITIAL_TAB = """PERSONAL_VAR=bar
-
-CRON_VAR=fork
-34 12 * * * eat_soup
-
-CRON_VAR=spoon
-35 12 * * * eat_salad
-
-CRON_VAR=knife
-36 12 * * * eat_icecream
-
-SECONDARY=fork
-38 12 * * * eat_steak
-"""
-
-class EnvTestCase(unittest.TestCase):
-    """Test vixie cron user addition."""
-    def setUp(self):
-        self.crontab = CronTab(tab=INITIAL_TAB)
-
-    def test_01_consistancy(self):
-        """Read in crontab and write out the same"""
-        self.assertEqual(INITIAL_TAB, str(self.crontab))
-
-    def test_02_top_vars(self):
-        """Whole file env variables"""
-        crontab = CronTab(tab="SHELL=dash\n")
-        self.assertEqual(str(crontab), "SHELL=dash\n")
-        self.assertEqual(crontab.env['SHELL'], 'dash')
-        crontab.env['SHELL'] = 'bash'
-        self.assertEqual(str(crontab), "SHELL=bash\n")
-        self.assertEqual(crontab.env['SHELL'], 'bash')
-
-    def test_03_get_job_var(self):
-        """Test each of the job env structures"""
-        for job, expected in zip(self.crontab, [
-            {'PERSONAL_VAR': 'bar', 'CRON_VAR': 'fork'},
-            {'PERSONAL_VAR': 'bar', 'CRON_VAR': 'spoon'},
-            {'PERSONAL_VAR': 'bar', 'CRON_VAR': 'knife'},
-            {'PERSONAL_VAR': 'bar', 'CRON_VAR': 'knife', 'SECONDARY': 'fork'},
-          ]):
-            self.assertEqual(OrderedDict(job.env.all()), expected)
-
-    def test_04_set_job_var(self):
-        """Test that variables set are applied correctly"""
-        self.crontab[1].env['CRON_VAR'] = 'javlin'
-        self.assertEqual(self.crontab[1].env.all(),
-            {'PERSONAL_VAR': 'bar', 'CRON_VAR': 'javlin'})
-        self.crontab[2].env['CRON_VAR'] = 'javlin'
-        self.assertEqual(self.crontab[2].env.all(),
-            {'PERSONAL_VAR': 'bar', 'CRON_VAR': 'javlin'})
-        self.assertEqual(self.crontab[3].env['PERSONAL_VAR'], 'bar')
-        self.assertEqual(self.crontab[3].env.all(),
-            {'PERSONAL_VAR': 'bar', 'CRON_VAR': 'javlin', 'SECONDARY': 'fork'})
-
-        self.crontab.env['PERSONAL_VAR'] = 'foo'
-        self.assertEqual(self.crontab[2].env.all(),
-            {'PERSONAL_VAR': 'foo', 'CRON_VAR': 'javlin'})
-
-        self.crontab.env['CRON_VAR'] = 'fork'
-        self.assertEqual(self.crontab[0].env.all(),
-            {'PERSONAL_VAR': 'foo', 'CRON_VAR': 'fork'})
-
-        self.assertEqual(str(self.crontab), """PERSONAL_VAR=foo
-CRON_VAR=fork
-
-34 12 * * * eat_soup
-
-CRON_VAR=javlin
-35 12 * * * eat_salad
-
-36 12 * * * eat_icecream
-
-SECONDARY=fork
-38 12 * * * eat_steak
-""")
-
-    def test_05_no_env(self):
-        """Test that we get an error asking for no var"""
-        with self.assertRaises(KeyError):
-            self.crontab.env['BLUE_BOTTLE']
-        with self.assertRaises(KeyError):
-            self.crontab[0].env['RED_BOTTLE']
-
-    def test_06_env_access(self):
-        cron = CronTab(tab="""
-MYNAME='Random'
-
-* * * * * echo "first: $MYNAME"
-* * * * * echo "second: $MYNAME"
-* * * * * echo "third: $MYNAME"
-        """)
-        for job in cron:
-            self.assertEqual(job.env['MYNAME'], "Random")
-
-    def test_07_mutated_dict(self):
-        """Test when the ordered dict is changed during loop"""
-        cron = CronTab(tab="""
-ALL='all'
-ABCD='first'
-* * * * * echo "first"
-        """)
-
-    def test_08_space_quotes(self):
-        """Test that spaces and quotes are handled correctly"""
-        cron = CronTab(tab="""
-A=   123   
-B="   123   "
-C='   123   '
-D=  " 123 "  
-E= 1 2 3 
-""")
-        self.assertEqual(cron.env['A'], '123')
-        self.assertEqual(cron.env['B'], '   123   ')
-        self.assertEqual(cron.env['C'], '   123   ')
-        self.assertEqual(cron.env['D'], ' 123 ')
-        self.assertEqual(cron.env['E'], '1 2 3')
-
-        self.assertEqual(str(cron), """A=123
-B="   123   "
-C="   123   "
-D=" 123 "
-E="1 2 3"
-
-""")
-
-    def test_09_delete_middle(self):
-        """Test that a delete doesn't remove vars"""
-        self.crontab.remove_all(command='eat_icecream')
-        self.crontab.remove_all(command='eat_soup')
-        self.assertEqual(str(self.crontab), """PERSONAL_VAR=bar
-CRON_VAR=spoon
-35 12 * * * eat_salad
-
-
-CRON_VAR=knife
-SECONDARY=fork
-38 12 * * * eat_steak
-""")
-
-    def test_10_empty_env(self):
-        """Test when an env is an empty string it should have quotes"""
-        tab='MAILTO=""\n'
-        self.assertEqual(str(CronTab(tab=tab)), tab)
-
-    def test_11_empty_flow(self):
-        """Test what happends when an env is involved in flow"""
-        tab = """
-# A
-# B
-MAILTO=""
-# C
-*/10 * * * * /home/pi/job.py # any job
-"""
-        cron = CronTab(tab=tab)
-        job = cron.new('update.py', 'update')
-        job.setall('1 12 * * 3')
-        self.assertTrue(job.is_valid())
-        self.assertEqual(str(cron), """MAILTO=""
-
-# A
-# B
-# C
-*/10 * * * * /home/pi/job.py # any job
-
-1 12 * * 3 update.py # update
-""")
-
-        cron.remove_all(comment='update')
-
-        cron.write_to_user("bob")
-        filename = os.path.join(TEST_DIR, 'data', 'spool', 'bob')
-        with open(filename, 'r') as fhl:
-            self.assertEqual(fhl.read(), """MAILTO=""
-
-# A
-# B
-# C
-*/10 * * * * /home/pi/job.py # any job
-""")
-        os.unlink(filename)
-
-if __name__ == '__main__':
-    test_support.run_unittest(EnvTestCase)

+ 0 - 109
desktop/core/ext-py/python-crontab-2.3.6/tests/test_every.py

@@ -1,109 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2013 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test simple 'every' api.
-"""
-
-import os
-import sys
-
-sys.path.insert(0, '../')
-
-import unittest
-from crontab import CronTab, PY3
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-TEST_DIR = os.path.dirname(__file__)
-
-if PY3:
-    unicode = str
-
-class EveryTestCase(unittest.TestCase):
-    """Test basic functionality of crontab."""
-    def setUp(self):
-        self.crontab = CronTab(tabfile=os.path.join(TEST_DIR, 'data', 'test.tab'))
-
-    def test_00_minutes(self):
-        """Every Minutes"""
-        for job in self.crontab:
-            job.every(3).minutes()
-            self.assertEqual(job.slices.clean_render(), '*/3 * * * *')
-            job.minutes.every(5)
-            self.assertEqual(job.slices.clean_render(), '*/5 * * * *')
-
-    def test_01_hours(self):
-        """Every Hours"""
-        for job in self.crontab:
-            job.every(3).hours()
-            self.assertEqual(job.slices.clean_render(), '0 */3 * * *')
-
-    def test_02_dom(self):
-        """Every Day of the Month"""
-        for job in self.crontab:
-            job.every(3).dom()
-            self.assertEqual(job.slices.clean_render(), '0 0 */3 * *')
-
-    def test_03_single(self):
-        """Every Single Hour"""
-        for job in self.crontab:
-            job.every().hour()
-            self.assertEqual(job.slices.clean_render(), '0 * * * *')
-
-    def test_04_month(self):
-        """Every Month"""
-        for job in self.crontab:
-            job.every(3).months()
-            self.assertEqual(job.slices.clean_render(), '0 0 1 */3 *')
-
-    def test_05_dow(self):
-        """Every Day of the Week"""
-        for job in self.crontab:
-            job.every(3).dow()
-            self.assertEqual(job.slices.clean_render(), '0 0 * * */3')
-
-    def test_06_year(self):
-        """Every Year"""
-        for job in self.crontab:
-            job.every().year()
-            self.assertEqual(job.slices.render(), '@yearly')
-            self.assertEqual(job.slices.clean_render(), '0 0 1 1 *')
-            self.assertRaises(ValueError, job.every(2).year)
-
-    def test_07_reboot(self):
-        """Every Reboot"""
-        for job in self.crontab:
-            job.every_reboot()
-            self.assertEqual(job.slices.render(), '@reboot')
-            self.assertEqual(job.slices.clean_render(), '* * * * *')
-
-    def test_08_newitem(self):
-        """Every on New Item"""
-        job = self.crontab.new(command='hourly')
-        job.every().hour()
-        self.assertEqual(job.slices.render(), '@hourly')
-        job = self.crontab.new(command='firstly')
-        job.hours.every(2)
-        self.assertEqual(job.slices.render(), '* */2 * * *')
-
-if __name__ == '__main__':
-    test_support.run_unittest(
-       EveryTestCase,
-    )

+ 0 - 161
desktop/core/ext-py/python-crontab-2.3.6/tests/test_frequency.py

@@ -1,161 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2013 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test frequency calculations
-"""
-
-import os
-import sys
-
-sys.path.insert(0, '../')
-
-import unittest
-from crontab import CronTab, PY3
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-if PY3:
-    unicode = str
-
-START_TAB = """
-"""
-
-class FrequencyTestCase(unittest.TestCase):
-    """Test basic functionality of crontab."""
-    def setUp(self):
-        self.crontab = CronTab(tab=START_TAB.strip())
-        self.job = self.crontab.new(command='freq')
-
-    def test_00_slice_frequency(self):
-        """Each Slice Frequency"""
-        # Make sure some of these overlap
-        self.job.setall("13-16,14-15 6,*/3 2,3,4 * *")
-        self.assertEqual(len(self.job[0]), 4)
-        self.assertEqual(len(self.job[1]), 8)
-        self.assertEqual(len(self.job[2]), 3)
-        self.assertEqual(len(self.job[3]), 12)
-        self.assertEqual(len(self.job[4]), 7)
-
-    def test_01_per_day(self):
-        """Frequency per Day"""
-        self.job.setall("21-29 10-14 * * *")
-        self.assertEqual(len(self.job[0]), 9)
-        self.assertEqual(len(self.job[1]), 5)
-        self.assertEqual(self.job.frequency_per_day(), 45)
-
-    def test_02_days_per_year(self):
-        """Frequency in Days per Year"""
-        self.job.setall("* * * * *")
-        self.assertEqual(self.job.frequency_per_year(year=2010), 365)
-        self.assertEqual(self.job.frequency_per_year(year=2012), 366)
-        self.job.setall("1 1 11-20 1,4,6,8 0,6")
-        self.assertEqual(len(self.job[2]), 10)
-        self.assertEqual(len(self.job[3]), 4)
-        self.assertEqual(len(self.job[4]), 2)
-        self.assertEqual(self.job.frequency_per_year(year=2013), 11)
-        self.assertEqual(self.job.frequency_per_year(year=2010), 12)
-
-    def test_03_job(self):
-        """Once Yearly"""
-        self.job.setall("0 0 1 1 *")
-        self.assertEqual(self.job.frequency(year=2010), 1)
-
-    def test_04_twice(self):
-        """Twice Yearly"""
-        self.job.setall("0 0 1 1,6 *")
-        self.assertEqual(self.job.frequency(year=2010), 2)
-
-    def test_05_thrice(self):
-        """Thrice Yearly"""
-        self.job.setall("0 0 1 1,3,6 *")
-        self.assertEqual(self.job.frequency(year=2010), 3)
-
-    def test_06_quart(self):
-        """Four Yearly"""
-        self.job.setall("0 0 1 */3 *")
-        self.assertEqual(self.job.frequency(year=2010), 4)
-
-    def test_07_monthly(self):
-        """Once a month"""
-        self.job.setall("0 0 1 * *")
-        self.assertEqual(self.job.frequency(year=2010), 12)
-
-    def test_08_six_monthly(self):
-        """Six a month"""
-        self.job.setall("0 0 1,2,3,4,5,6 * *")
-        self.assertEqual(self.job.frequency(year=2010), 72)
-
-    def test_09_every_day(self):
-        """Every Day"""
-        self.job.setall("0 0 * * *")
-        self.assertEqual(self.job.frequency(year=2010), 365)
-
-    def test_10_every_hour(self):
-        """Every Hour"""
-        self.job.setall("0 * * * *")
-        self.assertEqual(self.job.frequency(year=2010), 8760)
-
-    def test_11_every_other_hour(self):
-        """Every Other Hour"""
-        self.job.setall("0 */2 * * *")
-        self.assertEqual(self.job.frequency(year=2010), 4380)
-
-    def test_12_every_minute(self):
-        """Every Minute"""
-        self.job.setall("* * * * *")
-        self.assertEqual(self.job.frequency(year=2010), 525600)
-
-    def test_13_enum(self):
-        """Enumerations"""
-        self.job.setall("0 0 * * MON-WED")
-        self.assertEqual(self.job.frequency(year=2010), 156)
-        self.job.setall("0 0 * JAN-MAR *")
-        self.assertEqual(self.job.frequency(year=2010), 90)
-
-    def test_14_all(self):
-        """Test Maximum"""
-        self.job.setall("* * * * *")
-        self.assertEqual(self.job.frequency(2010), 525600)
-        self.assertEqual(self.job.frequency_per_year(year=2010), 365)
-        self.assertEqual(self.job.frequency_per_day(), 1440)
-        self.job.setall("*")
-        self.assertEqual(self.job.frequency_per_day(), 1440)
-        self.assertEqual(self.job.frequency_per_year(year=2010), 365)
-        self.assertEqual(self.job.frequency(2010), 525600)
-
-    def test_15_compare(self):
-        """Compare Times"""
-        job = self.crontab.new(command='match')
-        job.setall("*/2 * * * *")
-        self.assertEqual(job.slices, "*/2 * * * *")
-        self.assertEqual(job.slices, ["*/2"])
-        self.assertLess(job, ["*"])
-        self.assertGreater(job, "*/3")
-
-    def test_16_frequency_per_hour(self):
-        """Count per hour"""
-        job = self.crontab.new(command='per_hour')
-        job.setall("*/2 * * * *")
-        self.assertEqual(job.frequency_per_hour(), 30)
-
-if __name__ == '__main__':
-    test_support.run_unittest(
-       FrequencyTestCase,
-    )

+ 0 - 367
desktop/core/ext-py/python-crontab-2.3.6/tests/test_interaction.py

@@ -1,367 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2013 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test crontab interaction.
-"""
-
-import re
-import os
-import unittest
-
-from crontab import CronTab, CronSlices, CronSlice, PY3
-from .utils import LoggingMixin
-
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-TEST_DIR = os.path.dirname(__file__)
-
-if PY3:
-    unicode = str #pylint: disable=redefined-builtin
-
-COMMANDS = [
-    'firstcommand',
-    'range',
-    'byweek',
-    'disabled',
-    'spaced',
-    'python /example_app/testing.py',
-    'rebooted',
-]
-
-RESULT_TAB = """# First Comment
-# Edit this line to test for mistaken checks
-
-# m h dom mon dow user command
-
-*/30 * * * * firstcommand
-* 10-20/3 * * * range
-# Middle Comment
-* * * 10 * byweek # Comment One
-# * * * * * disabled
-0 5 * * * spaced # Comment  Two
-
-*/59 * * * * python /example_app/testing.py # monitorCron
-
-@reboot rebooted # re-id
-# Last Comment @has this # extra
-"""
-
-class InteractionTestCase(LoggingMixin, unittest.TestCase):
-    """Test basic functionality of crontab."""
-    log_name = 'crontab'
-
-    def setUp(self):
-        super(InteractionTestCase, self).setUp()
-        self.crontab = CronTab(tabfile=os.path.join(TEST_DIR, 'data', 'test.tab'))
-
-    def test_01_presevation(self):
-        """All Entries Re-Rendered Correctly"""
-        results = RESULT_TAB.split('\n')
-        for line_no, line in enumerate(self.crontab.lines):
-            self.assertEqual(str(line), results[line_no])
-
-    def test_02_access(self):
-        """All Entries Are Accessable"""
-        for line_no, job in enumerate(self.crontab):
-            self.assertEqual(str(job.command), COMMANDS[line_no])
-        else: # pylint: disable=useless-else-on-loop
-            self.assertEqual(line_no + 1, 7)
-
-    def test_03_blank(self):
-        """Render Blank"""
-        job = self.crontab.new(command='blank')
-        self.assertEqual(repr(job), '<CronItem \'* * * * * blank\'>')
-        self.assertEqual(job.render(), '* * * * * blank')
-
-    def test_04_number(self):
-        """Render Number"""
-        job = self.crontab.new(command='number')
-        job.minute.on(4)
-        self.assertEqual(job.render(), '4 * * * * number')
-
-    def test_05_fields(self):
-        """Render Hours Days and Weeks"""
-        job = self.crontab.new(command='fields')
-        job.hour.on(4)
-        self.assertEqual(job.render(), '* 4 * * * fields')
-        job.dom.on(5)
-        self.assertEqual(job.render(), '* 4 5 * * fields')
-        job.month.on(6)
-        self.assertEqual(job.render(), '* 4 5 6 * fields')
-        job.dow.on(7)
-        self.assertEqual(job.render(), '* 4 5 6 0 fields')
-
-    def test_05_multiple_fields(self):
-        """Test mutliple named fields"""
-        job = self.crontab.new(command='fields')
-        job.hour.on(4, 6, 7)
-        self.assertEqual(job.render(), '* 4,6,7 * * * fields')
-        job.dow.on('SUN', 'FRI')
-        self.assertEqual(job.render(), '* 4,6,7 * * SUN,FRI fields')
-
-    def test_06_clear(self):
-        """Render Hours Days and Weeks"""
-        job = self.crontab.new(command='clear')
-        job.minute.on(3)
-        job.hour.on(4)
-        job.dom.on(5)
-        job.month.on(6)
-        job.dow.on(7)
-        self.assertEqual(job.render(), '3 4 5 6 0 clear')
-        job.clear()
-        self.assertEqual(job.render(), '* * * * * clear')
-
-    def test_07_range(self):
-        """Render Time Ranges"""
-        job = self.crontab.new(command='range')
-        job.minute.during(4, 10)
-        self.assertEqual(job.render(), '4-10 * * * * range')
-        job.minute.during(15, 19)
-        self.assertEqual(job.render(), '15-19 * * * * range')
-        job.minute.clear()
-        self.assertEqual(job.render(), '* * * * * range')
-        job.minute.during(15, 19)
-        self.assertEqual(job.render(), '15-19 * * * * range')
-        job.minute.also.during(4, 10)
-        self.assertEqual(job.render(), '4-10,15-19 * * * * range')
-
-    def test_08_sequence(self):
-        """Render Time Sequences"""
-        job = self.crontab.new(command='seq')
-        job.hour.every(4)
-        self.assertEqual(job.render(), '* */4 * * * seq')
-        job.hour.during(2, 10)
-        self.assertEqual(job.render(), '* 2-10 * * * seq')
-        job.hour.clear()
-        self.assertEqual(job.render(), '* * * * * seq')
-        job.hour.during(2, 10).every(4)
-        self.assertEqual(job.render(), '* 2-10/4 * * * seq')
-        job.hour.also.during(1, 4)
-        self.assertEqual(job.render(), '* 1-4,2-10/4 * * * seq')
-        job.hour.also.every(4)
-        self.assertEqual(job.render(), '* */4,1-4,2-10/4 * * * seq')
-
-    def test_10_comment(self):
-        """Render cron Comments"""
-        job = self.crontab.new(command='com', comment='I love this')
-        self.assertEqual(unicode(job), '* * * * * com # I love this')
-
-    def test_11_disabled(self):
-        """Disabled Job"""
-        jobs = list(self.crontab.find_command('firstcommand'))
-        self.assertTrue(jobs[0].enabled)
-        jobs = list(self.crontab.find_command('disabled'))
-        self.assertFalse(jobs[0].enabled)
-
-    def test_12_disable(self):
-        """Disable and Enable Job"""
-        job = self.crontab.new(command='dis')
-        job.enable(False)
-        self.assertEqual(unicode(job), '# * * * * * dis')
-        job.enable()
-        self.assertEqual(unicode(job), '* * * * * dis')
-
-    def test_13_plural(self):
-        """Plural API"""
-        job = self.crontab.new(command='plural')
-        job.minutes.every(4)
-        job.hours.on(5, 6)
-        job.day.on(4)
-        job.months.on(2)
-        self.assertEqual(unicode(job), '*/4 5,6 4 2 * plural')
-
-    def test_14_valid(self):
-        """Valid and Invalid"""
-        job = self.crontab.new(command='valid')
-        job.minute.every(2)
-        job.valid = False
-        with self.assertRaises(ValueError):
-            unicode(job)
-        # Disabled jobs still work
-        job.enabled = False
-        unicode(job)
-
-        job.enabled = True
-        with self.assertRaises(ValueError):
-            self.crontab.render(errors=True)
-        self.crontab.render(errors=False)
-        self.assertFalse(job.enabled)
-
-    def test_15_slices(self):
-        """Invalid Slices"""
-        mon = CronSlices('* * * * *')
-        with self.assertRaises(ValueError):
-            CronSlices('* * * */15 *')
-        with self.assertRaises(AssertionError):
-            mon.setall(mon)
-
-    def test_16_slice(self):
-        """Single Slice"""
-        dow = CronSlice({'name': 'M', 'max': 7, 'min': 0, 'enum': ['a']}, '*/6')
-        self.assertEqual(repr(dow), '<CronSlice \'*/6\'>')
-
-        self.assertEqual(repr(dow.parse_value('a')), 'a')
-        with self.assertRaises(ValueError):
-            dow.parse_value('b')
-
-        self.assertEqual(dow.get_range()[0].render(), '*')
-        with self.assertRaises(ValueError):
-            dow.get_range('%')
-
-    def test_17_slice_id(self):
-        """Single slice by Id"""
-        self.assertEqual(CronSlice(1).max, 23)
-
-    def test_18_range_cmp(self):
-        """Compare ranges"""
-        dow = CronSlice({'max': 5, 'min': 0})
-        three = dow.get_range(2, 4)[0]
-        self.assertGreater(three, 2)
-        self.assertLess(three, 4)
-        self.assertEqual(str(three), '2-4')
-
-    def test_18_find(self):
-        """Find a command and comments by name"""
-        cmds = list(self.crontab.find_command('byweek'))
-        self.assertEqual(len(cmds), 1)
-        self.assertEqual(cmds[0].comment, 'Comment One')
-
-        cmds = list(self.crontab.find_command(re.compile(r'stc\w')))
-        self.assertEqual(len(cmds), 1)
-        self.assertEqual(cmds[0].command, 'firstcommand')
-
-        cmds = list(self.crontab.find_command('Comment One'))
-        self.assertEqual(len(cmds), 0)
-
-        cmds = list(self.crontab.find_comment('Comment One'))
-        self.assertEqual(len(cmds), 1)
-        self.assertEqual(cmds[0].command, 'byweek')
-
-        cmds = list(self.crontab.find_comment(re.compile(r'om+en\w O')))
-        self.assertEqual(len(cmds), 1)
-        self.assertEqual(cmds[0].comment, 'Comment One')
-
-        cmds = list(self.crontab.find_comment(re.compile(r'stc\w')))
-        self.assertEqual(len(cmds), 0)
-
-    def test_20_write(self):
-        """Write CronTab to file"""
-        self.crontab.write('output.tab')
-        self.assertTrue(os.path.exists('output.tab'))
-        os.unlink('output.tab')
-
-    def test_21_multiuse(self):
-        """Multiple Renderings"""
-        cron = '# start of tab\n'
-        for i in range(10):
-            crontab = CronTab(tab=cron)
-            p = list(crontab.new(command='multi%d' % i))
-            cron = unicode(crontab)
-            crontab = CronTab(tab=cron)
-            list(crontab.find_command('multi%d' % i))[0].delete()
-            cron = unicode(crontab)
-        self.assertEqual(unicode(crontab), '# start of tab\n')
-
-    def test_22_min(self):
-        """Minimum Field Values"""
-        job = self.crontab.new(command='min')
-        job.minute.on('<')
-        job.hour.on('<')
-        job.dom.on('<')
-        job.month.on('<')
-        self.assertEqual(unicode(job), '@yearly min')
-
-    def test_23_max(self):
-        """Maximum Field Values"""
-        job = self.crontab.new(command='max')
-        job.minute.on('>')
-        job.hour.on('>')
-        job.dom.on('>')
-        job.month.on('>')
-        self.assertEqual(unicode(job), '59 23 31 12 * max')
-
-    def test_24_special_r(self):
-        """Special formats are read and written"""
-        tab = CronTab(tabfile=os.path.join(TEST_DIR, 'data', 'specials_enc.tab'))
-        self.assertEqual(tab.render(), """@hourly hourly\n@daily daily\n@midnight midnight\n@weekly weekly\n@reboot reboot\n""")
-        self.assertEqual(len(list(tab)), 5)
-
-    def test_24_special_d(self):
-        """Removal All Specials"""
-        tab = CronTab(tabfile=os.path.join(TEST_DIR, 'data', 'specials.tab'))
-        tab.remove_all()
-        self.assertEqual(len(list(tab)), 0)
-
-    def test_24_special_w(self):
-        """Write Specials"""
-        tab = CronTab(tabfile=os.path.join(TEST_DIR, 'data', 'specials.tab'))
-        self.assertEqual(tab.render(), """@hourly hourly\n@daily daily\n@weekly weekly\n""")
-        self.assertEqual(len(list(tab)), 3)
-
-    def test_25_setall(self):
-        """Set all values at once"""
-        job = self.crontab.new(command='all')
-        job.setall(1, '*/2', '2-4', '>', 'SUN')
-        self.assertEqual(unicode(job), '1 */2 2-4 12 SUN all')
-        job.setall('*/2')
-        self.assertEqual(unicode(job), '*/2 * * * * all')
-        job.setall('1 */2 2-4 12 SUN')
-        self.assertEqual(unicode(job), '1 */2 2-4 12 SUN all')
-        job.setall(['*'])
-        self.assertEqual(unicode(job), '* * * * * all')
-
-    def test_26_setall_obj(self):
-        """Copy all values"""
-        job = self.crontab.new(command='all')
-        job2 = self.crontab.new(command='ignore')
-        job2.setall("1 */2 2-4 12 SUN")
-        job.setall(job2)
-        self.assertEqual(unicode(job), '1 */2 2-4 12 SUN all')
-        job2.setall("2 */3 4-8 10 MON")
-        job.setall(job2.slices)
-        self.assertEqual(unicode(job), '2 */3 4-8 10 MON all')
-
-    def test_27_commands(self):
-        """Get all commands"""
-        self.assertEqual(list(self.crontab.commands),
-                         [u'firstcommand', u'range', u'byweek', u'disabled',
-                          u'spaced', u'python /example_app/testing.py',
-                          u'rebooted'])
-
-    def test_28_comments(self):
-        """Get all comments"""
-        self.assertEqual(list(self.crontab.comments),
-                         ['Comment One', 'Comment  Two', 'monitorCron', 're-id'])
-
-    def test_29_set_lines(self):
-        """Set crontab lines directly"""
-        cron = CronTab(tab='')
-        cron.lines = [
-            str(self.crontab.lines[5]),
-        ]
-        self.assertEqual(str(cron), '\n*/30 * * * * firstcommand\n')
-
-        with self.assertRaises(AttributeError):
-            cron.crons = ['A']
-
-
-if __name__ == '__main__':
-    test_support.run_unittest(InteractionTestCase)

+ 0 - 161
desktop/core/ext-py/python-crontab-2.3.6/tests/test_log.py

@@ -1,161 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) YEAR Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test the cron log extention with a test syslog example data file.
-"""
-
-import os
-import sys
-from datetime import datetime, date
-
-import unittest
-from crontab import CronTab
-from cronlog import CronLog, LogReader
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-TEST_DIR = os.path.dirname(__file__)
-
-INITAL_TAB = """
-* * * * * userscript &> /dev/null
-* * * * * rootscript &> /dev/null
-* * * * * shadowscript &> /dev/null
-"""
-
-ROOT_PIDS = ['16592', '16574', '16552', '16522', '16514', '16489']
-SHAD_PIDS = ['16551', '16497']
-USER_PIDS = ['16591', '16588', '16573', '16569', '16554', '16539', '16523',\
-            '16519','16513','16496','16490']
-
-YEAR = date.today().year
-
-ROOT_DATES = [
-    datetime(YEAR, 4, 4, 21, 34, 1),
-    datetime(YEAR, 4, 4, 21, 32, 1),
-    datetime(YEAR, 4, 4, 21, 30, 1),
-    datetime(YEAR, 4, 4, 21, 28, 1),
-    datetime(YEAR, 4, 4, 21, 26, 1),
-    datetime(YEAR, 4, 4, 21, 24, 1),
-  ]
-SHAD_DATES = [
-    datetime(YEAR, 4, 4, 21, 30, 1),
-    datetime(YEAR, 4, 4, 21, 25, 1),
-  ]
-USER_DATES = [
-    datetime(YEAR, 4, 4, 21, 34, 1),
-    datetime(YEAR, 4, 4, 21, 33, 2),
-    datetime(YEAR, 4, 4, 21, 32, 1),
-    datetime(YEAR, 4, 4, 21, 31, 1),
-    datetime(YEAR, 4, 4, 21, 30, 1),
-    datetime(YEAR, 4, 4, 21, 29, 1),
-    datetime(YEAR, 4, 4, 21, 28, 1),
-    datetime(YEAR, 4, 4, 21, 27, 1),
-    datetime(YEAR, 4, 4, 21, 26, 1),
-    datetime(YEAR, 4, 4, 21, 25, 1),
-    datetime(YEAR, 4, 4, 21, 24, 1),
-  ]
-LONG_LINE = 'A really long line which can test log lines ability to put two bits together'
-READ_LINE = [ 'The End', 'Sickem', '2', '9', 'First Line', LONG_LINE ]
-
-class BasicTestCase(unittest.TestCase):
-    """Test basic functionality of crontab."""
-    def setUp(self):
-        self.log = os.path.join(TEST_DIR, 'data', 'test.log')
-        self.crontab = CronTab(tab=INITAL_TAB, log=self.log)
-
-    def test_00_logreader(self):
-        """Log Reader"""
-        lines = READ_LINE[:]
-        reader = LogReader(os.path.join(TEST_DIR, 'data', 'basic.log'), mass=50)
-        for line in reader:
-            self.assertEqual(line.strip(), lines.pop(0))
-
-    def test_01_cronreader(self):
-        """Cron Log Lines"""
-        with self.crontab.log as log:
-            lines = list(log.readlines())
-        self.assertEqual(len(lines), 32)
-        self.assertEqual(lines[0][1], "Apr  4 21:34:01 servername CRON[16592]"
-                                      ": (root) CMD (rootscript &> /dev/null)")
-        self.assertEqual(lines[15][1], "Apr  4 21:28:31 servername NOTCRON"
-                                      ": that these are ignored")
-        self.assertEqual(lines[-1][1], "Apr  4 21:24:01 servername CRON[16490]"
-                                      ": (user) CMD (userscript &> /dev/null)")
-
-    def test_01_iter(self):
-        """Iterate directly over log"""
-        with self.crontab.log as log:
-            self.assertEqual(len(list(log)), 8)
-
-    def test_02_cronlog(self):
-        """Cron Log Items"""
-        entries = list(CronLog(os.path.join(TEST_DIR, 'data', 'test.log')))
-        self.assertEqual(len(entries), 19)
-        self.assertEqual(entries[0]['pid'], "16592")
-        self.assertEqual(entries[3]['pid'], "16574")
-        self.assertEqual(entries[-1]['pid'], "16490")
-
-    def test_03_crontab(self):
-        """Cron Tab Items"""
-        entries = list(self.crontab.log)
-        self.assertEqual(len(entries), 8)
-        self.assertEqual(entries[0]['pid'], "16592")
-        self.assertEqual(entries[3]['pid'], "16551")
-        self.assertEqual(entries[-1]['pid'], "16489")
-
-    def test_04_root(self):
-        """Cron Job Items"""
-        pids, dates = ROOT_PIDS[:], ROOT_DATES[:]
-        job = list(self.crontab.find_command('rootscript'))[0]
-        for log in job.log:
-            self.assertEqual(log['pid'], pids.pop(0))
-            self.assertEqual(log['date'], dates.pop(0))
-        self.assertEqual(pids, [])
-
-    def tst_05_shadow(self):
-        """Seperate Job Items"""
-        pids, dates = SHAD_PIDS[:], SHAD_DATES[:]
-        job = self.crontab.find_command('shadowscript')[0]
-        for log in job.log:
-            self.assertEqual(log['pid'], pids.pop(0))
-            self.assertEqual(log['date'], dates.pop(0))
-        self.assertEqual(pids, [])
-
-    def tst_06_user(self):
-        """Seperate User Crontab"""
-        pids, dates = USER_PIDS[:], User_DATES[:]
-        self.crontab.user = 'user'
-        job = self.crontab.find_command('userscript')[0]
-        for log in job.log:
-            self.assertEqual(log['pid'], pids.pop(0))
-            self.assertEqual(log['date'], dates.pop(0))
-        self.assertEqual(pids, [])
-
-    def test_08_readerror(self):
-        """Cron Log Error"""
-        self.crontab.log.pipe = False
-        with self.assertRaises(IOError):
-            list(self.crontab.log.readlines())
-
-
-if __name__ == '__main__':
-    test_support.run_unittest(
-       BasicTestCase,
-    )

+ 0 - 136
desktop/core/ext-py/python-crontab-2.3.6/tests/test_range.py

@@ -1,136 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2013 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test crontab ranges.
-"""
-import unittest
-from crontab import CronTab, CronSlice, PY3
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-from .utils import LoggingMixin
-
-if PY3:
-    unicode = str #pylint: disable=redefined-builtin
-
-class RangeTestCase(LoggingMixin, unittest.TestCase):
-    """Test basic functionality of crontab."""
-    log_name = 'crontab'
-
-    def setUp(self):
-        super(RangeTestCase, self).setUp()
-        self.crontab = CronTab(tab="")
-
-    def test_01_atevery(self):
-        """At Every"""
-        tab = CronTab(tab="""
-*  *  *  *  * command
-61 *  *  *  * command
-*  25 *  *  * command
-*  *  32 *  * command
-*  *  *  13 * command
-*  *  *  *  8 command
-        """)
-        self.assertEqual(len(tab), 1)
-        self.assertLog("error", "'61', not in 0-59 for Minutes")
-        self.assertLog("error", "'25', not in 0-23 for Hours")
-        self.assertLog("error", "'32', not in 1-31 for Day of Month")
-        self.assertLog("error", "'13', not in 1-12 for Month")
-        self.assertLog("error", "'8', not in 0-6 for Day of Week")
-
-    def test_02_withinevery(self):
-        """Within Every"""
-        tab = CronTab(tab="""
-*    *    *    *    * command
-1-61 *    *    *    * command
-*    1-25 *    *    * command
-*    *    1-32 *    * command
-*    *    *    1-13 * command
-*    *    *    *    1-8 command
-        """)
-        self.assertEqual(len(tab), 1)
-        self.assertLog("error", "'61', not in 0-59 for Minutes")
-        self.assertLog("error", "'25', not in 0-23 for Hours")
-        self.assertLog("error", "'32', not in 1-31 for Day of Month")
-        self.assertLog("error", "'13', not in 1-12 for Month")
-        self.assertLog("error", "'8', not in 0-6 for Day of Week")
-
-    def test_03_outevery(self):
-        """Out of Every"""
-        tab = CronTab(tab="""
-*    *    *    *    *   command
-*/61 *    *    *    *   command
-*    */25 *    *    *   command
-*    *    */32 *    *   command
-*    *    *    */13 *   command
-*    *    *    *    */8 command
-        """)
-        self.assertEqual(len(tab), 1)
-        self.assertLog("error", "'61', not in 0-59 for Minutes")
-        self.assertLog("error", "'25', not in 0-23 for Hours")
-        self.assertLog("error", "'32', not in 1-31 for Day of Month")
-        self.assertLog("error", "'13', not in 1-12 for Month")
-        self.assertLog("error", "'8', not in 0-6 for Day of Week")
-
-    def test_03_inevery(self):
-        """Inside of Every"""
-        tab = CronTab(tab="""
-*    *    *    *    *   command
-*/59 *    *    *    *   command
-*    */23 *    *    *   command
-*    *    */30 *    *   command
-*    *    *    */11 *   command
-*    *    *    *    */7 command
-        """)
-        self.assertEqual(len(tab), 6, str(tab))
-
-    def test_04_zero_seq(self):
-        """Zero divisor in range"""
-        tab = CronTab(tab="""
-*/0 * * * * command
-        """)
-        self.assertEqual(len(tab), 0)
-        self.assertLog("error", "Sequence can not be divided by zero or max")
-
-    def test_14_invalid_range(self):
-        """No numerator in range"""
-        tab = CronTab(tab="/10 * * * * command")
-        self.assertEqual(len(tab), 0)
-        with self.assertRaises(ValueError):
-            tab.render(errors=True)
-        self.assertEqual(unicode(tab), "# DISABLED LINE\n# /10 * * * * command\n")
-        self.assertLog('error', u"No enumeration for Minutes: '/10'")
-
-    def test_05_sunday(self):
-        """Test all possible day of week combinations"""
-        for (a, b) in (\
-              ("7", "0"), ("5-7", "0,5-6"), ("1-7", "*"), ("*/7", "0"),\
-              ("0-6", "*"), ("2-7", "0,2-6"), ("1-5", "1-5"), ("0-5", "0-5")):
-            v = str(CronSlice(4, a))
-            self.assertEqual(v, b, "%s != %s, from %s" % (v, b, a))
-
-    def test_06_backwards(self):
-        """Test backwards ranges for error"""
-        tab = CronTab(tab="* * * * 3-1 command")
-        self.assertEqual(str(tab), "* * * * 1-3 command\n")
-        self.assertLog("warning", "Bad range '3-1'")
-
-if __name__ == '__main__':
-    test_support.run_unittest(RangeTestCase)

+ 0 - 154
desktop/core/ext-py/python-crontab-2.3.6/tests/test_removal.py

@@ -1,154 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2013 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test cron item removal
-"""
-
-import os
-import sys
-
-sys.path.insert(0, '../')
-
-import unittest
-from crontab import CronTab, PY3
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-if PY3:
-    unicode = str
-
-START_TAB = """
-3 * * * * command1 # CommentID C
-2 * * * * command2 # CommentID AAB
-1 * * * * command3 # CommentID B3
-"""
-
-class RemovalTestCase(unittest.TestCase):
-    """Test basic functionality of crontab."""
-    def setUp(self):
-        self.filenames = []
-        self.crontab = CronTab(tab=START_TAB.strip())
-
-    def test_01_remove(self):
-        """Remove Item"""
-        self.assertEqual(len(self.crontab), 3)
-        self.crontab.remove(self.crontab.crons[0])
-        self.assertEqual(len(self.crontab), 2)
-        self.assertEqual(len(self.crontab.render()), 69)
-
-    def test_02_remove_all(self):
-        """Remove All"""
-        self.crontab.remove_all()
-        self.assertEqual(len(self.crontab), 0)
-        self.assertEqual(unicode(self.crontab), '')
-
-    def test_03_remove_cmd(self):
-        """Remove all with Command"""
-        self.crontab.remove_all(command='command2')
-        self.assertEqual(len(self.crontab), 2)
-        self.assertEqual(len(self.crontab.render()), 67)
-        self.crontab.remove_all(command='command3')
-        self.assertEqual(len(self.crontab), 1)
-        self.assertEqual(len(self.crontab.render()), 33)
-
-    def test_04_remove_id(self):
-        """Remove all with Comment/ID"""
-        self.crontab.remove_all(comment='CommentID B3')
-        self.assertEqual(len(self.crontab), 2)
-        self.assertEqual(len(self.crontab.render()), 68)
-
-    def test_05_remove_date(self):
-        """Remove all with Time Code"""
-        self.crontab.remove_all(time='2 * * * *')
-        self.assertEqual(len(self.crontab), 2)
-        self.assertEqual(len(self.crontab.render()), 67)
-
-    def test_05_remove_all_error(self):
-        """Remove all with old arg"""
-        with self.assertRaises(AttributeError):
-            self.crontab.remove_all('command')
-
-    def test_06_removal_of_none(self):
-        """Remove all respects None as a possible value"""
-        self.crontab[1].set_comment(None)
-        self.crontab.remove_all(comment=None)
-        self.assertEqual(len(self.crontab), 2)
-        self.assertEqual(len(self.crontab.render()), 67)
-
-    def test_07_removal_in_loop(self):
-        """Remove items in a loop"""
-        for job in self.crontab:
-            self.crontab.remove(job)
-        self.assertEqual(len(self.crontab), 0)
-
-    def test_08_removal_write_loop(self):
-        """Remove items in a loop and save each time"""
-        filename = self.get_new_file('removal')
-        crontab = CronTab()
-        for i in range(10):
-            crontab.new('test', comment=str(i))
-            crontab.write(filename)
-            crontab = CronTab(tabfile=filename)
-            self.assertEqual(len(crontab), 1)
-            self.assertNotEqual(str(crontab), '')
-
-            crontab.remove_all(comment=str(i))
-            crontab.write(filename)
-            crontab = CronTab(tabfile=filename)
-            self.assertEqual(len(crontab), 0)
-            self.assertEqual(str(crontab), '')
-
-    def test_09_removal_during_iter(self):
-        crontab = CronTab()
-        for x in range(0, 5, 1):
-            job = crontab.new(command="cmd", comment="SAME_ID")
-            job.setall("%d * * * *" % (x + 1))
-        for item in crontab.find_comment("SAME_ID"):
-            crontab.remove(item)
-        self.assertEqual(len(crontab), 0)
-
-    def test_11_remove_generator(self):
-        """Remove jobs from the find generator"""
-        tabs = self.crontab.find_command('command2')
-        self.crontab.remove(tabs)
-        self.assertEqual(len(self.crontab), 2)
-
-    def test_12_remove_nonsense(self):
-        """Fail to remove bad type"""
-        self.assertRaises(TypeError, self.crontab.remove, 5)
-        self.assertRaises(TypeError, self.crontab.remove, "foo")
-
-    def get_new_file(self, name):
-        """Gets a filename and records it for deletion"""
-        this_dir = os.path.dirname(__file__)
-        filename = os.path.join(this_dir, 'data', 'spool', name)
-        self.filenames.append(filename)
-        return filename
-
-    def tearDown(self):
-        for filename in self.filenames:
-            if os.path.isfile(filename):
-                os.unlink(filename)
-
-
-if __name__ == '__main__':
-    test_support.run_unittest(
-       RemovalTestCase,
-    )

+ 0 - 113
desktop/core/ext-py/python-crontab-2.3.6/tests/test_scheduler.py

@@ -1,113 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2016 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test any internal scheduling
-"""
-
-import os
-import sys
-
-import unittest
-import crontab
-import logging
-import string
-import random
-
-try:
-    from StringIO import StringIO
-except ImportError:
-    from io import StringIO
-
-logger = logging.getLogger()
-logger.level = logging.WARNING
-
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-TEST_DIR = os.path.dirname(__file__)
-COMMAND = os.path.join(TEST_DIR, 'data', 'crontest ')
-
-class SchedulerTestCase(unittest.TestCase):
-    """Test scheduling functions of CronTab."""
-    def setUp(self):
-        self.tab = crontab.CronTab()
-        try:
-            import croniter
-        except ImportError:
-            self.skipTest("Croniter not installed")
-
-        self.handlers = []
-        self.log = crontab.LOG
-        self.log.setLevel(logging.DEBUG)
-        self.log.propagate = False
-        for handler in self.log.handlers:
-            self.handlers.append(handler)
-            self.log.removeHandler(handler)
-
-        self.err = StringIO()
-        self.handler = logging.StreamHandler(self.err)
-        self.log.addHandler(self.handler)
-
-    def tearDown(self):
-        logger.removeHandler(self.handler)
-        for handler in self.handlers:
-            logger.addHandler(handler)
-        #self.err.close()
-
-    def assertLog(self, text):
-        self.handler.flush()
-        self.assertEqual(self.err.getvalue().strip(), text)
-
-    def assertSchedule(self, slices, count, result):
-        uid = random.choice(string.ascii_letters)
-        self.tab.new(command=COMMAND + '-h ' + uid).setall(slices)
-        ret = list(self.tab.run_scheduler(count, cadence=0.01, warp=True))
-        self.assertEqual(len(ret), result)
-        if count > 0:
-            self.assertEqual(ret[0], '-h|' + uid)
-
-    def test_01_run(self):
-        """Run the command"""
-        self.tab.env['SHELL'] = crontab.SHELL
-        ret = self.tab.new(command=COMMAND+'-h A').run()
-        self.assertEqual(ret, '-h|A')
-
-    def test_02_run_error(self):
-        """Run with errors"""
-        ret = self.tab.new(command=COMMAND+'-e B').run()
-        self.assertEqual(ret, '')
-        self.assertLog('-e|B')
-
-    def test_03_schedule(self):
-        """Simple Schedule"""
-        self.assertSchedule("* * * * *", 5, 4)
-
-    def test_04_schedule_ten(self):
-        """Every Ten Minutes"""
-        self.assertSchedule("*/10 * * * *", 12, 1)
-
-    def test_05_env_passed(self):
-        """Environment is passed in"""
-        self.tab.env['CR_VAR'] = 'BABARIAN'
-        ret = self.tab.new(command=COMMAND+' -ev').run()
-        self.assertEqual(ret, 'BABARIAN')
-
-if __name__ == '__main__':
-    test_support.run_unittest(SchedulerTestCase)

+ 0 - 122
desktop/core/ext-py/python-crontab-2.3.6/tests/test_system_cron.py

@@ -1,122 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2015 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-System cron is prefixed with the username the process should run under.
-"""
-
-import os
-import sys
-
-sys.path.insert(0, '../')
-
-import unittest
-from crontab import CronTab
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-TEST_FILE = os.path.join(os.path.dirname(__file__), 'data', 'crontab')
-INITIAL_TAB = """
-*/30 * * * * palin one_cross_each
-*/30 * * * * matias\ttab_user_error
-"""
-
-class SystemCronTestCase(unittest.TestCase):
-    """Test vixie cron user addition."""
-    def setUp(self):
-        self.crontab = CronTab(tab=INITIAL_TAB, user=False)
-
-    def test_00_repr(self):
-        """System crontab repr"""
-        self.assertEqual(repr(self.crontab), "<Unattached System CronTab>")
-
-    def test_01_read(self):
-        """Read existing command"""
-        job = self.crontab[0]
-        self.assertEqual(job.user, 'palin')
-        self.assertEqual(job.command, 'one_cross_each')
-        job = self.crontab[1]
-        self.assertEqual(job.user, 'matias')
-        self.assertEqual(job.command, 'tab_user_error')
-        self.assertEqual(len(self.crontab), 2)
-
-    def test_02_new(self):
-        """Create a new job"""
-        job = self.crontab.new(command='release_brian', user='pontus')
-        self.assertEqual(job.user, 'pontus')
-        self.assertEqual(job.command, 'release_brian')
-        self.assertEqual(str(self.crontab), INITIAL_TAB.replace('\t', ' ') + """
-* * * * * pontus release_brian
-""")
-
-    def test_03_new_tab(self):
-        """Create a new system crontab"""
-        tab = CronTab(user=False)
-        tab.env['SHELL'] = '/usr/bin/roman'
-        job = tab.new(command='release_bwian', user='pontus')
-        self.assertEqual(str(tab), """SHELL=/usr/bin/roman
-* * * * * pontus release_bwian
-""")
-
-    def test_04_failure(self):
-        """Fail when no user"""
-        with self.assertRaises(ValueError):
-            self.crontab.new(command='im_brian')
-        cron = self.crontab.new(user='user', command='no_im_brian')
-        cron.user = None
-        with self.assertRaises(ValueError):
-            cron.render()
-
-    def test_05_remove(self):
-        """Remove the user flag"""
-        self.crontab._user = None
-        self.assertEqual(str(self.crontab), """
-*/30 * * * * one_cross_each
-*/30 * * * * tab_user_error
-""")
-        self.crontab.new(command='now_go_away')
-
-
-    def test_06_comments(self):
-        """Comment with six parts parses successfully"""
-        crontab = CronTab(user=False, tab="""
-#a system_comment that has six parts_will_fail_to_parse
-        """)
-
-    def test_07_recreation(self):
-        """Input doesn't change on save"""
-        crontab = CronTab(user=False, tab="* * * * * user command")
-        self.assertEqual(str(crontab), "* * * * * user command\n")
-        crontab = CronTab(user=False, tab="* * * * * user command\n")
-        self.assertEqual(str(crontab), "* * * * * user command\n")
-
-    def test_09_resaving(self):
-        """Cycle rendering to show no changes"""
-        for i in range(10):
-            self.crontab = CronTab(tab=str(self.crontab))
-
-        self.assertEqual(INITIAL_TAB.replace('\t', ' '), str(self.crontab))
-
-    def test_10_system_file(self):
-        """Load system crontab from a file"""
-        crontab = CronTab(user=False, tabfile=TEST_FILE)
-        self.assertEqual(repr(crontab), "<System CronTab '%s'>" % TEST_FILE)
-
-if __name__ == '__main__':
-    test_support.run_unittest(SystemCronTestCase)

+ 0 - 215
desktop/core/ext-py/python-crontab-2.3.6/tests/test_usage.py

@@ -1,215 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2012 Jay Sigbrandt <jsigbrandt@slb.com>
-#                    Martin Owens <doctormo@gmail.com>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test crontab usage.
-"""
-
-import os
-import sys
-
-import unittest
-import crontab
-
-from datetime import date, time, datetime, timedelta
-
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-crontab.LOG.setLevel(crontab.logging.ERROR)
-TEST_DIR = os.path.dirname(__file__)
-
-class DummyStdout(object):
-    def write(self, text):
-        pass
-
-BASIC = '@hourly firstcommand\n\n'
-USER = '\n*/4 * * * * user_command # user_comment\n\n\n'
-crontab.CRONCMD = "%s %s" % (sys.executable, os.path.join(TEST_DIR, 'data', 'crontest'))
-
-def flush():
-    pass
-
-class Attribute(object):
-    def __init__(self, obj, attr, value):
-        self.obj = obj
-        self.attr = attr
-        self.value = value
-
-    def __enter__(self, *args, **kw):
-        if hasattr(self.obj, self.attr):
-            self.previous = getattr(self.obj, self.attr)
-        setattr(self.obj, self.attr, self.value)
-
-    def __exit__(self, *args, **kw):
-        if hasattr(self, 'previous'):
-            setattr(self.obj, self.attr, self.previous)
-        else:
-            delattr(self.obj, self.attr)
-
-
-class UseTestCase(unittest.TestCase):
-    """Test use documentation in crontab."""
-    def setUp(self):
-        self.filenames = []
-
-    def test_01_empty(self):
-        """Open system crontab"""
-        cron = crontab.CronTab()
-        self.assertEqual(cron.render(), "")
-        self.assertEqual(cron.__unicode__(), "")
-        self.assertEqual(repr(cron), "<Unattached CronTab>")
-
-    def test_02_user(self):
-        """Open a user's crontab"""
-        cron = crontab.CronTab(user='basic')
-        self.assertEqual(cron.render(), BASIC)
-        self.assertEqual(repr(cron), "<User CronTab 'basic'>")
-
-    def test_03_usage(self):
-        """Dont modify crontab"""
-        cron = crontab.CronTab(tab='')
-        sys.stdout = DummyStdout()
-        sys.stdout.flush = flush
-        try:
-            exec(crontab.__doc__)
-        except ImportError:
-            pass
-        sys.stdout = sys.__stdout__
-        self.assertEqual(cron.render(), '')
-
-    def test_04_username(self):
-        """Username is True"""
-        cron = crontab.CronTab(user=True)
-        self.assertNotEqual(cron.user, True)
-        self.assertEqual(cron.render(), USER)
-        self.assertEqual(repr(cron), "<My CronTab>")
-
-    def test_05_nouser(self):
-        """Username doesn't exist"""
-        cron = crontab.CronTab(user='nouser')
-        self.assertEqual(cron.render(), '')
-
-    def test_06_touser(self):
-        """Write to use API"""
-        cron = crontab.CronTab(tab=USER)
-        self.assertEqual(repr(cron), "<Unattached CronTab>")
-        cron.write_to_user('bob')
-        filename = os.path.join(TEST_DIR, 'data', 'spool', 'bob')
-        self.filenames.append(filename)
-        self.assertTrue(os.path.exists(filename))
-        self.assertEqual(repr(cron), "<User CronTab 'bob'>")
-
-    def test_07_ioerror_read(self):
-        """No filename ioerror"""
-        with self.assertRaises(IOError):
-            cron = crontab.CronTab(user='error')
-            cron.read()
-
-    def test_07_ioerror_write(self):
-        """User not specified, nowhere to write to"""
-        cron = crontab.CronTab()
-        with self.assertRaises(IOError):
-            cron.write()
-
-    def test_08_cronitem(self):
-        """CronItem Standalone"""
-        item = crontab.CronItem.from_line('noline')
-        self.assertTrue(item.is_enabled())
-        with self.assertRaises(UnboundLocalError):
-            item.delete()
-        item.command = str('nothing')
-        self.assertEqual(item.render(), '* * * * * nothing')
-
-    def test_10_time_object(self):
-        """Set slices using time object"""
-        item = crontab.CronItem(command='cmd')
-        self.assertEqual(str(item.slices), '* * * * *')
-        item.setall(time(1, 2))
-        self.assertEqual(str(item.slices), '2 1 * * *')
-        self.assertTrue(item.is_valid())
-        item.setall(time(0, 30, 0, 0))
-        self.assertEqual(str(item.slices), '30 0 * * *')
-        self.assertTrue(item.is_valid())
-        self.assertEqual(str(item), '30 0 * * * cmd')
-
-    def test_11_date_object(self):
-        """Set slices using date object"""
-        item = crontab.CronItem(command='cmd')
-        self.assertEqual(str(item.slices), '* * * * *')
-        item.setall(date(2010, 6, 7))
-        self.assertEqual(str(item.slices), '0 0 7 6 *')
-        self.assertTrue(item.is_valid())
-
-    def test_12_datetime_object(self):
-        """Set slices using datetime object"""
-        item = crontab.CronItem(command='cmd')
-        self.assertEqual(str(item.slices), '* * * * *')
-        item.setall(datetime(2009, 8, 9, 3, 4))
-        self.assertTrue(item.is_valid())
-        self.assertEqual(str(item.slices), '4 3 9 8 *')
-
-    def test_20_slice_validation(self):
-        """CronSlices class and objects can validate"""
-        CronSlices = crontab.CronSlices
-        self.assertTrue(CronSlices('* * * * *').is_valid())
-        self.assertTrue(CronSlices.is_valid('* * * * *'))
-        self.assertTrue(CronSlices.is_valid('*/2 * * * *'))
-        self.assertTrue(CronSlices.is_valid('* 1,2 * * *'))
-        self.assertTrue(CronSlices.is_valid('* * 1-5 * *'))
-        self.assertTrue(CronSlices.is_valid('* * * * MON-WED'))
-        self.assertTrue(CronSlices.is_valid('@reboot'))
-
-        sliced = CronSlices('* * * * *')
-        sliced[0].parts = [300]
-        self.assertEqual(str(sliced), '300 * * * *')
-        self.assertFalse(sliced.is_valid())
-        self.assertFalse(CronSlices.is_valid('P'))
-        self.assertFalse(CronSlices.is_valid('*/61 * * * *'))
-        self.assertFalse(CronSlices.is_valid('* 1,300 * * *'))
-        self.assertFalse(CronSlices.is_valid('* * 50-1 * *'))
-        self.assertFalse(CronSlices.is_valid('* * * * FRO-TOO'))
-        self.assertFalse(CronSlices.is_valid('@retool'))
-
-    def test_25_open_pipe(self):
-        """Test opening pipes"""
-        from crontab import open_pipe, CRONCMD
-        pipe = open_pipe(CRONCMD, h=None, a='one', abc='two')
-        (out, err) = pipe.communicate()
-        self.assertEqual(err, b'')
-        self.assertEqual(out, b'--abc=two|-a|-h|one\n')
-
-    def test_07_zero_padding(self):
-        """Can we get zero padded output"""
-        cron = crontab.CronTab(tab="02 3-5 2,4 */2 01 cmd")
-        self.assertEqual(str(cron), '2 3-5 2,4 */2 1 cmd\n')
-        with Attribute(crontab, 'ZERO_PAD', True):
-            self.assertEqual(str(cron), '02 03-05 02,04 */2 01 cmd\n')
-
-    def tearDown(self):
-        for filename in self.filenames:
-            if os.path.exists(filename):
-                os.unlink(filename)
-
-
-if __name__ == '__main__':
-    test_support.run_unittest(
-       UseTestCase,
-    )

+ 0 - 116
desktop/core/ext-py/python-crontab-2.3.6/tests/test_utf8.py

@@ -1,116 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Test crontab use of UTF-8 filenames and strings
-"""
-
-import os
-import sys
-
-import locale
-import unittest
-from crontab import CronTab, PY3
-try:
-    from test import test_support
-except ImportError:
-    from test import support as test_support
-
-TEST_DIR = os.path.dirname(__file__)
-
-if PY3:
-    unicode = str
-
-content = """
-*/4 * * * * ůțƒ_command # ůțƒ_comment
-"""
-filename = os.path.join(TEST_DIR, 'data', 'output-ůțƒ-8.tab')
-
-class Utf8TestCase(unittest.TestCase):
-    """Test basic functionality of crontab."""
-    def setUp(self):
-        self.crontab = CronTab(tab=content)
-
-    def test_01_input(self):
-        """Read UTF-8 contents"""
-        self.assertTrue(self.crontab)
-
-    def test_02_write(self):
-        """Write/Read UTF-8 Filename"""
-        self.assertEqual(locale.getpreferredencoding(), 'UTF-8')
-        self.crontab.write(filename)
-        crontab = CronTab(tabfile=filename)
-        self.assertTrue(crontab)
-        with open(filename, "r") as fhl:
-            self.assertEqual(content, fhl.read())
-        os.unlink(filename)
-
-    def test_04_command(self):
-        """Read Command String"""
-        self.assertEqual(self.crontab[0].command, u"ůțƒ_command")
-
-    def test_05_comment(self):
-        """Read Comment String"""
-        self.assertEqual(self.crontab[0].comment, u'ůțƒ_comment')
-
-    def test_06_unicode(self):
-        """Write New via Unicode"""
-        job = self.crontab.new(command=u"ůțƒ_command", comment=u'ůțƒ_comment')
-        self.assertEqual(job.command, u"ůțƒ_command")
-        self.assertEqual(job.comment, u"ůțƒ_comment")
-        self.crontab.render()
-
-    def test_07_utf8(self):
-        """Write New via UTF-8"""
-        job = self.crontab.new(command=b'\xc5\xaf\xc8\x9b\xc6\x92_command',
-                               comment=b'\xc5\xaf\xc8\x9b\xc6\x92_comment')
-        self.assertEqual(self.crontab.render(), u"""
-*/4 * * * * ůțƒ_command # ůțƒ_comment
-
-* * * * * ůțƒ_command # ůțƒ_comment
-""")
-        self.assertEqual(type(job.command), unicode)
-        self.assertEqual(type(job.comment), unicode)
-
-    def test_08_utf8_str(self):
-        """Test UTF8 (non unicode) strings"""
-        self.crontab[0].command = '£12'
-        self.crontab[0].comment = '𝗔𝗕𝗖𝗗'
-        self.assertEqual(self.crontab.render(), u"""
-*/4 * * * * £12 # 𝗔𝗕𝗖𝗗
-""")
-
-    def test_09_utf8_again(self):
-        """Test Extra UTF8 input"""
-        filename = os.path.join(TEST_DIR, 'data', 'utf_extra')
-        with open(filename + '.in', 'w') as fhl:
-            fhl.write('# 中文\n30 2 * * * source /etc/profile\n30 1 * * * source /etc/profile')
-
-        try:
-            cron = CronTab(tabfile=filename + '.in')
-        finally:
-            os.unlink(filename + '.in')
-
-        cron.write(filename + '.out')
-        if os.path.isfile(filename + '.out'):
-            os.unlink(filename + '.out')
-
-if __name__ == '__main__':
-    test_support.run_unittest(
-       Utf8TestCase,
-    )

+ 0 - 81
desktop/core/ext-py/python-crontab-2.3.6/tests/utils.py

@@ -1,81 +0,0 @@
-#
-# Copyright (C) 2018 Martin Owens
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3.0 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.
-#
-"""
-Provide some utilities to tests
-"""
-from logging import Handler, getLogger, root
-from collections import defaultdict
-
-# FLAG: do not report failures from here in tracebacks
-# pylint: disable=invalid-name
-__unittest = True
-
-class LoggingRecorder(Handler):
-    """Record any logger output for testing"""
-    def __init__(self, *args, **kwargs):
-        self.logs = defaultdict(list)
-        super(LoggingRecorder, self).__init__(*args, **kwargs)
-
-    def __getitem__(self, name):
-        return self.logs[name.upper()]
-
-    def emit(self, record):
-        """Save the log message to the right level"""
-        # We have no idea why record's getMessage is prefixed
-        msg = str(record.getMessage())
-        if msg.startswith('u"'):
-            msg = msg[1:]
-        if msg and (msg[0] == msg[-1] and msg[0] in '"\''):
-            msg = msg[1:-1]
-        self[record.levelname].append(msg)
-        return True
-
-
-class LoggingMixin(object):
-    """Provide logger capture"""
-    log_name = None
-
-    def setUp(self):
-        """Make a fresh logger for each test function"""
-        super(LoggingMixin, self).setUp()
-        named = getLogger(self.log_name)
-        for handler in root.handlers[:]:
-            root.removeHandler(handler)
-        for handler in named.handlers[:]:
-            named.removeHandler(handler)
-        self.log_handler = LoggingRecorder(level='DEBUG')
-        named.addHandler(self.log_handler)
-
-    def tearDown(self):
-        """Warn about untested logs"""
-        for level in self.log_handler.logs:
-            for msg in self.log_handler[level]:
-                raise ValueError("Uncaught log: {}: {}\n".format(level, msg))
-
-    def assertLog(self, level, msg):
-        """Checks that the logger has emitted the given log"""
-        logs = self.log_handler[level]
-        self.assertTrue(logs, 'Logger hasn\'t emitted "{}"'.format(msg))
-        if len(logs) == 1:
-            self.assertEqual(msg, logs[0])
-        else:
-            self.assertIn(msg, logs)
-        logs.remove(msg)
-
-    def assertNoLog(self, level, msg):
-        """Checks that the logger has NOT emitted the given log"""
-        self.assertNotIn(msg, self.log_handler[level])

+ 0 - 1
desktop/core/requirements.txt

@@ -40,7 +40,6 @@ nose==1.3.7
 openpyxl==2.6.2
 pyformance==0.3.2
 pysaml2>=4.5.0
-python-crontab==2.3.6
 python-dateutil==2.4.2
 python-daemon==2.2.4
 python-ldap==3.1.0

+ 0 - 1
desktop/core/requirements_py3.txt

@@ -73,7 +73,6 @@ Pygments==2.5.2
 pyOpenSSL==17.5.0
 pysaml2>=4.5.0
 PySocks==1.7.0
-python-crontab==2.3.6
 python-daemon==2.2.3
 python-dateutil==2.4.2
 python-ldap==3.1.0