rda-python-icoads 3.0.3__py3-none-any.whl → 3.0.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,8 +29,7 @@ class FillIcoads(PgIMMA):
29
29
  'names' : None,
30
30
  'files' : [],
31
31
  'dates' : [],
32
- 'dtlen' : 0,
33
- 'zipped' : 0
32
+ 'dtlen' : 0
34
33
  }
35
34
 
36
35
  #
@@ -112,12 +111,6 @@ class FillIcoads(PgIMMA):
112
111
  fcnt = 0
113
112
  tcounts = [0]*self.TABLECOUNT
114
113
  for file in self.PVALS['files']:
115
- pfile = self.get_partial_month_file(file) if addinventory else None
116
- if pfile:
117
- fcnt += 1
118
- acnts = self.process_imma_file(pfile, addinventory)
119
- for i in range(self.TABLECOUNT): tcounts[i] += acnts[i]
120
- if self.PVALS['zipped']: self.pgsystem("gzip " + pfile, self.LOGWRN, 5)
121
114
  fcnt += 1
122
115
  acnts = self.process_imma_file(file, addinventory)
123
116
  for i in range(self.TABLECOUNT): tcounts[i] += acnts[i]
@@ -152,49 +145,21 @@ class FillIcoads(PgIMMA):
152
145
  return self.format_date(pgrec['mdate']) if pgrec and pgrec['mdate'] else None
153
146
 
154
147
  #
155
- # locate a data file, gunzip it if only the gzipped one is on file
148
+ # the iidx values are allocated sequentially, so no date can be filled while an earlier one is
149
+ # still missing; a month must be filled up before the next month is filled, and a month cannot
150
+ # be skipped; months are sequenced by fillmonth, this only guards a direct call
156
151
  #
157
- def locate_imma_file(self, fname):
158
-
159
- self.PVALS['zipped'] = 0
160
- if op.isfile(fname): return fname
161
-
162
- zfile = fname + ".gz"
163
- if op.isfile(zfile):
164
- self.pgsystem("gunzip " + zfile, self.LOGWRN, 5)
165
- if op.isfile(fname):
166
- self.PVALS['zipped'] = 1
167
- return fname
168
-
169
- return None
170
-
171
- #
172
- # a month is filled up only if its last day is in the inventory; if an earlier month is
173
- # filled partially, return the name of its data file, to fill up the missing dates before
174
- # the given file is filled
175
- #
176
- def get_partial_month_file(self, fname):
152
+ def check_fill_order(self, fdate):
177
153
 
178
154
  mdate = self.get_max_filled_date()
179
- if not mdate: return None # nothing filled yet
180
-
181
- edate = self.enddate(mdate, 0, 'M')
182
- if mdate == edate: return None # the latest filled month is filled up
183
-
184
- fdate = self.get_imma_file_date(fname)
185
- if not fdate or self.diffdate(fdate, edate) <= 0: return None # the given file holds the partial month
186
-
187
- pgrec = self.pgget(f"{self.CNTLSC}.inventory", "fname", "date = '{}'".format(mdate), self.LGEREX)
188
- pfile = self.locate_imma_file(pgrec['fname']) if pgrec and pgrec['fname'] else None
189
- if not pfile:
190
- self.pglog("{}: month is filled through {} only, and its data file is not found in {} to "
191
- "fill it up before filling {}".format(mdate[0:7], mdate, op.abspath('.'), fdate[0:7]), self.LGEREX)
155
+ if not mdate: return # nothing filled yet
156
+ if self.diffdate(mdate, fdate) >= 0: return # the file holds filled dates already
192
157
 
193
- # the leading '>' propagates the note up through the calling processes, into the email report
194
- self.pglog("> {}: filled through {} only, fill it up from {} before filling {}".format(
195
- mdate[0:7], mdate, pfile, fdate[0:7]), self.LOGWRN)
158
+ rdate = self.adddate(mdate, 0, 0, 1) # the first missing date
159
+ if self.diffdate(fdate[0:7] + "-01", rdate) <= 0: return # the file covers it
196
160
 
197
- return pfile
161
+ self.pglog("{}: filled through {} only, fill from {} before filling {}".format(
162
+ mdate[0:7], mdate, rdate, fdate[0:7]), self.LGEREX)
198
163
 
199
164
  #
200
165
  # skip the dates that are filled already if the month of the given file is resumed
@@ -245,7 +210,9 @@ class FillIcoads(PgIMMA):
245
210
  edate = self.PVALS['dates'][1] if self.PVALS['dtlen'] > 1 else None
246
211
 
247
212
  fdate = self.get_imma_file_date(fname) if iname else None
248
- if fdate: bdate = self.get_resume_date(fname, fdate, bdate)
213
+ if fdate:
214
+ if self.PVALS['dtlen'] == 0: self.check_fill_order(fdate)
215
+ bdate = self.get_resume_date(fname, fdate, bdate)
249
216
 
250
217
  IMMA = open(fname, 'r', encoding = 'latin_1')
251
218
 
@@ -8,6 +8,7 @@
8
8
  # 2025-03-03 transferred to package rda_python_icoads from
9
9
  # https://github.com/NCAR/rda-icoads.git
10
10
  # 2026-09-04 convert to class FillMonth
11
+ # 2026-09-09 fill each missing month, in order, up to the given month
11
12
  # Purpose : process ICOADS monthly data file in IMMA1 format and fill into IVADDB
12
13
  #
13
14
  # Github : https://github.com/NCAR/rda-python-icoads.git
@@ -18,8 +19,9 @@ import sys
18
19
  import re
19
20
  from os import path as op
20
21
  from rda_python_common.pg_util import PgUtil
22
+ from rda_python_common.pg_dbi import PgDBI
21
23
 
22
- class FillMonth(PgUtil):
24
+ class FillMonth(PgUtil, PgDBI):
23
25
 
24
26
  def __init__(self):
25
27
  super().__init__()
@@ -27,7 +29,8 @@ class FillMonth(PgUtil):
27
29
  'filenames' : ["IMMA1_R3.0.2_", "IMMA1_R3.0.3_"], # IMMA1_R3.0.3_ since 2025-08
28
30
  'fillicoads' : "fillicoads -i ",
29
31
  'fillitable' : "fillitable -t -v dck pt sid -r ",
30
- 'cdmsmonth' : "cdmsmonth "
32
+ 'cdmsmonth' : "cdmsmonth ",
33
+ 'inventory' : "cntldb.inventory"
31
34
  }
32
35
 
33
36
  #
@@ -36,7 +39,7 @@ class FillMonth(PgUtil):
36
39
  def main(self):
37
40
 
38
41
  argv = sys.argv[1:]
39
- smonth = srange = None
42
+ smonth = None
40
43
 
41
44
  for arg in argv:
42
45
  if arg == "-b":
@@ -47,7 +50,6 @@ class FillMonth(PgUtil):
47
50
  ms = re.match(r'^(\d+)-(\d+)', arg)
48
51
  if ms:
49
52
  smonth = "{:04}-{:02}".format(int(ms.group(1)), int(ms.group(2)))
50
- srange = "{}-01 {}".format(smonth, self.enddate(smonth, 0, 'M'))
51
53
  else:
52
54
  self.pglog(arg +": Invalid month format", self.LGWNEX)
53
55
  else:
@@ -56,14 +58,62 @@ class FillMonth(PgUtil):
56
58
  if not smonth:
57
59
  print("Usage: fillmonth ProcessMonth")
58
60
  print(" Provide a month (YYYY-MM), to fill monthly IMMA1 into IVADDB")
61
+ print(" Any earlier month not filled up yet is filled first, in order")
59
62
  sys.exit(0)
60
63
 
61
64
  self.PGLOG['LOGFILE'] = "icoads.log"
65
+ self.ivaddb_dbname()
62
66
  self.cmdlog("fillmonth {}".format(' '.join(argv)))
63
- self.fill_monthly_data(smonth, srange)
67
+ months = self.get_fill_months(smonth)
68
+ if len(months) > 1:
69
+ self.pglog("> {}: fill {} months, {} through {}, in order".format(
70
+ smonth, len(months), months[0][0], months[-1][0]), self.LOGWRN)
71
+ mcnt = len(months)
72
+ for i in range(mcnt):
73
+ (cmonth, bdate, edate) = months[i]
74
+ self.fill_monthly_data(cmonth, "{} {}".format(bdate, edate))
75
+ if self.month_filled(cmonth, edate) or (i + 1) == mcnt: continue
76
+ # a later month cannot be filled while this one is short of dates
77
+ self.pglog("> {}: filled partially, stop before {}".format(cmonth, months[i+1][0]), self.LOGWRN)
78
+ break
64
79
  self.cmdlog()
65
80
  sys.exit(0)
66
81
 
82
+ #
83
+ # the iidx values are allocated sequentially, so every month between the last filled date
84
+ # and the given month must be filled, in order; return a [month, bdate, edate] per month,
85
+ # with bdate on the first month set to resume a partially filled month
86
+ #
87
+ def get_fill_months(self, smonth):
88
+
89
+ edate = self.enddate(smonth, 0, 'M')
90
+ pgrec = self.pgget(self.CMDS['inventory'], "max(date) mdate", "", self.LGEREX)
91
+ mdate = self.format_date(pgrec['mdate']) if pgrec and pgrec['mdate'] else None
92
+ if not mdate: return [[smonth, smonth + "-01", edate]] # nothing filled yet
93
+
94
+ bdate = self.adddate(mdate, 0, 0, 1) # resume the partial month, or start the next one
95
+ if self.diffdate(bdate, edate) > 0: return [[smonth, smonth + "-01", edate]] # refill an earlier month
96
+
97
+ months = []
98
+ while self.diffdate(bdate, edate) <= 0:
99
+ cmonth = bdate[0:7]
100
+ cedate = self.enddate(cmonth, 0, 'M')
101
+ if self.diffdate(cedate, edate) > 0: cedate = edate
102
+ months.append([cmonth, bdate, cedate])
103
+ bdate = self.adddate(cedate, 0, 0, 1)
104
+
105
+ return months
106
+
107
+ #
108
+ # check if the given month is filled through its last date
109
+ #
110
+ def month_filled(self, cmonth, edate):
111
+
112
+ pgrec = self.pgget(self.CMDS['inventory'], "max(date) mdate",
113
+ "date BETWEEN '{}-01' AND '{}'".format(cmonth, edate), self.LGEREX)
114
+
115
+ return (pgrec and pgrec['mdate'] and self.format_date(pgrec['mdate']) == edate)
116
+
67
117
  #
68
118
  # locate the monthly IMMA1 file, gunzip it if only the gzipped one is on file
69
119
  #
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rda_python_icoads
3
- Version: 3.0.3
3
+ Version: 3.0.4
4
4
  Summary: RDA python package to manage RDA ICOADS datasets
5
5
  Author-email: Zaihua Ji <zji@ucar.edu>
6
6
  Project-URL: Homepage, https://github.com/NCAR/rda-python-icoads
@@ -8,10 +8,10 @@ rda_python_icoads/countattm.py,sha256=HACWjl1J1gR-wObSAY_8WtJh6RGZG_b1dwE9NGr6ZF
8
8
  rda_python_icoads/countattmvar.py,sha256=5Xrg6zPxy0ckDUE0WYFVF9oDZRBOCTEQq0WQFd5VxRE,8571
9
9
  rda_python_icoads/counticoads.py,sha256=7SMu2HJBvUSmmThkNitAdvdyk7aO9dWKvdSv6VGBLng,5179
10
10
  rda_python_icoads/countsst.py,sha256=3jLrZUqlrZBVt9ib7nBO6n1D6jPL0T9Esu_elntHMDg,7170
11
- rda_python_icoads/fillicoads.py,sha256=kPk4SVaZhfA7DKSZEyiM0_ipsvq4Ct8ERN9J_e8KXxA,11146
11
+ rda_python_icoads/fillicoads.py,sha256=FXqo94_WKvRqHXRVw19vW5Ms2MivV_WkYXXzUIr2yLs,9951
12
12
  rda_python_icoads/fillinventory.py,sha256=cDcfjPAF2Ir991xO9PNMiGSB9boLCUj8txKAw3D_yzI,4617
13
13
  rda_python_icoads/fillitable.py,sha256=QpatUrSbIHcs-BCL8dBfZCM4FnQWwhArWnENhmvBZUQ,11178
14
- rda_python_icoads/fillmonth.py,sha256=jeelzcSFic29-R5JoaKr87iDygha0b9AaHSRbxxPluY,3405
14
+ rda_python_icoads/fillmonth.py,sha256=SoaAWSukfkppwSFvQ7d_k1jvG7ylPx2MZRbuFy5BNds,5719
15
15
  rda_python_icoads/fixiidx.py,sha256=5k6Intm4Zw5mAik-W-lnj167_YloP5THqaY96TMP4Mw,2333
16
16
  rda_python_icoads/imma1_subset.py,sha256=IX8vAdViFtcG3ai0_FQSro9038D2cRDcQdezUrNA6Kg,27566
17
17
  rda_python_icoads/maxsst.py,sha256=TroXmOKvy2VS0l6ILPJmVfVvDTynma_yoilaVDMXCZ8,9108
@@ -23,9 +23,9 @@ rda_python_icoads/msgsubset.f,sha256=KuM2WAk0ZFEH8LBhHKiGWt8zaW_0ARJXYV2kiD5w5xs
23
23
  rda_python_icoads/pg_imma.py,sha256=RDl2h-JScZxozVLHhebrEuAAUWtbU0_7BoJKZpxMhI8,66378
24
24
  rda_python_icoads/rdimma1_csv.f,sha256=_hOHvA0UiTykCIsj7ZYkmooNmUq29-p7ZnyjeSyvt8U,22443
25
25
  rda_python_icoads/writeicoads.py,sha256=HQqTp4m2erTV1bOkkBJZwDH6ispJPutPM3ZA8Y_giKI,5841
26
- rda_python_icoads-3.0.3.dist-info/licenses/LICENSE,sha256=1dck4EAQwv8QweDWCXDx-4Or0S8YwiCstaso_H57Pno,1097
27
- rda_python_icoads-3.0.3.dist-info/METADATA,sha256=nZybIybbtjmcxeiFOE1J48lhKGrsiISeWik6X23GnKI,3032
28
- rda_python_icoads-3.0.3.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
29
- rda_python_icoads-3.0.3.dist-info/entry_points.txt,sha256=RrLvvQNiBddv_LCYU9b49Zm3fpSl53DBOUXi22SVcE0,776
30
- rda_python_icoads-3.0.3.dist-info/top_level.txt,sha256=PjJe4PwUIiNxPlNg2d8JNPY1SLSu-_GHAdXe-hUVU1U,18
31
- rda_python_icoads-3.0.3.dist-info/RECORD,,
26
+ rda_python_icoads-3.0.4.dist-info/licenses/LICENSE,sha256=1dck4EAQwv8QweDWCXDx-4Or0S8YwiCstaso_H57Pno,1097
27
+ rda_python_icoads-3.0.4.dist-info/METADATA,sha256=WpYqpi94zQPu2k4BlMYj8-Nu7jo6TzTAZZxsRzRqty4,3032
28
+ rda_python_icoads-3.0.4.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
29
+ rda_python_icoads-3.0.4.dist-info/entry_points.txt,sha256=RrLvvQNiBddv_LCYU9b49Zm3fpSl53DBOUXi22SVcE0,776
30
+ rda_python_icoads-3.0.4.dist-info/top_level.txt,sha256=PjJe4PwUIiNxPlNg2d8JNPY1SLSu-_GHAdXe-hUVU1U,18
31
+ rda_python_icoads-3.0.4.dist-info/RECORD,,