Skip to content

Commit 5ba3054

Browse files
committed
big routing refactoring
1 parent b404a29 commit 5ba3054

File tree

8 files changed

+479
-328
lines changed

8 files changed

+479
-328
lines changed

lib/adapter/__init__.py

Whitespace-only changes.

lib/adapter/cheat_sheets.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import sys
2+
import os
3+
import glob
4+
5+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
6+
from globals import PATH_CHEAT_SHEETS
7+
8+
def _remove_initial_underscore(filename):
9+
if filename.startswith('_'):
10+
filename = filename[1:]
11+
return filename
12+
13+
def _sanitize_dirname(dirname):
14+
dirname = os.path.basename(dirname)
15+
dirname = _remove_initial_underscore(dirname)
16+
return dirname
17+
18+
def _format_answer(dirname, filename):
19+
return "%s/%s" % (_sanitize_dirname(dirname), filename)
20+
21+
def _get_answer_files_from_folder():
22+
topics = map(os.path.split, glob.glob(PATH_CHEAT_SHEETS + "*/*"))
23+
return [_format_answer(dirname, filename)
24+
for dirname, filename in topics if filename not in ['_info.yaml']]
25+
def _isdir(topic):
26+
return os.path.isdir(topic)
27+
def _get_answers_and_dirs():
28+
topics = glob.glob(PATH_CHEAT_SHEETS + "*")
29+
answer_dirs = [_remove_initial_underscore(os.path.split(topic)[1]).rstrip('/')+'/'
30+
for topic in topics if _isdir(topic)]
31+
answers = [os.path.split(topic)[1] for topic in topics if not _isdir(topic)]
32+
return answers, answer_dirs
33+
34+
def _update_cheat_sheets_topics():
35+
answers = _get_answer_files_from_folder()
36+
cheatsheet_answers, cheatsheet_dirs = _get_answers_and_dirs()
37+
return answers+cheatsheet_answers, cheatsheet_dirs
38+
39+
def get_list():
40+
return _update_cheat_sheets_topics()[0]
41+
42+
def get_dirs_list():
43+
return _update_cheat_sheets_topics()[1]
44+
45+
_CHEAT_SHEETS_LIST = get_list()
46+
def is_found(topic):
47+
return topic in _CHEAT_SHEETS_LIST
48+
49+
_CHEAT_SHEETS_DIRS = get_dirs_list()
50+
def is_dir_found(topic):
51+
return topic in _CHEAT_SHEETS_DIRS
52+
53+
def get_page(topic, request_options=None):
54+
"""
55+
Get the cheat sheet topic from the own repository (cheat.sheets).
56+
It's possible that topic directory starts with omitted underscore
57+
"""
58+
filename = PATH_CHEAT_SHEETS + "%s" % topic
59+
if not os.path.exists(filename):
60+
filename = PATH_CHEAT_SHEETS + "_%s" % topic
61+
if os.path.isdir(filename):
62+
return ""
63+
else:
64+
return open(filename, "r").read().decode('utf-8')
65+
66+
def get_dir(topic, request_options=None):
67+
answer = []
68+
for f_name in glob.glob(PATH_CHEAT_SHEETS + "%s/*" % topic.rstrip('/')):
69+
answer.append(os.path.basename(f_name))
70+
topics = sorted(answer)
71+
return "\n".join(topics) + "\n"

lib/adapter/cmd.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from gevent.monkey import patch_all
2+
from gevent.subprocess import Popen, PIPE
3+
patch_all()
4+
5+
import sys
6+
import os
7+
import glob
8+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
9+
10+
from globals import PATH_TLDR_PAGES, PATH_CHEAT_PAGES
11+
12+
def _get_filenames(path):
13+
return [os.path.split(topic)[1] for topic in glob.glob(path)]
14+
15+
def get_tldr_list():
16+
return [filename[:-3]
17+
for filename in _get_filenames(PATH_TLDR_PAGES) if filename.endswith('.md')]
18+
19+
_TLDR_LIST = get_tldr_list()
20+
def tldr_is_found(topic):
21+
return topic in _TLDR_LIST
22+
23+
def get_tldr(topic, request_options=None):
24+
cmd = ["tldr", topic]
25+
proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
26+
answer = proc.communicate()[0]
27+
28+
fixed_answer = []
29+
for line in answer.splitlines():
30+
line = line[2:]
31+
if line.startswith('-'):
32+
line = '# '+line[2:]
33+
elif not line.startswith(' '):
34+
line = "# "+line
35+
else:
36+
pass
37+
38+
fixed_answer.append(line)
39+
40+
answer = "\n".join(fixed_answer) + "\n"
41+
return answer.decode('utf-8')
42+
43+
def get_cheat_list():
44+
return _get_filenames(PATH_CHEAT_PAGES)
45+
46+
_CHEAT_LIST = get_cheat_list()
47+
def cheat_is_found(topic):
48+
return topic in _CHEAT_LIST
49+
50+
def get_cheat(topic, request_options=None):
51+
cmd = ["cheat", topic]
52+
proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
53+
answer = proc.communicate()[0].decode('utf-8')
54+
return answer
55+
56+
def get_translation(topic, request_options=None):
57+
from_, topic = topic.split('/', 1)
58+
to_ = request_options.get('lang', 'en')
59+
if '-' in from_:
60+
from_, to_ = from_.split('-', 1)
61+
62+
cmd = ["/home/igor/cheat.sh/bin/get_translation",
63+
from_, to_, topic.replace('+', ' ')]
64+
print("calling:", cmd)
65+
proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
66+
answer = proc.communicate()[0].decode('utf-8')
67+
return answer

lib/adapter/common.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Adapter(object):
2+
pass
3+
4+
class cheatAdapter(Adapter):
5+
pass
6+

lib/adapter/internal.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import sys
2+
import os
3+
import glob
4+
import collections
5+
6+
from fuzzywuzzy import process, fuzz
7+
8+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
9+
from globals import MYDIR, COLOR_STYLES
10+
from colorize_internal import colorize_internal
11+
12+
_INTERNAL_TOPICS = [
13+
":cht.sh",
14+
":bash_completion",
15+
":emacs",
16+
":emacs-ivy",
17+
":firstpage",
18+
":firstpage-v1",
19+
":firstpage-v2",
20+
":fish",
21+
":help",
22+
":intro",
23+
":list",
24+
":post",
25+
":styles",
26+
":styles-demo",
27+
":vim",
28+
":zsh",
29+
":share",
30+
]
31+
32+
_COLORIZED_INTERNAL_TOPICS = [
33+
':intro',
34+
]
35+
36+
class InternalPages(object):
37+
38+
def __init__(self, get_topic_type=None, get_topics_list=None):
39+
self.get_topic_type = get_topic_type
40+
self.get_topics_list = get_topics_list
41+
42+
def _get_stat(self):
43+
stat = collections.Counter([
44+
self.get_topic_type(topic)
45+
for topic in self.get_topics_list()
46+
])
47+
48+
answer = ""
49+
for key, val in stat.items():
50+
answer += "%s %s\n" % (key, val)
51+
return answer
52+
53+
54+
@staticmethod
55+
def get_list():
56+
return _INTERNAL_TOPICS
57+
58+
def _get_list_answer(self, topic, request_options=None):
59+
if '/' in topic:
60+
topic_type, topic_name = topic.split('/', 1)
61+
if topic_name == ":list":
62+
topic_list = [x[len(topic_type)+1:]
63+
for x in self.get_topics_list()
64+
if x.startswith(topic_type + "/")]
65+
return "\n".join(topic_list)+"\n"
66+
67+
answer = ""
68+
if topic == ":list":
69+
answer = "\n".join(x for x in self.get_topics_list()) + "\n"
70+
71+
return answer
72+
73+
def get_page(self, topic, request_options=None):
74+
if topic.endswith('/:list') or topic.lstrip('/') == ':list':
75+
return self._get_list_answer(topic)
76+
77+
answer = ""
78+
if topic == ':styles':
79+
answer = "\n".join(COLOR_STYLES) + "\n"
80+
elif topic == ":stat":
81+
answer = self._get_stat()+"\n"
82+
elif topic in _INTERNAL_TOPICS:
83+
answer = open(os.path.join(MYDIR, "share", topic[1:]+".txt"), "r").read()
84+
if topic in _COLORIZED_INTERNAL_TOPICS:
85+
answer = colorize_internal(answer)
86+
87+
return answer
88+
89+
def is_found(self, topic):
90+
return topic in self.get_list()
91+
92+
class UnknownPages(InternalPages):
93+
94+
@staticmethod
95+
def get_list():
96+
return []
97+
98+
@staticmethod
99+
def is_found(topic):
100+
return False
101+
102+
def get_page(self, topic, request_options=None):
103+
topics_list = self.get_topics_list()
104+
if topic.startswith(':'):
105+
topics_list = [x for x in topics_list if x.startswith(':')]
106+
else:
107+
topics_list = [x for x in topics_list if not x.startswith(':')]
108+
109+
possible_topics = process.extract(topic, topics_list, scorer=fuzz.ratio)[:3]
110+
possible_topics_text = "\n".join([(" * %s %s" % x) for x in possible_topics])
111+
return """
112+
Unknown topic.
113+
Do you mean one of these topics maybe?
114+
115+
%s
116+
""" % possible_topics_text

lib/adapter/latenz.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import sys
2+
import os
3+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
4+
5+
from globals import PATH_LATENZ
6+
7+
def get_answer(topic, request_options=None):
8+
sys.path.append(PATH_LATENZ)
9+
import latencies
10+
return latencies.render()
11+
12+
def get_list():
13+
return ['latencies']
14+
15+
def is_found(topic):
16+
return topic.lower() in ['latencies', 'late.nz', 'latency']

lib/adapter/question.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from gevent.monkey import patch_all
2+
from gevent.subprocess import Popen, PIPE
3+
patch_all()
4+
5+
import sys
6+
import os
7+
import re
8+
9+
from polyglot.detect import Detector
10+
from polyglot.detect.base import UnknownLanguage
11+
12+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
13+
from globals import MYDIR
14+
15+
def get_page(topic, request_options=None):
16+
"""
17+
Find answer for the `topic` question.
18+
"""
19+
20+
# if there is a language name in the section name,
21+
# cut it off (de:python => python)
22+
if '/' in topic:
23+
section_name, topic = topic.split('/', 1)
24+
if ':' in section_name:
25+
_, section_name = section_name.split(':', 1)
26+
topic = "%s/%s" % (section_name, topic)
27+
28+
# some clients send queries with - instead of + so we have to rewrite them to
29+
topic = re.sub(r"(?<!-)-", ' ', topic)
30+
31+
topic_words = topic.split()
32+
33+
topic = " ".join(topic_words)
34+
35+
lang = 'en'
36+
try:
37+
query_text = topic # " ".join(topic)
38+
query_text = re.sub('^[^/]*/+', '', query_text.rstrip('/'))
39+
query_text = re.sub('/[0-9]+$', '', query_text)
40+
query_text = re.sub('/[0-9]+$', '', query_text)
41+
detector = Detector(query_text)
42+
supposed_lang = detector.languages[0].code
43+
if len(topic_words) > 2 or supposed_lang in ['az', 'ru', 'uk', 'de', 'fr', 'es', 'it', 'nl']:
44+
lang = supposed_lang
45+
if supposed_lang.startswith('zh_') or supposed_lang == 'zh':
46+
lang = 'zh'
47+
elif supposed_lang.startswith('pt_'):
48+
lang = 'pt'
49+
if supposed_lang in ['ja', 'ko']:
50+
lang = supposed_lang
51+
52+
except UnknownLanguage:
53+
print("Unknown language (%s)" % query_text)
54+
55+
if lang != 'en':
56+
topic = ['--human-language', lang, topic]
57+
else:
58+
topic = [topic]
59+
60+
cmd = [os.path.join(MYDIR, "bin/get-answer-for-question")] + topic
61+
proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
62+
answer = proc.communicate()[0].decode('utf-8')
63+
return answer

0 commit comments

Comments
 (0)