Version history
===============

To find out how to migrate your application from a previous version of
APScheduler, see the :doc:`migration section <migration>`.

3.5.3
-----

* Fixed regression introduced in 3.5.2: Class methods were mistaken for instance methods and thus
  were broken during serialization
* Fixed callable name detection for methods in old style classes


3.5.2
-----

* Fixed scheduling of bound methods on persistent job stores (the workaround of scheduling
  ``YourClass.methodname`` along with an explicit ``self`` argument is no longer necessary as this
  is now done automatically for you)
* Added the FAQ section to the docs
* Made ``BaseScheduler.start()`` raise a ``RuntimeError`` if running under uWSGI with threads
  disabled


3.5.1
-----

* Fixed ``OverflowError`` on Windows when the wait time is too long

* Fixed ``CronTrigger`` sometimes producing fire times beyond ``end_date`` when jitter is enabled
  (thanks to gilbsgilbs for the tests)

* Fixed ISO 8601 UTC offset information being silently discarded from string formatted datetimes by
  adding support for parsing them


3.5.0
-----

* Added the ``engine_options`` option to ``SQLAlchemyJobStore``

* Added the ``jitter`` options to ``IntervalTrigger`` and ``CronTrigger`` (thanks to gilbsgilbs)

* Added combining triggers (``AndTrigger`` and ``OrTrigger``)

* Added better validation for the steps and ranges of different expressions in ``CronTrigger``

* Added support for named months (``jan`` – ``dec``) in ``CronTrigger`` month expressions

* Added support for creating a ``CronTrigger`` from a crontab expression

* Allowed spaces around commas in ``CronTrigger`` fields

* Fixed memory leak due to a cyclic reference when jobs raise exceptions
  (thanks to gilbsgilbs for help on solving this)

* Fixed passing ``wait=True`` to ``AsyncIOScheduler.shutdown()`` (although it doesn't do much)

* Cancel all pending futures when ``AsyncIOExecutor`` is shut down


3.4.0
-----

* Dropped support for Python 3.3

* Added the ability to specify the table schema for ``SQLAlchemyJobStore``
  (thanks to Meir Tseitlin)

* Added a workaround for the ``ImportError`` when used with PyInstaller and the likes
  (caused by the missing packaging metadata when APScheduler is packaged with these tools)


3.3.1
-----

* Fixed Python 2.7 compatibility in ``TornadoExecutor``


3.3.0
-----

* The asyncio and Tornado schedulers can now run jobs targeting coroutine functions
  (requires Python 3.5; only native coroutines (``async def``) are supported)

* The Tornado scheduler now uses TornadoExecutor as its default executor (see above as for why)

* Added ZooKeeper job store (thanks to Jose Ignacio Villar for the patch)

* Fixed job store failure (``get_due_jobs()``) causing the scheduler main loop to exit (it now
  waits a configurable number of seconds before retrying)

* Fixed ``@scheduled_job`` not working when serialization is required (persistent job stores and
  ``ProcessPoolScheduler``)

* Improved import logic in ``ref_to_obj()`` to avoid errors in cases where traversing the path with
  ``getattr()`` would not work (thanks to Jarek Glowacki for the patch)

* Fixed CronTrigger's weekday position expressions failing on Python 3

* Fixed CronTrigger's range expressions sometimes allowing values outside the given range


3.2.0
-----

* Added the ability to pause and unpause the scheduler

* Fixed pickling problems with persistent jobs when upgrading from 3.0.x

* Fixed AttributeError when importing apscheduler with setuptools < 11.0

* Fixed some events missing from ``apscheduler.events.__all__`` and
  ``apscheduler.events.EVENTS_ALL``

* Fixed wrong run time being set for date trigger when the timezone isn't the same as the local one

* Fixed builtin ``id()`` erroneously used in MongoDBJobStore's ``JobLookupError()``

* Fixed endless loop with CronTrigger that may occur when the computer's clock resolution is too
   low (thanks to Jinping Bai for the patch)


3.1.0
-----

* Added RethinkDB job store (contributed by Allen Sanabria)

* Added method chaining to the ``modify_job()``, ``reschedule_job()``, ``pause_job()`` and
   ``resume_job()`` methods in ``BaseScheduler`` and the corresponding methods in the ``Job`` class

* Added the EVENT_JOB_SUBMITTED event that indicates a job has been submitted to its executor.

* Added the EVENT_JOB_MAX_INSTANCES event that indicates a job's execution was skipped due to its
  maximum number of concurrently running instances being reached

* Added the time zone to the  repr() output of ``CronTrigger`` and ``IntervalTrigger``

* Fixed rare race condition on scheduler ``shutdown()``

* Dropped official support for CPython 2.6 and 3.2 and PyPy3

* Moved the connection logic in database backed job stores to the ``start()`` method

* Migrated to setuptools_scm for versioning

* Deprecated the various version related variables in the ``apscheduler`` module
  (``apscheduler.version_info``, ``apscheduler.version``, ``apscheduler.release``,
  ``apscheduler.__version__``)


3.0.6
-----

* Fixed bug in the cron trigger that produced off-by-1-hour datetimes when crossing the daylight
  saving threshold (thanks to Tim Strazny for reporting)


3.0.5
-----

* Fixed cron trigger always coalescing missed run times into a single run time
  (contributed by Chao Liu)

* Fixed infinite loop in the cron trigger when an out-of-bounds value was given in an expression

* Fixed debug logging displaying the next wakeup time in the UTC timezone instead of the
  scheduler's configured timezone

* Allowed unicode function references in Python 2


3.0.4
-----

* Fixed memory leak in the base executor class (contributed by Stefan Nordhausen)


3.0.3
-----

* Fixed compatibility with pymongo 3.0


3.0.2
-----

* Fixed ValueError when the target callable has a default keyword argument that wasn't overridden

* Fixed wrong job sort order in some job stores

* Fixed exception when loading all jobs from the redis job store when there are paused jobs in it

* Fixed AttributeError when printing a job list when there were pending jobs

* Added setuptools as an explicit requirement in install requirements


3.0.1
-----

* A wider variety of target callables can now be scheduled so that the jobs are still serializable
  (static methods on Python 3.3+, unbound methods on all except Python 3.2)

* Attempting to serialize a non-serializable Job now raises a helpful exception during
  serialization. Thanks to Jeremy Morgan for pointing this out.

* Fixed table creation with SQLAlchemyJobStore on MySQL/InnoDB

* Fixed start date getting set too far in the future with a timezone different from the local one

* Fixed _run_job_error() being called with the incorrect number of arguments in most executors


3.0.0
-----

* Added support for timezones (special thanks to Curtis Vogt for help with this one)

* Split the old Scheduler class into BlockingScheduler and BackgroundScheduler and added
  integration for asyncio (PEP 3156), Gevent, Tornado, Twisted and Qt event loops

* Overhauled the job store system for much better scalability

* Added the ability to modify, reschedule, pause and resume jobs

* Dropped the Shelve job store because it could not work with the new job store system

* Dropped the max_runs option and run counting of jobs since it could not be implemented reliably

* Adding jobs is now done exclusively through ``add_job()`` -- the shortcuts to triggers were
  removed

* Added the ``end_date`` parameter to cron and interval triggers

* It is now possible to add a job directly to an executor without scheduling, by omitting the
  trigger argument

* Replaced the thread pool with a pluggable executor system

* Added support for running jobs in subprocesses (via the ``processpool`` executor)

* Switched from nose to py.test for running unit tests


2.1.0
-----

* Added Redis job store

* Added a "standalone" mode that runs the scheduler in the calling thread

* Fixed disk synchronization in ShelveJobStore

* Switched to PyPy 1.9 for PyPy compatibility testing

* Dropped Python 2.4 support

* Fixed SQLAlchemy 0.8 compatibility in SQLAlchemyJobStore

* Various documentation improvements


2.0.3
-----

* The scheduler now closes the job store that is being removed, and all job stores on shutdown() by
  default

* Added the ``last`` expression in the day field of CronTrigger (thanks rcaselli)

* Raise a TypeError when fields with invalid names are passed to CronTrigger (thanks Christy
  O'Reilly)

* Fixed the persistent.py example by shutting down the scheduler on Ctrl+C

* Added PyPy 1.8 and CPython 3.3 to the test suite

* Dropped PyPy 1.4 - 1.5 and CPython 3.1 from the test suite

* Updated setup.cfg for compatibility with distutils2/packaging

* Examples, documentation sources and unit tests are now packaged in the source distribution


2.0.2
-----

* Removed the unique constraint from the "name" column in the SQLAlchemy
  job store

* Fixed output from Scheduler.print_jobs() which did not previously output
  a line ending at the end


2.0.1
-----

* Fixed cron style jobs getting wrong default values


2.0.0
-----

* Added configurable job stores with several persistent back-ends
  (shelve, SQLAlchemy and MongoDB)

* Added the possibility to listen for job events (execution, error, misfire,
  finish) on a scheduler

* Added an optional start time for cron-style jobs

* Added optional job execution coalescing for situations where several
  executions of the job are due

* Added an option to limit the maximum number of concurrenctly executing
  instances of the job

* Allowed configuration of misfire grace times on a per-job basis

* Allowed jobs to be explicitly named

* All triggers now accept dates in string form (YYYY-mm-dd HH:MM:SS)

* Jobs are now run in a thread pool; you can either supply your own PEP 3148
  compliant thread pool or let APScheduler create its own

* Maximum run count can be configured for all jobs, not just those using
  interval-based scheduling

* Fixed a v1.x design flaw that caused jobs to be executed twice when the
  scheduler thread was woken up while still within the allowable range of their
  previous execution time (issues #5, #7)

* Changed defaults for cron-style jobs to be more intuitive -- it will now
  default to all minimum values for fields lower than the least significant
  explicitly defined field


1.3.1
-----

* Fixed time difference calculation to take into account shifts to and from
  daylight saving time


1.3.0
-----

* Added __repr__() implementations to expressions, fields, triggers, and jobs
  to help with debugging

* Added the dump_jobs method on Scheduler, which gives a helpful listing of
  all jobs scheduled on it

* Fixed positional weekday (3th fri etc.) expressions not working except in
  some edge cases (fixes #2)

* Removed autogenerated API documentation for modules which are not part of
  the public API, as it might confuse some users

.. Note:: Positional weekdays are now used with the **day** field, not
   **weekday**.


1.2.1
-----

* Fixed regression: add_cron_job() in Scheduler was creating a CronTrigger with
  the wrong parameters (fixes #1, #3)

* Fixed: if the scheduler is restarted, clear the "stopped" flag to allow
  jobs to be scheduled again


1.2.0
-----

* Added the ``week`` option for cron schedules

* Added the ``daemonic`` configuration option

* Fixed a bug in cron expression lists that could cause valid firing times
  to be missed

* Fixed unscheduling bound methods via unschedule_func()

* Changed CronTrigger constructor argument names to match those in Scheduler


1.01
----

* Fixed a corner case where the combination of hour and day_of_week parameters
  would cause incorrect timing for a cron trigger
