2525import re
2626import sys
2727
28- import requests
2928import urllib .parse
29+ import urllib .request
3030from datetime import datetime
3131from typing import Optional
3232
4040# a pretty crude parser which relies on the data for each Android version being inserted
4141# in the table row for a particular API level, see level_to_version dict below.
4242#
43- # MacOS Note: Should work with the python3 that comes with the Xcode command line tools, but
44- # you'll need to install the 'requests' module, for example:
45- # python3 -m pip install requests
43+ # MacOS Note: Should work with the python3 that comes with the Xcode command line tools.
4644
4745versions_to_report_on = [
48- '14.0' , '13.0' , '12.0' , '11.0' , '10.0' , '9.0' ,
46+ '17.0' , '16.0' , '15.0' , ' 14.0' , '13.0' , '12.0' , '11.0' , '10.0' , '9.0' ,
4947 '8.1' , '8.0' , '7.1' , '7.0' , '6.0' , '5.1' , '5.0' ,
5048 '4.4' , '4.3' , '4.2' , '4.1' , '4.0'
5149]
5250
5351level_to_version = {
52+ 37 : '17.0' , 36 : '16.0' , 35 : '15.0' ,
5453 34 : '14.0' , 33 : '13.0' , 32 : '12.0' , 30 : '11.0' , 29 : '10.0' , 28 : '9.0' ,
5554 27 : '8.1' , 26 : '8.0' , 25 : '7.1' , 24 : '7.0' , 23 : '6.0' , 22 : '5.1' , 21 : '5.0' ,
5655 20 : '4.4' , 18 : '4.3' , 17 : '4.2' , 16 : '4.1' , 15 : '4.0'
@@ -69,21 +68,17 @@ def generate_stats_url() -> str:
6968 'region' : 'Worldwide' ,
7069 'csv' : '1'
7170 }
72- date_string = last_month_as_string ( )
71+ date_string = previous_month (). strftime ( "%Y-%m" )
7372 parameters ['fromMonthYear' ] = date_string
7473 parameters ['toMonthYear' ] = date_string
7574 return base + join_parameters (parameters )
7675
7776
78- def last_month_as_string () -> str :
79- month = datetime .now ().month
80- year = datetime .now ().year
81- if month == 1 :
82- month = 12
83- year -= 1
84- else :
85- month -= 1
86- return "{}-{:02d}" .format (year , month )
77+ def previous_month () -> datetime :
78+ now = datetime .now ()
79+ if now .month == 1 :
80+ return datetime (now .year - 1 , 12 , 1 )
81+ return datetime (now .year , now .month - 1 , 1 )
8782
8883
8984def join_parameters (parameters : dict [str , str ]) -> str :
@@ -103,23 +98,21 @@ def version_key(line: str) -> Optional[str]:
10398
10499
105100def download (url : str ) -> dict [str , float ]:
106- response = requests .get (url )
107- response .raise_for_status ()
108-
109- lines = (line .decode ('utf-8' ) for line in response .iter_lines ())
110- values = dict ()
111- for row in csv .reader (lines ):
112- key = version_key (row [0 ])
113- if key :
114- values [key ] = float (row [1 ])
101+ with urllib .request .urlopen (url ) as response :
102+ lines = (line .decode ('utf-8' ) for line in response )
103+ values = dict ()
104+ for row in csv .reader (lines ):
105+ key = version_key (row [0 ])
106+ if key :
107+ values [key ] = float (row [1 ])
115108 return values
116109
117110
118111def accumulate (input_values : dict [str , float ]) -> dict [str , float ]:
119112 cumulative = 0.0
120113 values = dict ()
121114 for key in versions_to_report_on :
122- cumulative += input_values [ key ]
115+ cumulative += input_values . get ( key , 0.0 )
123116 values [key ] = cumulative
124117 return values
125118
@@ -137,9 +130,9 @@ def __init__(self):
137130 self .level_re = re .compile ('.*Level (\\ d+)' )
138131 # Matches a line with a progressive-cell and extracts the current value.
139132 self .data_re = re .compile ('(.*progress-cell.html.* percentage=)([0-9.]+)(.*)' )
140- # Matches and extracts the "last updated" date.
133+ # Matches and extracts the "last updated" date and the StatCounter data month .
141134 self .updated_re = re .compile (
142- '(\\ s+<p>Cumulative.*updated on <b> )(\\ w+ \\ d+, \\ d+)(</b> using .*)' )
135+ '(\\ s+<p>Cumulative.*updated on )(\\ w+ \\ d+, \\ d+)( using <b>)( \\ w+ \\ d+)(</b> .*)' )
143136 # Current 'state', which is a reference to the method to use to process the next line.
144137 self .process = self .init
145138 # Last API level found which has not yet been used, else None.
@@ -201,8 +194,10 @@ def update_date(self, line: str) -> str:
201194 match = re .match (self .updated_re , line )
202195 if match :
203196 self .process = self .done
204- return ("{}{}{}\n "
205- .format (match [1 ], datetime .now ().strftime ("%B %d, %Y" ), match [3 ]))
197+ return "{}{}{}{}{}\n " .format (
198+ match [1 ], datetime .now ().strftime ("%B %d, %Y" ),
199+ match [3 ], previous_month ().strftime ("%B %Y" ),
200+ match [5 ])
206201 return line
207202
208203 # State reached after all substitutions have been performed.
0 commit comments