Giter Site home page Giter Site logo

crython's Introduction

Hello.

How did I get here? I'm not good with computers.

crython's People

Contributors

a-mere-peasant avatar ahawker avatar aisipos avatar gitter-badger avatar jtratner avatar liangqun avatar pyup-bot avatar raverona avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

crython's Issues

get an Exception when you try to new a tab using 'logger' keyword

when you trying to new a tab like this:
Tab=crython.tab.CronTab(name='test',logger=logging.getLogger('xxx'))
it throws a Exception.
it is because you try to call the super function ,and thread.init() does't accept the keyword logger.
so you should pop the 'logger' keyword out ,the call super function

Week day doesn't work properly

There is some mismatch in weekday...

I am trying to run something on friday. But debug log shows it is not matching on a friday.

import crython
from datetime import datetime
import logging

logging.basicConfig(level=logging.DEBUG)

@crython.job(expr="*/25 * 9-16 * * fri *")
def test():
	print("im at %s",datetime.now())

crython.start()

#crython.stop()
#crython.join(timeout=5)

On Friday, logs:

DEBUG:crython.crython.expression:Field "weekday:4" does not match value "5"

Expression "@reboot" does not work

The expression @reboot does not work. Running crython.start() outputs this error:

Traceback (most recent call last):
[...
  File "/home/joost/Ontwikkeling/GoAbout/Docker/tarsnap/crython/local/lib/python2.7/site-packages/crython/job.py", line 39, in decorator
    wrapper.cron_expression = expression.CronExpression.new(expr, **fields)
  File "/home/joost/Ontwikkeling/GoAbout/Docker/tarsnap/crython/local/lib/python2.7/site-packages/crython/expression.py", line 116, in new
    return cls.from_str(expression) if expression else cls.from_kwargs(**kwargs)
  File "/home/joost/Ontwikkeling/GoAbout/Docker/tarsnap/crython/local/lib/python2.7/site-packages/crython/expression.py", line 127, in from_str
    fields = _expression_str_to_dict(expression, reboot_sentinel=reboot_sentinel)
  File "/home/joost/Ontwikkeling/GoAbout/Docker/tarsnap/crython/local/lib/python2.7/site-packages/crython/expression.py", line 69, in _expression_str_to_dict
    raise ValueError('Expression contains {0} fields; expects {1}'.format(len(values), expression_field_count))
ValueError: Expression contains 1 fields; expects 7

The cause is probably the line if expression is REBOOT_KEYWORD in expression.py which should be if expression == REBOOT_KEYWORD.

cron jobs run every second(bug)

the function 'matches' in expression.py always return true.
the problem is on line 195:
yield (name,match)
because yield return a tuple,so the all() method will always return True(forgive my pool English,I know why it performed like that,but I don't know how to say that).

to fix it ,just change like this
yield match
on line 195,expression.py

Add isort support

This package should leverage isort to enforce a consistent style for imports across modules.

  • Bring in dependency
  • Add isort config file
  • Add make target and add it to all linters target to run in Travis CI

See ulid for an integration example

Support Python 3.X

Add support for Python 3.X versions where "X" is still TBD (likely 3.2+).

Options:

  • PR #6 with a small compat file.
  • Add dependency on six

How to update job

Not an issue, but a question. Great work btw!

How do I update job with new cron expression.

I tried
crontab.start()
time.sleep(5)
update job expr with 'some new expr'
crontab.stop()
crontab.start()
time.sleep(5)

Not working
Log:
Traceback (most recent call last):
File "test-0.py", line 27, in
crython.start()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/crython/tab.py", line 129, in start
default_tab.start()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/threading.py", line 842, in start
raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once

Need to run all jobs from a mapping dictionary

First of all this module is just what I wanted (Supporting second-wide functionality)!!! Thanks for the author!
My problem is I have all config of tasks in DB and want to run all tasks one-by-one.
My code:

map_from_db = {
    '*/1 * * * * * *': 'every 1 sec',
    '*/2 * * * * * *': 'every 2 sec',
}

for ex, speech in map_from_db.items():
    @crython.job(expr=ex)
    def func():
        print(speech)

crython.start()

It seems crython is only selecting random one task and start running.
What should I do?

Using range

Checking in again!

when running:
@crython.job(hour=range(6,24,1))

I expected a trigger to happen every second, of every minute, og every hour between 6 and 24, however it seems as if the range have to start at 0 and end at 24, to fit the hour range.

However, when giving hour a list:
@crython.job(hour=[6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23])

I get the expected behavior. Maybe I am just missing something python-related. I just stumbled upon either an undocumented feature, using lists, or a bug when using range. You decide ;)

Reserved keywords are mapped to wrong expressions

Description of bug

Documentation in README mismatch for weekly cronjob expression.

# Fire once a week.

@crython.job(expr='0 0 0 * * 0 *')
def foo():
print "Back in line, maggot! - Kearny"

and

@Weekly | Run once a week at midnight in the morning of Sunday | 0 0 0 0 * 0 *

Looking in details of the expression in the code for @weekly keyword, we can see the actual expression used:

'@weekly': '0 0 0 0 * 0 *',

As shown in below section, the expression is not correct.

According to the crython docstring, this is how an expression is constructed:

    Represents an entire cron expression.
    An expression consists of seven, space delimited fields that represent the following values::
        +------------- second (0 - 59)
        | +------------- minute (0 - 59)
        | | +------------- hour (0 - 23)
        | | | +------------- day (1 - 31)
        | | | | +------------- month (1 - 12)
        | | | | | +------------- weekday (0 - 6) (Sunday to Saturday; 7 is also Sunday)
        | | | | | | +------------- year (1970 - 2099)
        | | | | | | |
        | | | | | | |
        * * * * * * *

I believe all keywords using incorrectly the day_in_month part of expressions set to 0 should fail?
I only tested it for the weekly keyword as shown below.

How to reproduce

Python 3.6.9 (default, Nov  7 2019, 10:44:02) 

In [1]: import pandas as pd
In [2]: import crython
In [3]: crython.__version__
Out[3]: '0.2.0'

In [5]: crython.expression.CronExpression.new('0 0 0 * * 0 *').matches(pd.Timestamp('2020-01-26 00:00:00'))
Out[5]: True

In [6]: crython.expression.CronExpression.new('0 0 0 0 * 0 *').matches(pd.Timestamp('2020-01-26 00:00:00'))
Out[6]: False

In [7]: crython.expression.CronExpression.new('@weekly').matches(pd.Timestamp('2020-01-26 00:00:00'))
Out[7]: False

pyup.io: Initial Update

Hi ๐Ÿ‘Š

This is my first visit to this fine repo, but it seems you have been working hard to keep all dependencies updated so far.

Once you have closed this issue, I'll create separate pull requests for every update as soon as I find one.

That's it for now!

Happy merging! ๐Ÿค–

using minute= only assumes second='*'

I just want to check in on this one, as I expect a different behaviour.

From the docs, we have:

# fire every 10 seconds
@crython.job(second=range(0,60,10))

which is true and good behaviour. However from that I expected the same use for minutes:

# fire every 10 minutes
@crython.job(minute=range(0,60,10))

But as second= defaults to '*', we actually get:

# fire every second of every 10th minute
@crython.job(minute=range(0,60,10))

Is this intended?

Full Windows Support

This issue tracks work for making Windows a first class citizen for this package.

  • - All tests passing
  • - CI/CD pipeline via AppVeyor

Keep the main script alive, threads with I/O

I've defined this example script main_foo.py which dies just after I execute it with python main_foo.py. If I enable that infinite while loop currently commented out at the bottom of the following example, then I see the script staying alive and printing logging statements as expected.

I have 2 questions:

  • Is this infinite while loop the expected way to keep alive the script? I was expecting the library was taking care itself of keeping the script alive with some sort of blocking infinite loop and I was surprised I had to take care of it myself, so I am wondering if I am using it the right way or is there a recommended way to do this?
  • Let's say I have first_func() in the following example which could potentially take more time than the recurrence at which it is scheduled. If the code inside first_func() is mainly network I/O (REST APIs) and numpy / pandas calculations (done in native C), then I should be good to go with crython invoking it multiple times even if some old executions still have to complete. I am assuming crython is running first_func() in a separate thread at each match of the crontab string (e.g. '*/5 * * * * * *'), so whenever this first_func() is finished the thread will die and crython will go on with no hiccups. Given that there is no CPU intensive code running in python (because the CPU intensive part is done in C), then I shouldn't be blocking the main thread of the main process, right? With this setup I should not mess with the GIL, I think.
import crython
import time

import sys
import logging
logging.basicConfig(
  format='%(asctime)s %(processName)-10s %(levelname)-6s %(message)s',
  level=logging.DEBUG,
  stream=sys.stdout
)

# every 5 seconds
@crython.job(expr='*/5 * * * * * *')
def first_func():
    logging.info("start 1st func")
    time.sleep(3) # but this could sometimes take more than 5 seconds
    logging.info("finish 1st func")

# every minute at seconds 1, 5 and 10
@crython.job(expr='1,5,10 * * * * * *')
def second_func():
    logging.info("2nd func")

if __name__ == "__main__":
    crython.start()
    # TODO is the following needed? 
    # while True:
    #    time.sleep(1)

Parameterize tests to test all partials

Currently, the tests in the multi-module-refactor branch mostly just test against the second field partial. This means that most fixtures are setup to create values based on the min/max/specials allowed by the second field.

Ideally, we want to parameterize all of the tests so we can feed in a field (or partial) with the valid min/max/specials and use the same test methods for all field types, not just second.

Range "10-26/8" matches "14".

I'm seeing this in the multi-module-refactor branch but likely a pre-existing bug and not a regression.

>>> from crython import field
>>> sec = field.second('10-26/8')
>>> sec.matches(10)
False
>>> sec.matches(18)
False
>>> sec.matches(14)
True

Does not work in python3.5

Here is the code
`import crython
#Fire every second.
@crython.job(second='*/10')
def foo():
print ( "I'm Homer Simpson. -- Grimey" )

if name == "main":
crython.start()`

Here is the result
Traceback (most recent call last):
File "ctest.py", line 3, in
@crython.job(second='*/10')
File "/Users/pete/lib/python3.5/site-packages/crython/job.py", line 27, in job
fields = dict((k, kwargs.pop(k)) for k in kwargs.keys() if k in field.NAMES)
File "/Users/pete/lib/python3.5/site-packages/crython/job.py", line 27, in
fields = dict((k, kwargs.pop(k)) for k in kwargs.keys() if k in field.NAMES)
RuntimeError: dictionary changed size during iteration

*/int syntax doesn't appear to work

Test script:

#!/usr/bin/env python
import crython
import time

@crython.job(second='*/3')
def foo():
    print("I'm using */3 syntax.")

@crython.job(second=range(0, 60, 2))
def bla():
    print("I'm using range(0, 60, 2).")

if __name__ == '__main__':
    crython.start()
    try:
        while True:
            time.sleep(0.2)
    except KeyboardInterrupt:
        pass

    print("Done")

Prints:

I'm using range(0, 60, 2).
I'm using range(0, 60, 2).
I'm using range(0, 60, 2).
... etc ...

I would expect "I'm using */3 syntax." to be printed every three seconds also, but it's not.

Is this a bug or am I doing something wrong ?

Latest master and pypi 0.0.4 version.

Add subprocess execution context

Add a "subprocess" context as a simple shortcut for subprocess.Popen instead of requiring users to write it themselves.

The initial thought it to just feed the result of the function directly into the subprocess.Popen call. However, we'll want to provide a way to pass *args and **kwargs down as well.

@crython.job(ctx='subprocess')
def cat(path):
    return 'cat {}'.format(path)

How to change the logging level

I am trying to change the logging level of the whole crython package, but this does not help:

# first
logging.basicConfig(
  format='%(asctime)s %(threadName)s %(funcName)-10s %(levelname)-6s %(message)s',
  level=logging.getLevelName("DEBUG"), # ATTENTION this string comes from a configuration file
  stream=sys.stdout
)

# then
crython_log = logging.getLogger("crython")
crython_log.setLevel(logging.INFO)
crython_log.propagate = True

# finally
@crython.job(expr="0 0 * * * * *")
def my_scheduled_func():
    # TODO do stuff
    logging.debug("do stuff")

How do I change the logging level only for the crython package?

Weekday should support 0-7 range; 7 being Sunday.

The weekday field should be support numeric range 0-7 in order to support zero and one based inputs.

Normally, the inputs are 0-6 with Sunday being zero and Saturday being six. However, Sunday being seven is also a valid possibility.

Feature: Block on global CronTab thread

As discussed in #262 , the crython module interface does not expose a mechanism to block/join on the default (global) CronTab instance. This makes processes that only run scheduled jobs significantly harder to write as well as any that don't block by binding to a socket.

Considerations:

  • block vs. join
  • special handling of re-joining a stopped instance beyond what stdlib does?

multi threading

hello

is this script available for multi threading or multiprocess jobs ?

Fix 'ctx' examples in README

Issue #249 brought up the question about running in multi-threaded/multi-process environments.

This is supported but incorrectly documented. The README should include a example of setting both thread and multiprocess contexts and not use the old, deprecated process value.

Exceptions being suppressed

Hello, let me start off by saying I'm a bit of a python beginner so excuse me if there's a well-documented way to solve this.

I noticed that if an exception occurs while a job is happening, the stack trace is not shown on the console. I wanted to pipe that output into a file or something so I can review, or better yet, pipe all exception stack traces to a function that logs to slack.

Is there a way to disable the exception output suppression?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.