Skip to content

Commit 0d9141d

Browse files
refeedrhttimabbott
committed
Add new new wildcard operators for web-public streams.
Now that we have a concept of web-public streams, many archive sites will want to use the set of web-public streams for their archive; rewrite the stream selection syntax to make that easy to do. Fixes #80. Fixes #zulip/zulip/21789. Co-authored-by: rht <rhtbot@protonmail.com> Co-authored-by: Tim Abbott <tabbott@zulip.com>
1 parent 8a3d53e commit 0d9141d

File tree

5 files changed

+64
-33
lines changed

5 files changed

+64
-33
lines changed

default_settings.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,20 +119,22 @@
119119
- data structures
120120
121121
122-
If you want to include all the streams you can use '*'
122+
A few wildcard operators are supported.
123123
124124
Example
125125
---
126126
127127
included:
128-
- '*'
128+
- 'web-public:*'
129129
130-
Using '*' includes all the **public streams** in Zulip archive. You
131-
can make the settings more restrictive than that, but not the opposite
132-
direction.
130+
Using 'web-public:*' includes all the **web-public streams** in the
131+
Zulip organization. Using 'public:*' includes all the **public
132+
streams** in Zulip archive (`*` will do the same thing, for
133+
backwards-compatibility). You can make the settings more restrictive
134+
than that, but not the opposite direction.
133135
134-
If you want to exclude some public streams, mention them under `excluded`
135-
category in `streams.yaml`
136+
If you want to exclude some public streams, mention them in the
137+
`excluded` category in `streams.yaml`.
136138
137139
Example:
138140
---

default_streams.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
included:
2-
- '*'
2+
- 'web-public:*'
33
# - general
44
# - javascript
55
# - data structures
6+
# - 'public:*'
67

78
excluded:
89
# - checkins

lib/common.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,20 @@ def stream_validator(settings):
2828
included_streams = set(settings.included_streams)
2929

3030
def validator(stream):
31-
if stream in excluded_streams:
31+
stream_name = stream["name"]
32+
is_web_public = stream["is_web_public"]
33+
is_public = not stream["invite_only"]
34+
35+
if stream_name in excluded_streams:
3236
return False
3337

34-
if "*" in included_streams:
38+
if "web-public:*" in included_streams and is_web_public:
39+
return True
40+
41+
# The bare * case is for backwards-compatibility.
42+
if ("*" in included_streams or "public:*" in included_streams) and is_public:
3543
return True
3644

37-
return stream in included_streams
45+
return stream_name in included_streams
3846

3947
return validator

lib/populate.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,13 @@ def safe_request(cmd, *args, **kwargs):
100100

101101

102102
def get_streams(client):
103-
# In the future, we may want to change this to
104-
# include_web_public=True, for organizations that might want to
105-
# use the upcoming web_public flag; but at the very least we
106-
# should only include public streams.
103+
# Fetch metadata on all streams the current user has access to.
104+
# We will filter these for processing via is_valid_stream_name.
107105
response = safe_request(
108-
client.get_streams, include_public=True, include_subscribed=False
106+
client.get_streams,
107+
include_public=True,
108+
include_subscribed=True,
109+
include_web_public=True,
109110
)
110111
return response["streams"]
111112

@@ -117,8 +118,7 @@ def populate_all(
117118
is_valid_stream_name,
118119
):
119120
all_streams = get_streams(client)
120-
121-
streams = [s for s in all_streams if is_valid_stream_name(s["name"])]
121+
streams = [s for s in all_streams if is_valid_stream_name(s)]
122122

123123
streams_data = {}
124124

@@ -199,7 +199,7 @@ def populate_incremental(
199199
js = json.load(f)
200200
f.close()
201201

202-
for s in (s for s in streams if is_valid_stream_name(s["name"])):
202+
for s in (s for s in streams if is_valid_stream_name(s)):
203203
print(s["name"])
204204
if s["name"] not in js["streams"]:
205205
js["streams"][s["name"]] = {

tests/testCommon.py

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
# For convenience, just run the tests from its own directory
2-
import os
1+
# For convenience, just run the tests in the repo root directory.
32
import sys
43

5-
os.chdir(os.path.dirname(sys.argv[0]))
6-
sys.path.append("../lib")
4+
sys.path.append("lib")
75

86
import common
97
import url
@@ -48,27 +46,49 @@ def test_sanitize():
4846

4947

5048
def test_validator():
51-
validator = common.stream_validator(Settings(included_streams=["*"]))
52-
53-
assert_equal(validator("foo"), True)
49+
def stream(name, public, web_public):
50+
# Returns a minimalist stream dictionary.
51+
return {"name": name, "invite_only": not public, "is_web_public": web_public}
52+
53+
# Test wildcard operator for public streams.
54+
for k in ["*", "public:*"]:
55+
validator = common.stream_validator(Settings(included_streams=[k]))
56+
assert_equal(validator(stream("foo", True, False)), True)
57+
assert_equal(validator(stream("foo", True, True)), True)
58+
assert_equal(validator(stream("bar", False, False)), False)
59+
assert_equal(validator(stream("bar", False, True)), False)
60+
61+
# Test web-public
62+
validator = common.stream_validator(Settings(included_streams=["web-public:*"]))
63+
assert_equal(validator(stream("foo", True, False)), False)
64+
assert_equal(validator(stream("foo", True, True)), True)
65+
assert_equal(validator(stream("bar", False, False)), False)
66+
assert_equal(validator(stream("bar", False, True)), True)
5467

5568
validator = common.stream_validator(Settings(included_streams=["foo", "bar"]))
56-
assert_equal(validator("foo"), True)
57-
assert_equal(validator("bar"), True)
58-
assert_equal(validator("baz"), False)
69+
assert_equal(validator(stream("foo", True, True)), True)
70+
assert_equal(validator(stream("bar", True, True)), True)
71+
assert_equal(validator(stream("baz", True, True)), False)
5972

73+
# Test exclude.
6074
validator = common.stream_validator(
6175
Settings(included_streams=["*"], excluded_streams=["bad", "worse"])
6276
)
63-
assert_equal(validator("good"), True)
64-
assert_equal(validator("bad"), False)
65-
assert_equal(validator("worse"), False)
77+
assert_equal(validator(stream("good", True, True)), True)
78+
assert_equal(validator(stream("bad", True, True)), False)
79+
assert_equal(validator(stream("worse", True, True)), False)
6680

6781
# edge case: excluded takes precedence over included
6882
validator = common.stream_validator(
6983
Settings(included_streams=["foo"], excluded_streams=["foo"])
7084
)
71-
assert_equal(validator("foo"), False)
85+
assert_equal(validator(stream("foo", False, False)), False)
86+
87+
validator = common.stream_validator(
88+
Settings(included_streams=["baz"], excluded_streams=["bar"])
89+
)
90+
assert_equal(validator(stream("foo", True, True)), False)
91+
assert_equal(validator(stream("bar", False, False)), False)
7292

7393

7494
if __name__ == "__main__":

0 commit comments

Comments
 (0)