progress.pyx 4.87 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
#cython: language_level=3

'''
Created on 27 mars 2016

@author: coissac
'''

import sys
from ..utils import bytes2str,str2bytes
11
from .config    cimport getConfiguration 
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27


cdef class ProgressBar:
    cdef clock_t clock(self):
        cdef clock_t t
        cdef timeval tp
        cdef clock_t s
        
        <void> gettimeofday(&tp,NULL)
        s = <clock_t> (<double> tp.tv_usec * 1.e-6 * <double> CLOCKS_PER_SEC)
        t = tp.tv_sec * CLOCKS_PER_SEC + s 
        
        return t

    def __init__(self,
                 off_t maxi,
28
                 dict  config={},
29 30 31 32 33 34 35 36 37 38
                 str head="",
                 double seconde=0.1):
        self.starttime = self.clock()
        self.lasttime  = self.starttime
        self.tickcount = <clock_t> (seconde * CLOCKS_PER_SEC)
        self.freq      = 1
        self.cycle     = 0
        self.arrow     = 0
        self.lastlog   = 0
        
39
        
40 41 42 43 44 45
        self.ontty = sys.stderr.isatty()
        
        if (maxi<=0):
            maxi=1
            
        self.maxi = maxi
46 47
        self._head = str2bytes(head)
        self.chead= self._head 
48 49
        
        
50 51 52 53 54 55 56 57
        try:
            if not config:
                config=getConfiguration()
                
            self.logger=config[config["__root_config__"]]["logger"]
        except RuntimeError:
            self.logger=None

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
        self.wheel =  '|/-\\'
        self.spaces='          ' \
                    '          ' \
                    '          ' \
                    '          ' \
                    '          '
        self.diese ='##########' \
                    '##########' \
                    '##########' \
                    '##########' \
                    '##########'  
                           
    def __call__(self,object pos):
        cdef off_t    ipos
        cdef clock_t  elapsed
        cdef clock_t  newtime
        cdef clock_t  delta
        cdef clock_t  more 
        cdef double   percent 
        cdef tm remain
        cdef int days,hour,minu,sec
        cdef off_t fraction
80
        cdef int tenth
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
        
        self.cycle+=1
    
        if self.cycle % self.freq == 0:
            self.cycle=1
            newtime  = self.clock()
            delta         = newtime - self.lasttime
            self.lasttime = newtime
            elapsed       = newtime - self.starttime
#            print(" ",delta,elapsed,elapsed/CLOCKS_PER_SEC,self.tickcount)
            
            if   delta < self.tickcount / 5 :
                self.freq*=2
            elif delta > self.tickcount * 5 and self.freq>1:
                self.freq/=2
                
            
            if callable(pos):
                ipos=pos()
            else:
                ipos=pos
                
            if ipos==0:
                ipos=1                

            percent = <double>ipos/<double>self.maxi
            more = <time_t>((<double>elapsed / percent * (1. - percent))/CLOCKS_PER_SEC)
            <void>gmtime_r(&more, &remain)
            days  = remain.tm_yday 
            hour  = remain.tm_hour
            minu  = remain.tm_min
            sec   = remain.tm_sec
                
            if self.ontty:
                fraction=<int>(percent * 50.)
                self.arrow=(self.arrow+1) % 4
            
                if days:
119
                    <void>fprintf(stderr,b'\r%s %5.1f %% |%.*s%c%.*s] remain : %d days %02d:%02d:%02d',
120 121
                                    self.chead,
                                    percent*100,
122 123 124
                                    fraction,self.diese,
                                    self.wheel[self.arrow],
                                    50-fraction,self.spaces,
125 126
                                    days,hour,minu,sec)
                else:
127
                    <void>fprintf(stderr,b'\r%s %5.1f %% |%.*s%c%.*s] remain : %02d:%02d:%02d',
128 129
                                    self.chead,
                                    percent*100.,
130 131 132
                                    fraction,self.diese,
                                    self.wheel[self.arrow],
                                    50-fraction,self.spaces,
133 134
                                    hour,minu,sec)

135
            tenth = int(percent * 10)
136
            if tenth != self.lastlog and not self.ontty and self.logger is not None:
137
                
138 139 140
#                if self.ontty:
#                    <void>fputs(b'\n',stderr)
                                   
141
                self.logger.info('%s %5.1f %% remain : %02d:%02d:%02d' % (
142
                                        bytes2str(self._head),
143 144
                                        percent*100.,
                                        hour,minu,sec))
145
                self.lastlog=tenth
146 147 148
        else:
            self.cycle+=1

149 150 151 152 153 154 155 156
    property head:
    
        def __get__(self):
            return self._head
        
        def __set__(self,str value):
            self._head=str2bytes(value)
            self.chead=self._head