diff options
Diffstat (limited to 'py-fake-service')
28 files changed, 0 insertions, 1335 deletions
diff --git a/py-fake-service/app/__init__.py b/py-fake-service/app/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/py-fake-service/app/__init__.py +++ /dev/null diff --git a/py-fake-service/app/adapter/__init__.py b/py-fake-service/app/adapter/__init__.py deleted file mode 100644 index 55f91e08..00000000 --- a/py-fake-service/app/adapter/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from mail_service import MailService diff --git a/py-fake-service/app/adapter/contacts.py b/py-fake-service/app/adapter/contacts.py deleted file mode 100644 index 30ff1253..00000000 --- a/py-fake-service/app/adapter/contacts.py +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -import re - - -class Contacts: - - def __init__(self): - self.contacts = [] - - def add(self, mbox_mail): - contact = mbox_mail.get('From') or mbox_mail.from_addr - self.contacts.append(Contact(contact)) - - def search(self, query): - contacts_query = re.compile(query) - return [ - contact.__dict__ - for contact in self.contacts - if contacts_query.match(contact.addresses[0]) - ] - - -class Contact: - - def __init__(self, contact): - self.addresses = [contact] - self.name = '' diff --git a/py-fake-service/app/adapter/mail.py b/py-fake-service/app/adapter/mail.py deleted file mode 100644 index 26c00277..00000000 --- a/py-fake-service/app/adapter/mail.py +++ /dev/null @@ -1,91 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from datetime import datetime -import random -import calendar -from dateutil import parser - -class Mail: - - NOW = calendar.timegm( - datetime.strptime( - datetime.now().isoformat(), - "%Y-%m-%dT%H:%M:%S.%f").timetuple()) - - @staticmethod - def from_json(mail_json): - mail = Mail() - mail.header = mail_json['header'] - mail.header['date'] = datetime.now().isoformat() - mail.ident = mail_json.get('ident', 0) - mail.body = mail_json['body'] - mail.tags = mail_json['tags'] - mail.security_casing = {} - mail.status = [] - mail.draft_reply_for = mail_json.get('draft_reply_for', 0) - return mail - - def __init__(self, mbox_mail=None, ident=None): - if mbox_mail: - self.header = self._get_headers(mbox_mail) - self.ident = ident - self.body = self._get_body(mbox_mail) - self.tags = self._get_tags(mbox_mail) - self.security_casing = {} - self.status = self._get_status() - self.draft_reply_for = -1 - - def _get_body(self, message): - if message.is_multipart(): - boundary = '--{boundary}'.format( - boundary=message.get_boundary().strip()) - body_parts = [x.as_string() for x in message.get_payload()] - - body = boundary + '\n' - body += '{boundary}\n'.format(boundary=boundary).join(body_parts) - body += '{boundary}--\n'.format(boundary=boundary) - - return body - else: - return message.get_payload() - - def _get_status(self): - status = [] - if 'sent' in self.tags: - status.append('read') - - return status - - def _get_headers(self, mbox_mail): - headers = {} - headers['from'] = mbox_mail.get('From') or mbox_mail.from_addr - headers['to'] = [mbox_mail.get('To')] - headers['subject'] = mbox_mail.get('Subject') - headers['date'] = parser.parse(mbox_mail['Date']).isoformat() - headers['content_type'] = mbox_mail.get('Content-Type') - - return headers - - def _get_tags(self, mbox_mail): - return filter(len, mbox_mail.get('X-TW-Pixelated-Tags').split(', ')) - - @property - def subject(self): - return self.header['subject'] - - @property - def date(self): - return self.header['date'] diff --git a/py-fake-service/app/adapter/mail_service.py b/py-fake-service/app/adapter/mail_service.py deleted file mode 100644 index 2825af9d..00000000 --- a/py-fake-service/app/adapter/mail_service.py +++ /dev/null @@ -1,128 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -import os -import re -import mailbox - -from tagsset import TagsSet -from mailset import MailSet -from contacts import Contacts -from mail import Mail - - -class MailService: - MAILSET_PATH = os.path.join(os.environ['HOME'], 'mailsets', 'mediumtagged') - - def __init__(self): - self.mailset = MailSet() - self.tagsset = TagsSet() - self.contacts = Contacts() - - def reset(self): - self.mailset = MailSet() - self.tagsset = TagsSet() - self.contacts = Contacts() - - def _read_file(self, filename): - with open(filename, 'r') as fd: - return fd.read() - - def _create_message_from_file(self, filename): - data = self._read_file(filename) - return self.create_message_from_string(data, filename) - - def create_message_from_string(self, data, filename=None): - if data.startswith('From '): - msg = mailbox.mboxMessage(data) - from_addr = re.sub(r"^From ", "", msg.get_unixfrom()) - msg.from_addr = from_addr - msg.set_from(from_addr) - else: - msg = mailbox.Message(data) - msg.from_addr = msg.get('From') - return msg - - def _create_message_from_string(self, data): - return mailbox.Message(data) - - def load_mailset(self): - mbox_filenames = [ - filename - for filename in os.listdir - (self.MAILSET_PATH) if filename.startswith('mbox')] - messages = (self._create_message_from_file(os.path.join(self.MAILSET_PATH, mbox)) - for mbox in mbox_filenames) - - self.index_messages(messages) - - def index_messages(self, messages): - for message in messages: - self.mailset.add(message) - self.tagsset.add(message) - self.contacts.add(message) - - def mails(self, query, page, window_size): - mails = self.mailset.values() - mails = [mail for mail in mails if query.test(mail)] - return sorted(mails, key=lambda mail: mail.date, reverse=True) - - def mail(self, mail_id): - return self.mailset.get(mail_id) - - def search_contacts(self, query): - return self.contacts.search(query) - - def mark_as_read(self, mail_id): - self.mailset.mark_as_read(mail_id) - self.tagsset.mark_as_read(self.mail(mail_id).tags) - - def delete_mail(self, mail_id): - purged = self.mailset.delete(mail_id) - if not purged: - self.tagsset.increment_tag_total_count('trash') - - def update_tags_for(self, mail_id, new_tags): - mail = self.mail(mail_id) - - new_tags_set = set(new_tags) - old_tags_set = set(mail.tags) - - increment_set = new_tags_set - old_tags_set - decrement_set = old_tags_set - new_tags_set - - map(lambda x: self.tagsset.increment_tag_total_count(x), increment_set) - map(lambda x: self.tagsset.decrement_tag_total_count(x), decrement_set) - - mail.tags = new_tags - - def send(self, mail): - mail = Mail.from_json(mail) - self.mailset.update(mail) - self.tagsset.increment_tag_total_count('sent') - self.tagsset.decrement_tag_total_count('drafts') - return mail.ident - - def save_draft(self, mail): - mail = self.mailset.add_draft(Mail.from_json(mail)) - return mail.ident - - def update_draft(self, mail): - mail = Mail.from_json(mail) - self.mailset.update(mail) - return mail.ident - - def draft_reply_for(self, mail_id): - return self.mailset.find(draft_reply_for=mail_id) diff --git a/py-fake-service/app/adapter/mailset.py b/py-fake-service/app/adapter/mailset.py deleted file mode 100644 index bf7e8c67..00000000 --- a/py-fake-service/app/adapter/mailset.py +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from mail import Mail - - -class MailSet: - - def __init__(self): - self.ident = 0 - self.mails = {} - - def add(self, mbox_mail): - self.mails[self.ident] = Mail(mbox_mail, self.ident) - self.ident += 1 - - def values(self): - return self.mails.values() - - def get(self, mail_id): - return self.mails.get(mail_id) - - def mark_as_read(self, mail_id): - mail = self.get(mail_id) - mail.status.append('read') - - def delete(self, mail_id): - """ - Returns True if the email got purged, - else returns False meaning the email got moved to trash - """ - - mail = self.get(mail_id) - if 'trash' in mail.tags: - del self.mails[mail_id] - return True - mail.tags.append('trash') - return False - - def update(self, mail): - self.mails[mail.ident] = mail - - def add_draft(self, mail): - mail.ident = self.ident - self.mails[mail.ident] = mail - self.ident += 1 - return mail - - def find(self, draft_reply_for): - match = [ - mail - for mail in self.mails.values - () if mail.draft_reply_for == draft_reply_for] - if len(match) == 0: - return None - else: - return match[0] diff --git a/py-fake-service/app/adapter/tag.py b/py-fake-service/app/adapter/tag.py deleted file mode 100644 index b866d789..00000000 --- a/py-fake-service/app/adapter/tag.py +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. - - -class Tag: - DEFAULT_TAGS = ["inbox", "sent", "trash", "drafts"] - - def __init__(self, name, ident): - self.counts = { - 'total': 0, - 'read': 0, - 'starred': 0, - 'reply': 0 - } - - self.ident = ident - self.name = name.lower() - self.default = name in self.DEFAULT_TAGS - - def increment_count(self): - self.counts['total'] += 1 - - def increment_read(self): - self.counts['read'] += 1 - - def decrement_count(self): - self.counts['total'] -= 1 diff --git a/py-fake-service/app/adapter/tagsset.py b/py-fake-service/app/adapter/tagsset.py deleted file mode 100644 index 8e0d7ca3..00000000 --- a/py-fake-service/app/adapter/tagsset.py +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from tag import Tag - - -class TagsSet: - - DEFAULT_TAGS = ["inbox", "sent", "trash", "drafts"] - - def __init__(self): - self.ident = 0 - self.tags = {} - self.tags = {tag: self._create_new_tag(tag) for tag in self.DEFAULT_TAGS} - - def add(self, mbox_mail): - tags = filter(len, mbox_mail.get('X-TW-Pixelated-Tags').split(', ')) - for tag in tags: - tag = self._create_new_tag(tag) - tag.increment_count() - - def all_tags(self): - return self.tags.values() - - def mark_as_read(self, tags): - for tag in tags: - tag = tag.lower() - tag = self.tags.get(tag) - tag.increment_read() - - def increment_tag_total_count(self, tagname): - tag = self.tags.get(tagname) - if tag: - tag.increment_count() - else: - self._create_new_tag(tagname) - - def decrement_tag_total_count(self, tag): - self.tags.get(tag).decrement_count() - - def _create_new_tag(self, tag): - tag = Tag(tag, self.ident) - tag = self.tags.setdefault(tag.name, tag) - self.ident += 1 - return tag diff --git a/py-fake-service/app/pixelated_user_agent.py b/py-fake-service/app/pixelated_user_agent.py deleted file mode 100644 index 5931bce5..00000000 --- a/py-fake-service/app/pixelated_user_agent.py +++ /dev/null @@ -1,196 +0,0 @@ -# # Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from flask import Flask, request, Response, redirect -import os -import csv -import json -import datetime -import mailbox -import StringIO -import requests -from adapter import MailService -from search import SearchQuery - -app = Flask(__name__, static_url_path='', static_folder='../../web-ui/app') -MEDIUM_TAGGED_URL = 'https://static.wazokazi.is/py-mediumtagged.tar.gz' -client = None -converter = None -account = None -autoload = os.environ.get('AUTOLOAD', False) -mail_service = MailService() - - -def respond_json(entity): - response = json.dumps(entity) - return Response(response=response, mimetype="application/json") - - -@app.route('/disabled_features') -def disabled_features(): - return respond_json([]) - - -@app.route('/mails', methods=['POST']) -def save_draft_or_send(): - mail = request.json - if mail['ident']: - ident = mail_service.send(mail) - else: - ident = mail_service.save_draft(mail) - - return respond_json({'ident': ident}) - - -@app.route('/mails', methods=['PUT']) -def update_draft(): - mail = request.json - ident = mail_service.update_draft(mail) - return respond_json({'ident': ident}) - - -@app.route('/mails') -def mails(): - query = SearchQuery.compile(request.args.get('q', '')) - page = request.args.get('p', '') - window_size = request.args.get('w', '') - fetched_mails = mail_service.mails(query, page, window_size) - - mails = [mail.__dict__ for mail in fetched_mails] - response = { - "stats": { - "total": len(mails), - "read": 0, - "starred": 0, - "replied": 0 - }, - "mails": mails - } - - return respond_json(response) - - -@app.route('/mail/<int:mail_id>', methods=['DELETE']) -def delete_mails(mail_id): - mail_service.delete_mail(mail_id) - return respond_json(None) - - -@app.route('/tags') -def tags(): - tags = mail_service.tagsset.all_tags() - return respond_json([tag.__dict__ for tag in tags]) - - -@app.route('/mail/<int:mail_id>') -def mail(mail_id): - return respond_json(mail_service.mail(mail_id).__dict__) - - -@app.route('/mail/<int:mail_id>/tags', methods=['POST']) -def mail_tags(mail_id): - new_tags = request.json['newtags'] - mail_service.update_tags_for(mail_id, new_tags) - return respond_json(request.json['newtags']) - - -@app.route('/mail/<int:mail_id>/read', methods=['POST']) -def mark_mail_as_read(mail_id): - mail_service.mark_as_read(mail_id) - return "" - - -@app.route('/contacts') -def contacts(): - contacts_query = request.args.get('q') - return respond_json( - {'contacts': mail_service.search_contacts(contacts_query)}) - - -@app.route('/draft_reply_for/<int:mail_id>') -def draft_reply_for(mail_id): - mail = mail_service.draft_reply_for(mail_id) - if mail: - return respond_json(mail.__dict__) - else: - return respond_json(None) - - -def utf_8_encoder(unicode_csv_data): - for line in unicode_csv_data: - yield line.encode('utf-8') - - -@app.route('/control/mailset/csv/load', methods=['POST']) -def load_mailset_from_csv(): - csv_data = request.form.keys()[0] - csv_string = StringIO.StringIO(csv_data) - csv_reader = csv.reader(utf_8_encoder(csv_string)) - headers = csv_reader.next() - messages = [] - for row in csv_reader: - mail = "" - row[3] = ', '.join(filter(len, row[3].split(' '))) - for header, value in zip(headers, row): - if header == 'Body': - mail += "\n" - else: - mail += header + ": " - mail += value + "\n" - messages.append(mailbox.mboxMessage(mail)) - mail_service.index_messages(messages) - return respond_json(None) - - -@app.route('/control/mailset/<mailset>/load', methods=['POST']) -def load_mailset(mailset): - import os - from tarfile import TarFile - from gzip import GzipFile - mbox_root = os.path.join(os.environ['HOME'], 'mailsets') - if not os.path.isdir(os.path.join(mbox_root)): - os.mkdir(mbox_root) - - if len(os.listdir(mbox_root)) == 0: - response = requests.get(MEDIUM_TAGGED_URL, verify=False) - mbox_archive_path = os.path.join(mbox_root, 'py-mediumtagged.tar.gz') - mbox_archive = open(mbox_archive_path, 'w') - mbox_archive.write(response.content) - mbox_archive.close() - gzippedfile = GzipFile(filename=mbox_archive_path) - tarfile = TarFile(fileobj=gzippedfile) - tarfile.extractall(path=mbox_root) - - mail_service.reset() - mail_service.load_mailset() - - return respond_json(None) - - -@app.route('/') -def index(): - global autoload - if autoload: - load_mailset('mediumtagged') - autoload = False - - return app.send_static_file('index.html') - - -def setup(): - app.run(host="0.0.0.0", debug=True, port=4567) - - -if __name__ == '__main__': - setup() diff --git a/py-fake-service/app/search/__init__.py b/py-fake-service/app/search/__init__.py deleted file mode 100644 index d6d7b07c..00000000 --- a/py-fake-service/app/search/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from search_query import SearchQuery diff --git a/py-fake-service/app/search/search_query.py b/py-fake-service/app/search/search_query.py deleted file mode 100644 index 34e68601..00000000 --- a/py-fake-service/app/search/search_query.py +++ /dev/null @@ -1,86 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from scanner import StringScanner, StringRegexp -import re - - -def _next_token(): - return StringRegexp('[^\s]+') - - -def _separators(): - return StringRegexp('[\s&]+') - - -def _compile_tag(compiled, token): - tag = token.split(":").pop() - if token[0] == "-": - compiled["not_tags"].append(tag) - else: - compiled["tags"].append(tag) - return compiled - - -class SearchQuery: - - @staticmethod - def compile(query): - compiled = {"tags": [], "not_tags": [], "general": []} - - scanner = StringScanner(query.encode('utf8').replace("\"", "")) - first_token = True - while not scanner.is_eos: - token = scanner.scan(_next_token()) - - if not token: - scanner.skip(_separators()) - continue - - if ":" in token: - compiled = _compile_tag(compiled, token) - elif first_token: - compiled["general"].append(token) - - if not first_token: - first_token = True - - compiled["general"] = ' '.join(compiled["general"]) - return SearchQuery(compiled) - - def __init__(self, compiled): - self.compiled = compiled - - def test(self, mail): - if 'all' in self.compiled.get('tags'): - return True - - if set(self.compiled.get('not_tags')).intersection(set(mail.tags)): - return False - - if set(self.compiled.get('tags')).intersection(set(mail.tags)): - return True - - if self.compiled.get('general'): - search_terms = re.compile( - self.compiled['general'], - flags=re.IGNORECASE) - if search_terms.search(mail.subject+' '+mail.body): - return True - - if not [v for v in self.compiled.values() if v]: - return True - - return False diff --git a/py-fake-service/fake-user-agent-daemon b/py-fake-service/fake-user-agent-daemon deleted file mode 100755 index 621f463e..00000000 --- a/py-fake-service/fake-user-agent-daemon +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -export PYTHONPATH=`pwd`/app:$PYTHONPATH - -USER_AGENT_PORT=4567 - -function do_stop() { - test -e gunicorn.pid && (kill -9 $(cat gunicorn.pid) && rm gunicorn.pid && echo "Stopped User Agent") || echo "User Agent is not running" -} - -function do_start() { - echo "gunicorn pixelated_user_agent:app -b 0.0.0.0:$USER_AGENT_PORT -D -p gunicorn.pid --log-file=gunicorn.log" - gunicorn pixelated_user_agent:app -b 0.0.0.0:$USER_AGENT_PORT -D -p gunicorn.pid --log-file=gunicorn.log -} - -case $1 in - restart) - do_stop && do_start - ;; - start) - do_start - ;; - stop) - do_stop - ;; - killall) - pgrep -f gunicorn | xargs kill -9 - rm -rf gunicorn.pid - ;; - *) - echo "usage: start|stop|restart|killall" - ;; -esac - diff --git a/py-fake-service/features/compose_save_draft_and_send.feature b/py-fake-service/features/compose_save_draft_and_send.feature deleted file mode 100644 index 7be7de0b..00000000 --- a/py-fake-service/features/compose_save_draft_and_send.feature +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. - -Feature: compose mail, save draft and send mail - - @wip - Scenario: user composes and email, save the draft, later sends the draft and checks the sent message - Given I compose a message with - | subject | body | - | Pixelated rocks! | You should definitely use it. Cheers, User. | - And for the 'To' field I type 'ab' and chose the first contact that shows - And I save the draft - When I open the saved draft and send it - Then I see that mail under the 'sent' tag - When I open that mail - Then I see that the subject reads 'Pixelated rocks!' - And I see that the body reads 'You should definitely use it. Cheers, User.' diff --git a/py-fake-service/features/environment.py b/py-fake-service/features/environment.py deleted file mode 100644 index 415391d6..00000000 --- a/py-fake-service/features/environment.py +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from selenium import webdriver - - -def before_feature(context, feature): - #context.browser = webdriver.Firefox() - context.browser = webdriver.PhantomJS() - context.browser.set_window_size(1280, 1024) - context.browser.implicitly_wait(5) - context.browser.set_page_load_timeout(60) # wait for data - context.browser.get('http://localhost:4567/') - - -def after_feature(context, feature): - context.browser.quit() - - -def take_screenshot(context): - context.browser.save_screenshot('/tmp/screenshot.jpeg') - - -def save_source(context): - with open('/tmp/source.html', 'w') as out: - out.write(context.browser.page_source.encode('utf8')) diff --git a/py-fake-service/features/forward_trash_archive.feature b/py-fake-service/features/forward_trash_archive.feature deleted file mode 100644 index fd7c6f6e..00000000 --- a/py-fake-service/features/forward_trash_archive.feature +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. - -Feature: forward_trash_archive - Scenario: User forwards a mail, add CC and BCC address, later trash and archive the mail - When I open the first mail in the 'inbox' - Then I choose to forward this mail - And for the 'CC' field I type 'ab' and chose the first contact that shows - And for the 'Bcc' field I type 'fr' and chose the first contact that shows - And I forward this mail - When I open the first mail in the 'sent' - Then I see the mail has a cc and a bcc recipient - And I remove all tags - And I choose to trash - Then I see that mail under the 'trash' tag diff --git a/py-fake-service/features/search_and_destroy.feature b/py-fake-service/features/search_and_destroy.feature deleted file mode 100644 index 5b0d550d..00000000 --- a/py-fake-service/features/search_and_destroy.feature +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. - -Feature: search html mail and destroy - - Scenario: User searches for a mail and deletes it - When I search for a mail with the words "this is a html mail" - When I open the first mail in the mail list - Then I see one or more mails in the search results - Then I see if the mail has html content - When I try to delete the first mail - # Then I learn that the mail was deleted - When I select the tag 'trash' - Then the deleted mail is there diff --git a/py-fake-service/features/steps/__init__.py b/py-fake-service/features/steps/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/py-fake-service/features/steps/__init__.py +++ /dev/null diff --git a/py-fake-service/features/steps/common.py b/py-fake-service/features/steps/common.py deleted file mode 100644 index ae46b04a..00000000 --- a/py-fake-service/features/steps/common.py +++ /dev/null @@ -1,83 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from selenium.webdriver.common.by import By -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.support.wait import WebDriverWait -from selenium.common.exceptions import NoSuchElementException -from hamcrest import * - -def wait_until_element_is_invisible_by_locator(context, locator_tuple): - wait = WebDriverWait(context.browser, 10) - wait.until(EC.invisibility_of_element_located(locator_tuple)) - -def wait_for_user_alert_to_disapear(context): - wait_until_element_is_invisible_by_locator(context, (By.ID, 'user-alerts')) - -def wait_until_element_is_visible_by_locator(context, locator_tuple): - wait = WebDriverWait(context.browser, 10) - wait.until(EC.visibility_of_element_located(locator_tuple)) - - -def fill_by_xpath(context, xpath, text): - field = context.browser.find_element_by_xpath(xpath) - field.send_keys(text) - -def take_screenshot(context, filename): - context.browser.save_screenshot(filename) - -def dump_source_to(context, filename): - with open(filename, 'w') as out: - out.write(context.browser.page_source.encode('utf8')) - -def page_has_css(context, css): - try: - find_element_by_css_selector(context, css) - return True - except NoSuchElementException: - return False - -def find_element_by_xpath(context, xpath): - return context.browser.find_element_by_xpath(xpath) - -def find_element_by_css_selector(context, css_selector): - return context.browser.find_element_by_css_selector(css_selector) - -def find_elements_by_css_selector(context, css_selector): - return context.browser.find_elements_by_css_selector(css_selector) - -def find_element_containing_text(context, text, element_type='*'): - return context.browser.find_element_by_xpath("//%s[contains(.,'%s')]" % (element_type, text)) - -def element_should_have_content(context, css_selector, content): - e = find_element_by_css_selector(context, css_selector) - assert_that(e.text, equal_to(content)) - -def wait_until_button_is_visible(context, title): - wait = WebDriverWait(context.browser, 10) - locator_tuple = (By.XPATH, ("//%s[contains(.,'%s')]" % ('button', title))) - wait.until(EC.visibility_of_element_located(locator_tuple)) - -def click_button(context, title): - button = find_element_containing_text(context, title, element_type='button') - button.click() - -def mail_subject(context): - e = find_element_by_css_selector(context, '#mail-view .subject') - return e.text - -def reply_subject(context): - e = find_element_by_css_selector(context, '#reply-subject') - return e.text diff --git a/py-fake-service/features/steps/compose.py b/py-fake-service/features/steps/compose.py deleted file mode 100644 index 24c2e679..00000000 --- a/py-fake-service/features/steps/compose.py +++ /dev/null @@ -1,73 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from behave import given, when -from selenium.webdriver.common.by import By -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.support.wait import WebDriverWait -from time import sleep -from common import * -from hamcrest import * - - -@given('I compose a message with') -def impl(context): - take_screenshot(context, '/tmp/screenshot.jpeg') - toggle = context.browser.find_element_by_id('compose-mails-trigger') - toggle.click() - - for row in context.table: - fill_by_xpath(context, '//*[@id="subject"]', row['subject']) - fill_by_xpath(context, '//*[@id="text-box"]', row['body']) - -@given("for the '{recipients_field}' field I type '{to_type}' and chose the first contact that shows") -def choose_impl(context, recipients_field, to_type): - browser = context.browser - browser.find_element_by_css_selector( - '#recipients-to-area span input.tt-input' - ).click() - recipients_field = recipients_field.lower() - css_selector = '#recipients-%s-area' % recipients_field - recipients_element = browser.find_element_by_css_selector(css_selector) - recipients_element.find_element_by_css_selector( - '.tt-input' - ).send_keys(to_type) - wait_until_element_is_visible_by_locator(context, (By.CSS_SELECTOR, '.tt-dropdown-menu div div')) - browser.find_element_by_css_selector('.tt-dropdown-menu div div').click() - -@then("for the '{recipients_field}' field I type '{to_type}' and chose the first contact that shows") -def choose_impl(context, recipients_field, to_type): - recipients_field = recipients_field.lower() - browser = context.browser - field = browser.find_element_by_css_selector( - '#recipients-%s-area .tt-input' % recipients_field - ) - field.send_keys(to_type) - sleep(1) - find_element_by_css_selector(context, '.tt-dropdown-menu div div').click() - -@given('I save the draft') -def save_impl(context): - context.browser.find_element_by_id('draft-button').click() - - -@when('I open the saved draft and send it') -def send_impl(context): - context.execute_steps(u"when I select the tag 'drafts'") - context.execute_steps(u"when I open the first mail in the mail list") - assert_that(is_not(page_has_css(context, '#send-button[disabled]'))) - click_button(context, 'Send') - element_should_have_content(context, '#user-alerts', 'Your message was sent!') - diff --git a/py-fake-service/features/steps/mail_list.py b/py-fake-service/features/steps/mail_list.py deleted file mode 100644 index 2ea90c2b..00000000 --- a/py-fake-service/features/steps/mail_list.py +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -import re -from behave import * -from common import * - -def find_current_mail(context): - return find_element_by_xpath(context, '//*[@id="mail-list"]/li[@id="mail-%s"]//a' % context.current_mail_id) - - -def check_current_mail_is_visible(context): - find_current_mail(context) - -def open_current_mail(context): - e = find_current_mail(context) - e.click() - -@then('I see that mail under the \'{tag}\' tag') -def impl(context, tag): - context.execute_steps("when I select the tag '%s'" % tag) - check_current_mail_is_visible(context) - -@when('I open that mail') -def impl(context): - open_current_mail(context) - -@when('I open the first mail in the mail list') -def impl(context): - elements = context.browser.find_elements_by_xpath('//*[@id="mail-list"]//a') - context.current_mail_id = elements[0].get_attribute('href').split('/')[-1] - elements[0].click() - -@when('I open the first mail in the \'{tag}\'') -def impl(context, tag): - context.browser.execute_script('window.scrollBy(0, -200)') - context.execute_steps(u"When I select the tag '%s'" % tag) - context.execute_steps(u'When I open the first mail in the mail list') - -@then('I open the mail I previously tagged') -def impl(context): - open_current_mail(context) - -@then('I see the mail I sent') -def impl(context): - src = context.browser.page_source - assert_that(src, contains_string(context.reply_subject)) - -@then('the deleted mail is there') -def impl(context): - check_current_mail_is_visible(context) - diff --git a/py-fake-service/features/steps/mail_view.py b/py-fake-service/features/steps/mail_view.py deleted file mode 100644 index 96208acc..00000000 --- a/py-fake-service/features/steps/mail_view.py +++ /dev/null @@ -1,96 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -import re -from selenium.webdriver.common.keys import Keys -from behave import * -from common import * -from hamcrest import * -from time import sleep - -@then('I see that the subject reads \'{subject}\'') -def impl(context, subject): - e = find_element_by_css_selector(context, '#mail-view .subject') - assert_that(e.text, equal_to(subject)) - -@then('I see that the body reads \'{expected_body}\'') -def impl(context, expected_body): - e = find_element_by_css_selector(context, '#mail-view .bodyArea') - assert_that(e.text, equal_to(expected_body)) - -@then('that email has the \'{tag}\' tag') -def impl(context, tag): - elements = find_elements_by_css_selector(context, '#mail-view .tagsArea .tag') - tags = [e.text for e in elements] - assert_that(tags, has_item(tag.upper())) - -@when('I add the tag \'{tag}\' to that mail') -def impl(context, tag): - context.browser.execute_script("$('#new-tag-button').click();") - context.browser.execute_script("$('#new-tag-input').val('%s');" % tag) - e = find_element_by_css_selector(context, '#new-tag-input') - e.send_keys(Keys.ENTER) - -@then('I reply to it') -def impl(context): - click_button(context, 'Reply') - click_button(context, 'Send') - context.reply_subject = reply_subject(context) - -@then('I see if the mail has html content') -def impl(context): - e = find_element_by_css_selector(context, '#mail-view .bodyArea') - h2 = e.find_element_by_css_selector("h2[style*='color: #3f4944']") - assert_that(h2.text, contains_string('cborim')) - -@when('I try to delete the first mail') -def impl(context): - context.execute_steps(u"When I open the first mail in the mail list") - find_element_by_css_selector(context, '#mail-view #view-more-actions').click() - context.browser.execute_script("$('#delete-button-top').click();") - - e = find_element_by_css_selector(context, '#user-alerts') - assert_that(e.text, equal_to('Your message was moved to trash!')) - -@then('I choose to forward this mail') -def impl(context): - wait_until_button_is_visible(context, 'Forward') - click_button(context, 'Forward') - -@then('I forward this mail') -def impl(context): - wait_until_button_is_visible(context, 'Send') - click_button(context, 'Send') - -@then('I remove all tags') -def impl(context): - e = find_element_by_css_selector(context, '.tagsArea') - tags = e.find_elements_by_css_selector('.tag') - assert_that(len(tags), greater_than(0)) - for tag in tags: - tag.click() - -@then('I choose to trash') -def impl(context): - wait_until_button_is_visible(context, 'Trash message') - click_button(context, 'Trash message') - -@then('I see the mail has a cc and a bcc recipient') -def impl(context): - cc = find_element_by_css_selector(context, '.msg-header .cc') - bcc = find_element_by_css_selector(context, '.msg-header .bcc') - - assert_that(cc.text, matches_regexp('[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+')) - diff --git a/py-fake-service/features/steps/search.py b/py-fake-service/features/steps/search.py deleted file mode 100644 index 9377bc5f..00000000 --- a/py-fake-service/features/steps/search.py +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from selenium.webdriver.common.keys import Keys -from behave import * -from common import * -from hamcrest import * -from time import sleep - -@when('I search for a mail with the words "{search_term}"') -def impl(context, search_term): - search_field = find_element_by_css_selector(context, '#search-trigger input[type="search"]') - search_field.send_keys(search_term) - search_field.send_keys(Keys.ENTER) - sleep(1) - -@then('I see one or more mails in the search results') -def impl(context): - lis = find_elements_by_css_selector(context, '#mail-list li') - assert_that(len(lis), greater_than_or_equal_to(1)) - diff --git a/py-fake-service/features/steps/tag_list.py b/py-fake-service/features/steps/tag_list.py deleted file mode 100644 index f62c390e..00000000 --- a/py-fake-service/features/steps/tag_list.py +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from behave import * -from selenium.webdriver.common.by import By -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.support.wait import WebDriverWait -from common import * - -def click_first_element_with_class(context, classname): - elements = context.browser.find_elements_by_class_name(classname) - elements[0].click() - - -@when('I select the tag \'{tag}\'') -def impl(context, tag): - wait_for_user_alert_to_disapear(context) - click_first_element_with_class(context, 'left-off-canvas-toggle') - context.browser.execute_script("window.scrollBy(0, -200)") - e = context.browser.find_element_by_xpath('//*[@id="tag-list"]/ul/li[contains(translate(., "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "%s")]' % tag) - e.click() diff --git a/py-fake-service/features/tag_and_reply.feature b/py-fake-service/features/tag_and_reply.feature deleted file mode 100644 index 5e28827f..00000000 --- a/py-fake-service/features/tag_and_reply.feature +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. - -Feature: tagging and replying - Scenario: User tags a mail, replies to it then checks that mail is in the right tag - When I open the first mail in the 'inbox' - Then that email has the 'inbox' tag - When I add the tag 'website' to that mail - Then I see that mail under the 'website' tag - And I open the mail I previously tagged - And I reply to it - When I select the tag 'sent' - Then I see the mail I sent - - diff --git a/py-fake-service/go b/py-fake-service/go deleted file mode 100755 index d0d83096..00000000 --- a/py-fake-service/go +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python -from app.pixelated_user_agent import setup -import os -os.environ['PIXELATED_UA_CFG']='../config/pixelated_ua.cfg' -setup() - diff --git a/py-fake-service/mailset.csv.example b/py-fake-service/mailset.csv.example deleted file mode 100644 index 25a78e31..00000000 --- a/py-fake-service/mailset.csv.example +++ /dev/null @@ -1,14 +0,0 @@ -From,To,Date,X-TW-Pixelated-Tags,Subject,Body -Nelson Hines,me,2014-09-01,football inbox,European Champions League predictions, -Rodrigo Vargas,me,2014-08-29,ux cryptography,A new secure email experience,"Hey there! Have you checked Pixelated already? " -Anita Foster,me,2014-08-29,philosophy,The importance of privacy, -Rufus Reynolds,me,2014-08-29,art,Gallery opening in Hamburg, -Natasha Carr,me,2014-08-28,travel,What to do in Tokyo?, -Linda Smith,me,2014-08-27,,Happy birthday!, -Geraldine Walsh,me,2014-08-27,ux,Lean UX workshop, -Clyde Fox,me,2014-08-27,cryptography software,Cryptoparty Porto Alegre, -Mark Garcia,me,2014-08-26,politics,Migrant workers Photography Exhibition, -Leona Payne,me,2014-08-25,,Online Philosophy Course, -Natalia Jones,me,2014-08-25,family,Grandma's gift, -Linda Smith,me,2014-08-25,ux,UX Book Club - September Meeting, -Anita Foster,me,2014-06-24,,Open source conferences in Africa, diff --git a/py-fake-service/requirements.txt b/py-fake-service/requirements.txt deleted file mode 100644 index 5dd57828..00000000 --- a/py-fake-service/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -flask==0.10.1 -scanner==0.0.5 -requests==2.3.0 -gunicorn==19.1.1 -python-dateutil diff --git a/py-fake-service/test-requirements.txt b/py-fake-service/test-requirements.txt deleted file mode 100644 index 021c68bb..00000000 --- a/py-fake-service/test-requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -PyHamcrest==1.8.0 -behave==1.2.4 -selenium==2.42.1 - |