|
28 | 28 | data=json.loads(urllib.request.urlopen(url,timeout=1).read().decode())
|
29 | 29 |
|
30 | 30 | dates= []
|
31 |
| -names= [] |
| 31 | +releases= [] |
32 | 32 | foritemindata:
|
33 | 33 | if'rc'notinitem['tag_name']and'b'notinitem['tag_name']:
|
34 | 34 | dates.append(item['published_at'].split("T")[0])
|
35 |
| -names.append(item['tag_name']) |
36 |
| -# Convert date strings (e.g. 2014-10-18) to datetime |
37 |
| -dates= [datetime.strptime(d,"%Y-%m-%d")fordindates] |
| 35 | +releases.append(item['tag_name'].lstrip("v")) |
38 | 36 |
|
39 | 37 | exceptException:
|
40 | 38 | # In case the above fails, e.g. because of missing internet connection
|
41 | 39 | # use the following lists as fallback.
|
42 |
| -names= ['v2.2.4','v3.0.3','v3.0.2','v3.0.1','v3.0.0','v2.2.3', |
43 |
| -'v2.2.2','v2.2.1','v2.2.0','v2.1.2','v2.1.1','v2.1.0', |
44 |
| -'v2.0.2','v2.0.1','v2.0.0','v1.5.3','v1.5.2','v1.5.1', |
45 |
| -'v1.5.0','v1.4.3','v1.4.2','v1.4.1','v1.4.0'] |
46 |
| - |
| 40 | +releases= ['2.2.4','3.0.3','3.0.2','3.0.1','3.0.0','2.2.3', |
| 41 | +'2.2.2','2.2.1','2.2.0','2.1.2','2.1.1','2.1.0', |
| 42 | +'2.0.2','2.0.1','2.0.0','1.5.3','1.5.2','1.5.1', |
| 43 | +'1.5.0','1.4.3','1.4.2','1.4.1','1.4.0'] |
47 | 44 | dates= ['2019-02-26','2019-02-26','2018-11-10','2018-11-10',
|
48 | 45 | '2018-09-18','2018-08-10','2018-03-17','2018-03-16',
|
49 | 46 | '2018-03-06','2018-01-18','2017-12-10','2017-10-07',
|
50 | 47 | '2017-05-10','2017-05-02','2017-01-17','2016-09-09',
|
51 | 48 | '2016-07-03','2016-01-10','2015-10-29','2015-02-16',
|
52 | 49 | '2014-10-26','2014-10-18','2014-08-26']
|
53 | 50 |
|
54 |
| -# Convert date strings (e.g. 2014-10-18)todatetime |
55 |
| -dates= [datetime.strptime(d,"%Y-%m-%d")fordindates] |
| 51 | +dates= [datetime.strptime(d,"%Y-%m-%d")fordindates]# Convert strstodates. |
| 52 | +dates,releases=zip(*sorted(zip(dates,releases)))# Sort by increasing date. |
56 | 53 |
|
57 | 54 | # %%
|
58 | 55 | # Next, we'll create a stem plot with some variation in levels as to
|
|
64 | 61 | #
|
65 | 62 | # Note that Matplotlib will automatically plot datetime inputs.
|
66 | 63 |
|
67 |
| - |
68 |
| -# Choose some nice levels |
69 |
| -levels=np.tile([-5,5,-3,3,-1,1], |
70 |
| -int(np.ceil(len(dates)/6)))[:len(dates)] |
71 |
| - |
72 |
| -# Create figure and plot a stem plot with the date |
| 64 | +# Choose some nice levels: alternate minor releases between top and bottom, and |
| 65 | +# progressievly shorten the stems for bugfix releases. |
| 66 | +levels= [] |
| 67 | +major_minor_releases=sorted({release[:3]forreleaseinreleases}) |
| 68 | +forreleaseinreleases: |
| 69 | +major_minor=release[:3] |
| 70 | +bugfix=int(release[4]) |
| 71 | +h=1+0.8* (5-bugfix) |
| 72 | +level=hifmajor_minor_releases.index(major_minor)%2==0else-h |
| 73 | +levels.append(level) |
| 74 | + |
| 75 | +# The figure and the axes. |
73 | 76 | fig,ax=plt.subplots(figsize=(8.8,4),layout="constrained")
|
74 | 77 | ax.set(title="Matplotlib release dates")
|
75 | 78 |
|
76 |
| -ax.vlines(dates,0,levels,color="tab:red")# The vertical stems. |
77 |
| -ax.plot(dates,np.zeros_like(dates),"-o", |
78 |
| -color="k",markerfacecolor="w")# Baseline and markers on it. |
79 |
| - |
80 |
| -# annotate lines |
81 |
| -ford,l,rinzip(dates,levels,names): |
82 |
| -ax.annotate(r,xy=(d,l), |
83 |
| -xytext=(-3,np.sign(l)*3),textcoords="offset points", |
84 |
| -horizontalalignment="right", |
85 |
| -verticalalignment="bottom"ifl>0else"top") |
86 |
| - |
87 |
| -# format x-axis with 4-month intervals |
88 |
| -ax.xaxis.set_major_locator(mdates.MonthLocator(interval=4)) |
89 |
| -ax.xaxis.set_major_formatter(mdates.DateFormatter("%b %Y")) |
90 |
| -plt.setp(ax.get_xticklabels(),rotation=30,ha="right") |
91 |
| - |
92 |
| -# remove y-axis and spines |
| 79 | +# The vertical stems. |
| 80 | +ax.vlines(dates,0,levels, |
| 81 | +color=[("tab:red",1ifrelease.endswith(".0")else.5) |
| 82 | +forreleaseinreleases]) |
| 83 | +# The baseline. |
| 84 | +ax.axhline(0,c="black") |
| 85 | +# The markers on the baseline. |
| 86 | +minor_dates= [datefordate,releaseinzip(dates,releases)ifrelease[-1]=='0'] |
| 87 | +bugfix_dates= [datefordate,releaseinzip(dates,releases)ifrelease[-1]!='0'] |
| 88 | +ax.plot(bugfix_dates,np.zeros_like(bugfix_dates),"ko",mfc="white") |
| 89 | +ax.plot(minor_dates,np.zeros_like(minor_dates),"ko",mfc="tab:red") |
| 90 | + |
| 91 | +# Annotate the lines. |
| 92 | +fordate,level,releaseinzip(dates,levels,releases): |
| 93 | +ax.annotate(release,xy=(date,level), |
| 94 | +xytext=(-3,np.sign(level)*3),textcoords="offset points", |
| 95 | +verticalalignment="bottom"iflevel>0else"top", |
| 96 | +weight="bold"ifrelease.endswith(".0")else"normal", |
| 97 | +bbox=dict(boxstyle='square',pad=0,lw=0,fc=(1,1,1,0.7))) |
| 98 | + |
| 99 | +ax.yaxis.set(major_locator=mdates.YearLocator(), |
| 100 | +major_formatter=mdates.DateFormatter("%Y")) |
| 101 | + |
| 102 | +# Remove the y-axis and some spines. |
93 | 103 | ax.yaxis.set_visible(False)
|
94 | 104 | ax.spines[["left","top","right"]].set_visible(False)
|
95 | 105 |
|
|