vContent

Changeset

92:d39a2232c737
2017-12-03 Paul Boddie raw files shortlog changelog graph Introduce datetime information between selectors where appropriate. Added a function for obtaining the selector chain from a single root.
tests/qualifiers.py (file) vRecurrence.py (file)
     1.1 --- a/tests/qualifiers.py	Sun Dec 03 17:13:17 2017 +0100
     1.2 +++ b/tests/qualifiers.py	Sun Dec 03 19:19:14 2017 +0100
     1.3 @@ -39,6 +39,8 @@
     1.4  show(csel)
     1.5  
     1.6  s = get_selector(dt, sel)
     1.7 +csel = get_selectors_from_selector(s)
     1.8 +show(csel)
     1.9  
    1.10  l = s.materialise(dt, (2003, 12, 24))
    1.11  print len(l) == 7, 7, len(l)
    1.12 @@ -63,6 +65,8 @@
    1.13  show(csel)
    1.14  
    1.15  s = get_selector(dt, sel)
    1.16 +csel = get_selectors_from_selector(s)
    1.17 +show(csel)
    1.18  
    1.19  l = s.materialise(dt, (2003, 12, 24, 0, 0, 0))
    1.20  print len(l) == 34, 34, len(l)
    1.21 @@ -84,6 +88,8 @@
    1.22  show(csel)
    1.23  
    1.24  s = get_selector(dt, sel)
    1.25 +csel = get_selectors_from_selector(s)
    1.26 +show(csel)
    1.27  
    1.28  l = s.materialise(dt, (1997, 12, 24))
    1.29  print len(l) == 10, 10, len(l)
    1.30 @@ -104,6 +110,8 @@
    1.31  show(csel)
    1.32  
    1.33  s = get_selector(dt, sel)
    1.34 +csel = get_selectors_from_selector(s)
    1.35 +show(csel)
    1.36  
    1.37  l = s.materialise(dt, (1997, 12, 24, 0, 0, 0))
    1.38  print len(l) == 113, 113, len(l)
    1.39 @@ -124,6 +132,8 @@
    1.40  show(csel)
    1.41  
    1.42  s = get_selector(dt, sel)
    1.43 +csel = get_selectors_from_selector(s)
    1.44 +show(csel)
    1.45  
    1.46  l = s.materialise(dt, (1997, 12, 24, 0, 0, 0))
    1.47  print len(l) == 57, 57, len(l)
    1.48 @@ -144,6 +154,8 @@
    1.49  show(csel)
    1.50  
    1.51  s = get_selector(dt, sel)
    1.52 +csel = get_selectors_from_selector(s)
    1.53 +show(csel)
    1.54  
    1.55  l = s.materialise(dt, (1997, 12, 24, 0, 0, 0))
    1.56  print len(l) == 17, 17, len(l)
    1.57 @@ -165,6 +177,8 @@
    1.58  show(csel)
    1.59  
    1.60  s = get_selector(dt, sel)
    1.61 +csel = get_selectors_from_selector(s)
    1.62 +show(csel)
    1.63  
    1.64  l = s.materialise(dt, (1997, 12, 24, 0, 0, 0))
    1.65  print len(l) == 5, 5, len(l)
    1.66 @@ -187,6 +201,8 @@
    1.67  show(csel)
    1.68  
    1.69  s = get_selector(dt, sel)
    1.70 +csel = get_selectors_from_selector(s)
    1.71 +show(csel)
    1.72  
    1.73  l = s.materialise(dt, (2000, 1, 31, 14, 0, 0))
    1.74  print len(l) == 93, 93, len(l)
    1.75 @@ -208,6 +224,8 @@
    1.76  show(csel)
    1.77  
    1.78  s = get_selector(dt, sel)
    1.79 +csel = get_selectors_from_selector(s)
    1.80 +show(csel)
    1.81  
    1.82  l = s.materialise(dt, (2000, 1, 31, 14, 0, 0))
    1.83  print len(l) == 93, 93, len(l)
    1.84 @@ -229,6 +247,8 @@
    1.85  show(csel)
    1.86  
    1.87  s = get_selector(dt, sel)
    1.88 +csel = get_selectors_from_selector(s)
    1.89 +show(csel)
    1.90  
    1.91  l = s.materialise(dt, (1997, 12, 24, 0, 0, 0))
    1.92  print len(l) == 10, 10, len(l)
    1.93 @@ -249,6 +269,8 @@
    1.94  show(csel)
    1.95  
    1.96  s = get_selector(dt, sel)
    1.97 +csel = get_selectors_from_selector(s)
    1.98 +show(csel)
    1.99  
   1.100  l = s.materialise(dt, (1997, 12, 24, 0, 0, 0))
   1.101  print len(l) == 17, 17, len(l)
   1.102 @@ -269,6 +291,8 @@
   1.103  show(csel)
   1.104  
   1.105  s = get_selector(dt, sel)
   1.106 +csel = get_selectors_from_selector(s)
   1.107 +show(csel)
   1.108  
   1.109  l = s.materialise(dt, (1997, 12, 24, 0, 0, 0))
   1.110  print len(l) == 17, 17, len(l)
   1.111 @@ -289,6 +313,8 @@
   1.112  show(csel)
   1.113  
   1.114  s = get_selector(dt, sel)
   1.115 +csel = get_selectors_from_selector(s)
   1.116 +show(csel)
   1.117  
   1.118  l = s.materialise(dt, (1998, 2, 20, 0, 0, 0))
   1.119  print len(l) == 13, 13, len(l)
   1.120 @@ -310,6 +336,8 @@
   1.121  show(csel)
   1.122  
   1.123  s = get_selector(dt, sel)
   1.124 +csel = get_selectors_from_selector(s)
   1.125 +show(csel)
   1.126  
   1.127  l = s.materialise(dt, (1997, 10, 7, 9, 0, 0))
   1.128  print len(l) == 10, 10, len(l)
   1.129 @@ -332,6 +360,8 @@
   1.130  show(csel)
   1.131  
   1.132  s = get_selector(dt, sel)
   1.133 +csel = get_selectors_from_selector(s)
   1.134 +show(csel)
   1.135  
   1.136  l = s.materialise(dt, (1997, 12, 24, 0, 0, 0))
   1.137  print len(l) == 10, 10, len(l)
   1.138 @@ -353,6 +383,8 @@
   1.139  show(csel)
   1.140  
   1.141  s = get_selector(dt, sel)
   1.142 +csel = get_selectors_from_selector(s)
   1.143 +show(csel)
   1.144  
   1.145  l = s.materialise(dt, (1997, 12, 24, 0, 0, 0))
   1.146  print len(l) == 25, 25, len(l)
   1.147 @@ -375,6 +407,8 @@
   1.148  show(csel)
   1.149  
   1.150  s = get_selector(dt, sel)
   1.151 +csel = get_selectors_from_selector(s)
   1.152 +show(csel)
   1.153  
   1.154  l = s.materialise(dt, (1997, 12, 24, 0, 0, 0))
   1.155  print len(l) == 8, 8, len(l)
   1.156 @@ -397,6 +431,8 @@
   1.157  show(csel)
   1.158  
   1.159  s = get_selector(dt, sel)
   1.160 +csel = get_selectors_from_selector(s)
   1.161 +show(csel)
   1.162  
   1.163  l = s.materialise(dt, (1998, 12, 24, 0, 0, 0))
   1.164  print len(l) == 10, 10, len(l)
   1.165 @@ -418,6 +454,8 @@
   1.166  show(csel)
   1.167  
   1.168  s = get_selector(dt, sel)
   1.169 +csel = get_selectors_from_selector(s)
   1.170 +show(csel)
   1.171  
   1.172  l = s.materialise(dt, (1997, 12, 24, 0, 0, 0))
   1.173  print len(l) == 4, 4, len(l)
   1.174 @@ -440,6 +478,8 @@
   1.175  show(csel)
   1.176  
   1.177  s = get_selector(dt, sel)
   1.178 +csel = get_selectors_from_selector(s)
   1.179 +show(csel)
   1.180  
   1.181  l = s.materialise(dt, (1998, 12, 24, 0, 0, 0))
   1.182  print len(l) == 10, 10, len(l)
   1.183 @@ -462,6 +502,8 @@
   1.184  show(csel)
   1.185  
   1.186  s = get_selector(dt, sel)
   1.187 +csel = get_selectors_from_selector(s)
   1.188 +show(csel)
   1.189  
   1.190  l = s.materialise(dt, (1998, 12, 24, 0, 0, 0))
   1.191  print len(l) == 6, 6, len(l)
   1.192 @@ -484,6 +526,8 @@
   1.193  show(csel)
   1.194  
   1.195  s = get_selector(dt, sel)
   1.196 +csel = get_selectors_from_selector(s)
   1.197 +show(csel)
   1.198  
   1.199  l = s.materialise(dt, (1998, 12, 24, 0, 0, 0))
   1.200  print len(l) == 6, 6, len(l)
   1.201 @@ -506,6 +550,8 @@
   1.202  show(csel)
   1.203  
   1.204  s = get_selector(dt, sel)
   1.205 +csel = get_selectors_from_selector(s)
   1.206 +show(csel)
   1.207  
   1.208  l = s.materialise(dt, (1998, 12, 24, 0, 0, 0))
   1.209  print len(l) == 10, 10, len(l)
   1.210 @@ -528,6 +574,8 @@
   1.211  show(csel)
   1.212  
   1.213  s = get_selector(dt, sel)
   1.214 +csel = get_selectors_from_selector(s)
   1.215 +show(csel)
   1.216  
   1.217  l = s.materialise(dt, (1998, 12, 24, 0, 0, 0))
   1.218  print len(l) == 10, 10, len(l)
   1.219 @@ -550,6 +598,8 @@
   1.220  show(csel)
   1.221  
   1.222  s = get_selector(dt, sel)
   1.223 +csel = get_selectors_from_selector(s)
   1.224 +show(csel)
   1.225  
   1.226  l = s.materialise(dt, (1999, 12, 24, 0, 0, 0))
   1.227  print len(l) == 10, 10, len(l)
   1.228 @@ -571,6 +621,8 @@
   1.229  show(csel)
   1.230  
   1.231  s = get_selector(dt, sel)
   1.232 +csel = get_selectors_from_selector(s)
   1.233 +show(csel)
   1.234  
   1.235  l = s.materialise(dt, (1998, 4, 1, 0, 0, 0))
   1.236  print len(l) == 18, 18, len(l)
   1.237 @@ -593,6 +645,8 @@
   1.238  show(csel)
   1.239  
   1.240  s = get_selector(dt, sel)
   1.241 +csel = get_selectors_from_selector(s)
   1.242 +show(csel)
   1.243  
   1.244  l = s.materialise(dt, (2001, 12, 24, 0, 0, 0))
   1.245  print len(l) == 10, 10, len(l)
   1.246 @@ -615,6 +669,8 @@
   1.247  show(csel)
   1.248  
   1.249  s = get_selector(dt, sel)
   1.250 +csel = get_selectors_from_selector(s)
   1.251 +show(csel)
   1.252  
   1.253  l = s.materialise(dt, (2003, 12, 24, 0, 0, 0))
   1.254  print len(l) == 10, 10, len(l)
   1.255 @@ -637,6 +693,8 @@
   1.256  show(csel)
   1.257  
   1.258  s = get_selector(dt, sel)
   1.259 +csel = get_selectors_from_selector(s)
   1.260 +show(csel)
   1.261  
   1.262  l = s.materialise(dt, (2006, 2, 1, 0, 0, 0))
   1.263  print len(l) == 10, 10, len(l)
   1.264 @@ -658,6 +716,8 @@
   1.265  show(csel)
   1.266  
   1.267  s = get_selector(dt, sel)
   1.268 +csel = get_selectors_from_selector(s)
   1.269 +show(csel)
   1.270  
   1.271  l = s.materialise(dt, (1999, 12, 24, 0, 0, 0))
   1.272  print len(l) == 3, 3, len(l)
   1.273 @@ -681,6 +741,8 @@
   1.274  show(csel)
   1.275  
   1.276  s = get_selector(dt, sel)
   1.277 +csel = get_selectors_from_selector(s)
   1.278 +show(csel)
   1.279  
   1.280  l = s.materialise(dt, (1999, 12, 24, 0, 0, 0))
   1.281  print len(l) == 3, 3, len(l)
   1.282 @@ -704,6 +766,8 @@
   1.283  show(csel)
   1.284  
   1.285  s = get_selector(dt, sel)
   1.286 +csel = get_selectors_from_selector(s)
   1.287 +show(csel)
   1.288  
   1.289  l = s.materialise(dt, (1999, 12, 24, 0, 0, 0))
   1.290  print len(l) == 11, 11, len(l)
   1.291 @@ -726,6 +790,8 @@
   1.292  show(csel)
   1.293  
   1.294  s = get_selector(dt, sel)
   1.295 +csel = get_selectors_from_selector(s)
   1.296 +show(csel)
   1.297  
   1.298  l = s.materialise(dt, (1999, 12, 24, 0, 0, 0))
   1.299  print len(l) == 39, 39, len(l)
   1.300 @@ -748,6 +814,8 @@
   1.301  show(csel)
   1.302  
   1.303  s = get_selector(dt, sel)
   1.304 +csel = get_selectors_from_selector(s)
   1.305 +show(csel)
   1.306  
   1.307  l = s.materialise(dt, (2000, 12, 24, 0, 0, 0))
   1.308  print len(l) == 6, 6, len(l)
   1.309 @@ -770,6 +838,8 @@
   1.310  show(csel)
   1.311  
   1.312  s = get_selector(dt, sel)
   1.313 +csel = get_selectors_from_selector(s)
   1.314 +show(csel)
   1.315  
   1.316  l = s.materialise(dt, (1998, 6, 30, 0, 0, 0))
   1.317  print len(l) == 10, 10, len(l)
   1.318 @@ -793,6 +863,8 @@
   1.319  show(csel)
   1.320  
   1.321  s = get_selector(dt, sel)
   1.322 +csel = get_selectors_from_selector(s)
   1.323 +show(csel)
   1.324  
   1.325  l = s.materialise(dt, (2004, 12, 24, 0, 0, 0))
   1.326  print len(l) == 3, 3, len(l)
   1.327 @@ -816,6 +888,8 @@
   1.328  show(csel)
   1.329  
   1.330  s = get_selector(dt, sel)
   1.331 +csel = get_selectors_from_selector(s)
   1.332 +show(csel)
   1.333  
   1.334  l = s.materialise(dt, (1997, 12, 24, 0, 0, 0))
   1.335  print len(l) == 3, 3, len(l)
   1.336 @@ -840,6 +914,8 @@
   1.337  show(csel)
   1.338  
   1.339  s = get_selector(dt, sel)
   1.340 +csel = get_selectors_from_selector(s)
   1.341 +show(csel)
   1.342  
   1.343  l = s.materialise(dt, (1998, 4, 1, 0, 0, 0))
   1.344  print len(l) == 7, 7, len(l)
   1.345 @@ -858,6 +934,8 @@
   1.346  show(csel)
   1.347  
   1.348  s = get_selector(dt, sel)
   1.349 +csel = get_selectors_from_selector(s)
   1.350 +show(csel)
   1.351  
   1.352  l = s.materialise(dt, (2019, 1, 1))
   1.353  print len(l) == 37, 37, len(l)
   1.354 @@ -875,6 +953,8 @@
   1.355  show(csel)
   1.356  
   1.357  s = get_selector(dt, sel)
   1.358 +csel = get_selectors_from_selector(s)
   1.359 +show(csel)
   1.360  
   1.361  l = s.materialise(dt, (2019, 1, 1))
   1.362  print len(l) == 32, 32, len(l)
   1.363 @@ -892,6 +972,8 @@
   1.364  show(csel)
   1.365  
   1.366  s = get_selector(dt, sel)
   1.367 +csel = get_selectors_from_selector(s)
   1.368 +show(csel)
   1.369  
   1.370  l = s.materialise(dt, (2018, 1, 1))
   1.371  print len(l) == 18, 18, len(l)
     2.1 --- a/vRecurrence.py	Sun Dec 03 17:13:17 2017 +0100
     2.2 +++ b/vRecurrence.py	Sun Dec 03 19:19:14 2017 +0100
     2.3 @@ -488,24 +488,32 @@
     2.4      from_dt = get_next(iter_dt)
     2.5      from_sel = get_next(iter_sel)
     2.6      have_sel = False
     2.7 +    held_dt = []
     2.8  
     2.9      # Consume from both lists, merging entries.
    2.10  
    2.11 -    while from_dt and from_sel:
    2.12 -        _level = from_dt.level
    2.13 +    while from_sel:
    2.14          level = from_sel.level
    2.15  
    2.16          # Datetime value at wider resolution.
    2.17  
    2.18 -        if _level < level:
    2.19 +        if from_dt and from_dt.level < level:
    2.20 +            held_dt.append(from_dt)
    2.21              from_dt = get_next(iter_dt)
    2.22  
    2.23          # Qualifier at wider or same resolution as datetime value.
    2.24  
    2.25          else:
    2.26              if not have_sel:
    2.27 -                add_initial_selector(from_sel, level, l)
    2.28 -                have_sel = True
    2.29 +                have_sel = add_initial_selector(from_sel, level, l)
    2.30 +
    2.31 +            # Introduce any held datetime values, if appropriate.
    2.32 +
    2.33 +            elif can_restrict_selector(from_sel):
    2.34 +                for from_held_dt in held_dt:
    2.35 +                    add_datetime_selector(from_held_dt, l)
    2.36 +
    2.37 +            held_dt = []
    2.38  
    2.39              # Add the qualifier to the combined list.
    2.40  
    2.41 @@ -513,7 +521,7 @@
    2.42  
    2.43              # Datetime value at same resolution.
    2.44  
    2.45 -            if _level == level:
    2.46 +            if from_dt and from_dt.level == level:
    2.47                  from_dt = get_next(iter_dt)
    2.48  
    2.49              # Get the next qualifier.
    2.50 @@ -523,45 +531,44 @@
    2.51      # Complete the list by adding remaining datetime enumerators.
    2.52  
    2.53      while from_dt:
    2.54 -
    2.55 -        # Ignore datetime values that conflict with day-level qualifiers.
    2.56 -
    2.57 -        if not l or from_dt.level != freq["DAILY"] or \
    2.58 -           l[-1].level not in daylevels:
    2.59 -
    2.60 -            l.append(from_dt)
    2.61 -
    2.62 +        add_datetime_selector(from_dt, l)
    2.63          from_dt = get_next(iter_dt)
    2.64  
    2.65 -    # Complete the list by adding remaining qualifiers.
    2.66 +    return l
    2.67  
    2.68 -    while from_sel:
    2.69 -        if not have_sel:
    2.70 -            add_initial_selector(from_sel, level, l)
    2.71 -            have_sel = True
    2.72 +def can_restrict_selector(from_sel):
    2.73  
    2.74 -        # Add the qualifier to the combined list.
    2.75 -
    2.76 -        l.append(from_sel)
    2.77 +    "Return whether 'from_sel' can be restricted using datetime information."
    2.78  
    2.79 -        # Get the next qualifier.
    2.80 -
    2.81 -        from_sel = get_next(iter_sel)
    2.82 -
    2.83 -    return l
    2.84 +    return not isinstance(from_sel, Pattern) and from_sel.qualifier != "BYDAY"
    2.85  
    2.86  def add_initial_selector(from_sel, level, l):
    2.87  
    2.88      """
    2.89 -    Take the first selector 'from_sel' at the given resolution 'level', using it
    2.90 -    to create an initial selector, adding it to the combined list 'l' if
    2.91 -    required.
    2.92 +    Take the selector 'from_sel' at the given resolution 'level', using it to
    2.93 +    create an initial selector, adding it to the combined list 'l' if required.
    2.94 +
    2.95 +    Return whether a frequency selector has been introduced or if 'from_sel' is
    2.96 +    such a selector.
    2.97      """
    2.98  
    2.99      if isinstance(from_sel, Enum) and level > 0:
   2.100          parent_level = enum_parent_levels[level]
   2.101          repeat = Pattern(parent_level, {"interval" : 1}, freq_levels[parent_level])
   2.102          l.append(repeat)
   2.103 +        return True
   2.104 +
   2.105 +    return isinstance(from_sel, Pattern)
   2.106 +
   2.107 +def add_datetime_selector(from_dt, l):
   2.108 +
   2.109 +    """
   2.110 +    Take the selector 'from_dt' and add it to the list 'l' if it does not
   2.111 +    conflict with any day-level qualifiers already in 'l'.
   2.112 +    """
   2.113 +
   2.114 +    if not l or from_dt.level != freq["DAILY"] or l[-1].level not in daylevels:
   2.115 +        l.append(from_dt)
   2.116  
   2.117  def get_multiple(qualifier):
   2.118  
   2.119 @@ -1531,4 +1538,13 @@
   2.120          rule = (rule or "").split(";")
   2.121      return make_selectors(get_qualifiers(rule))
   2.122  
   2.123 +def get_selectors_from_selector(selector):
   2.124 +
   2.125 +    "Return the chain of selectors from 'selector', useful for debugging."
   2.126 +
   2.127 +    if selector.selecting:
   2.128 +        return [selector] + get_selectors_from_selector(selector.selecting)
   2.129 +    else:
   2.130 +        return [selector]
   2.131 +
   2.132  # vim: tabstop=4 expandtab shiftwidth=4