Merge branch 'develop'
This commit is contained in:
commit
bcc6de2bda
14 changed files with 167 additions and 40 deletions
|
|
@ -1,2 +1,2 @@
|
|||
from __future__ import unicode_literals
|
||||
__version__ = "6.10.0"
|
||||
__version__ = "6.10.1"
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import mimetypes, imghdr
|
|||
from frappe.utils import get_files_path
|
||||
|
||||
class FolderNotEmpty(frappe.ValidationError): pass
|
||||
class ThumbnailError(frappe.ValidationError): pass
|
||||
|
||||
exclude_from_linked_with = True
|
||||
|
||||
|
|
@ -154,13 +153,16 @@ class File(NestedSet):
|
|||
def make_thumbnail(self):
|
||||
if self.file_url:
|
||||
if self.file_url.startswith("/files"):
|
||||
image, filename, extn = get_local_image(self.file_url)
|
||||
try:
|
||||
image, filename, extn = get_local_image(self.file_url)
|
||||
except IOError:
|
||||
return
|
||||
|
||||
else:
|
||||
try:
|
||||
image, filename, extn = get_web_image(self.file_url)
|
||||
except ThumbnailError:
|
||||
frappe.msgprint("Unable to write file format for {0}".format(self.file_url))
|
||||
except requests.exceptions.HTTPError:
|
||||
return
|
||||
|
||||
thumbnail = ImageOps.fit(
|
||||
image,
|
||||
|
|
@ -177,6 +179,7 @@ class File(NestedSet):
|
|||
self.db_set("thumbnail_url", thumbnail_url)
|
||||
except IOError:
|
||||
frappe.msgprint("Unable to write file format for {0}".format(path))
|
||||
return
|
||||
|
||||
return thumbnail_url
|
||||
|
||||
|
|
@ -289,7 +292,7 @@ def get_local_image(file_url):
|
|||
image = Image.open(file_path)
|
||||
except IOError:
|
||||
frappe.msgprint("Unable to read file format for {0}".format(file_url))
|
||||
return
|
||||
raise
|
||||
|
||||
content = None
|
||||
|
||||
|
|
@ -315,9 +318,11 @@ def get_web_image(file_url):
|
|||
r.raise_for_status()
|
||||
except requests.exceptions.HTTPError, e:
|
||||
if "404" in e.args[0]:
|
||||
frappe.throw(_("File '{0}' not found").format(file_url))
|
||||
frappe.msgprint(_("File '{0}' not found").format(file_url))
|
||||
else:
|
||||
raise ThumbnailError
|
||||
frappe.msgprint("Unable to read file format for {0}".format(file_url))
|
||||
|
||||
raise
|
||||
|
||||
image = Image.open(StringIO.StringIO(r.content))
|
||||
|
||||
|
|
|
|||
|
|
@ -38,13 +38,13 @@ def add(args=None):
|
|||
and owner=%(assign_to)s""", args):
|
||||
frappe.msgprint(_("Already in user's To Do list"), raise_exception=True)
|
||||
return
|
||||
|
||||
|
||||
else:
|
||||
from frappe.utils import nowdate
|
||||
|
||||
|
||||
if args.get("re_assign"):
|
||||
remove_from_todo_if_already_assigned(args['doctype'], args['name'])
|
||||
|
||||
|
||||
d = frappe.get_doc({
|
||||
"doctype":"ToDo",
|
||||
"owner": args['assign_to'],
|
||||
|
|
@ -56,39 +56,38 @@ def add(args=None):
|
|||
"date": args.get('date', nowdate()),
|
||||
"assigned_by": args.get('assigned_by', frappe.session.user),
|
||||
}).insert(ignore_permissions=True)
|
||||
|
||||
|
||||
# set assigned_to if field exists
|
||||
if frappe.get_meta(args['doctype']).get_field("assigned_to"):
|
||||
frappe.db.set_value(args['doctype'], args['name'], "assigned_to", args['assign_to'])
|
||||
|
||||
# notify
|
||||
if not args.get("no_notification"):
|
||||
notify_assignment(d.assigned_by, d.owner, d.reference_type, d.reference_name, action='ASSIGN',\
|
||||
description=args.get("description"), notify=args.get('notify'))
|
||||
|
||||
notify_assignment(d.assigned_by, d.owner, d.reference_type, d.reference_name, action='ASSIGN',\
|
||||
description=args.get("description"), notify=args.get('notify'))
|
||||
|
||||
if not args.get("bulk_assign"):
|
||||
return get(args)
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_multiple(args=None):
|
||||
import json
|
||||
|
||||
|
||||
if not args:
|
||||
args = frappe.local.form_dict
|
||||
|
||||
|
||||
docname_list = json.loads(args['name'])
|
||||
|
||||
|
||||
for docname in docname_list:
|
||||
args.update({"name": docname})
|
||||
add(args)
|
||||
|
||||
|
||||
def remove_from_todo_if_already_assigned(doctype, docname):
|
||||
owner = frappe.db.get_value("ToDo", {"reference_type": doctype, "reference_name": docname, "status":"Open"}, "owner")
|
||||
if owner:
|
||||
remove(doctype, docname, owner)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def remove(doctype, name, assign_to):
|
||||
"""remove from todo"""
|
||||
|
|
@ -156,5 +155,6 @@ def notify_assignment(assigned_by, owner, doc_type, doc_name, action='CLOSE',
|
|||
}
|
||||
|
||||
arg["parenttype"] = "Assignment"
|
||||
|
||||
from frappe.desk.page.messages import messages
|
||||
messages.post(**arg)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ from poplib import error_proto
|
|||
import re
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from datetime import datetime, timedelta
|
||||
from frappe.desk.form import assign_to
|
||||
from frappe.utils.user import get_system_managers
|
||||
import socket
|
||||
|
||||
class SentEmailInInbox(Exception): pass
|
||||
|
||||
|
|
@ -96,7 +99,7 @@ class EmailAccount(Document):
|
|||
)
|
||||
server.sess
|
||||
|
||||
def get_pop3(self):
|
||||
def get_pop3(self, in_receive=False):
|
||||
"""Returns logged in POP3 connection object."""
|
||||
args = {
|
||||
"host": self.pop3_server,
|
||||
|
|
@ -111,18 +114,56 @@ class EmailAccount(Document):
|
|||
pop3 = POP3Server(frappe._dict(args))
|
||||
try:
|
||||
pop3.connect()
|
||||
|
||||
except error_proto, e:
|
||||
frappe.throw(e.message)
|
||||
if in_receive and e.message=="-ERR authentication failed":
|
||||
# if called via self.receive and it leads to authentication error, disable incoming
|
||||
# and send email to system manager
|
||||
self.handle_incoming_connect_error(
|
||||
description=_('Authentication failed while receiving emails from Email Account {0}'.format(self.name))
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
else:
|
||||
frappe.throw(e.message)
|
||||
|
||||
except socket.error:
|
||||
if in_receive:
|
||||
# timeout while connecting, see receive.py connect method
|
||||
description = frappe.message_log.pop() if frappe.message_log else "Socket Error"
|
||||
self.handle_incoming_connect_error(description=description)
|
||||
|
||||
return None
|
||||
|
||||
else:
|
||||
raise
|
||||
|
||||
return pop3
|
||||
|
||||
def handle_incoming_connect_error(self, description):
|
||||
self.db_set("enable_incoming", 0)
|
||||
|
||||
for user in get_system_managers(only_name=True):
|
||||
assign_to.add({
|
||||
'assign_to': user,
|
||||
'doctype': self.doctype,
|
||||
'name': self.name,
|
||||
'description': description,
|
||||
'priority': 'High',
|
||||
'notify': 1
|
||||
})
|
||||
|
||||
def receive(self, test_mails=None):
|
||||
"""Called by scheduler to receive emails from this EMail account using POP3."""
|
||||
if self.enable_incoming:
|
||||
if frappe.local.flags.in_test:
|
||||
incoming_mails = test_mails
|
||||
else:
|
||||
pop3 = self.get_pop3()
|
||||
pop3 = self.get_pop3(in_receive=True)
|
||||
if not pop3:
|
||||
return
|
||||
|
||||
incoming_mails = pop3.get_messages()
|
||||
|
||||
exceptions = []
|
||||
|
|
|
|||
|
|
@ -13,6 +13,14 @@ from frappe.email.doctype.email_account.email_account import notify_unreplied
|
|||
from datetime import datetime, timedelta
|
||||
|
||||
class TestEmailAccount(unittest.TestCase):
|
||||
def setUp(self):
|
||||
email_account = frappe.get_doc("Email Account", "_Test Email Account 1")
|
||||
email_account.db_set("enable_incoming", 1)
|
||||
|
||||
def tearDown(self):
|
||||
email_account = frappe.get_doc("Email Account", "_Test Email Account 1")
|
||||
email_account.db_set("enable_incoming", 0)
|
||||
|
||||
def test_incoming(self):
|
||||
frappe.db.sql("delete from tabCommunication where sender='test_sender@example.com'")
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -47,6 +48,7 @@
|
|||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -70,6 +72,7 @@
|
|||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
|
|
@ -93,6 +96,7 @@
|
|||
"options": "DocType",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
|
|
@ -116,6 +120,7 @@
|
|||
"options": "\nNew\nSave\nSubmit\nCancel\nDays After\nDays Before\nValue Change",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
|
|
@ -140,6 +145,7 @@
|
|||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -165,6 +171,7 @@
|
|||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -189,6 +196,7 @@
|
|||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -213,6 +221,7 @@
|
|||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -234,6 +243,7 @@
|
|||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -256,6 +266,7 @@
|
|||
"options": "<p><strong>Condition Examples:</strong></p>\n<pre>doc.status==\"Open\"\ndoc.due_date==nowdate()\ndoc.total > 40000\n</pre>\n<p><strong>Hints:</strong></p>\n<ol>\n<li>To check for an event every day, select \"Date Change\" in Event</li>\n<li>To send an alert if a particular value changes, select \"Value Change\"</li>\n</ol>",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -278,6 +289,7 @@
|
|||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -301,6 +313,7 @@
|
|||
"options": "Email Alert Recipient",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
|
|
@ -323,6 +336,7 @@
|
|||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -345,6 +359,7 @@
|
|||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
|
|
@ -368,6 +383,7 @@
|
|||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -388,9 +404,10 @@
|
|||
"label": "Message Examples",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "<h5>Message Example</h5>\n\n<pre>\n<h3>Order Overdue</h3>\n\n<p>Transaction {{ doc.name }} has exceeded Due Date. Please take necessary action.</p>\n\n<h4>Details</h4>\n\n<ul>\n<li>Customer: {{ doc.customer }}\n<li>Amount: {{ doc.total_amount }}\n</ul>\n</pre>",
|
||||
"options": "<h5>Message Example</h5>\n\n<pre>\n<h3>Order Overdue</h3>\n\n<p>Transaction {{ doc.name }} has exceeded Due Date. Please take necessary action.</p>\n\n<!-- show last comment -->\n{% if comments %}\nLast comment: {{ comments[-1].comment }} by {{ comments[-1].by }}\n{% endif %}\n\n<h4>Details</h4>\n\n<ul>\n<li>Customer: {{ doc.customer }}\n<li>Amount: {{ doc.total_amount }}\n</ul>\n</pre>",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -414,6 +431,7 @@
|
|||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -425,13 +443,15 @@
|
|||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "icon-envelope",
|
||||
"idx": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2015-11-16 06:29:46.014034",
|
||||
"menu_index": 0,
|
||||
"modified": "2015-11-26 02:14:59.637519",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Email",
|
||||
"name": "Email Alert",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import json
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import validate_email_add, nowdate
|
||||
|
|
@ -95,10 +96,21 @@ def evaluate_alert(doc, alert, event):
|
|||
return
|
||||
|
||||
subject = alert.subject
|
||||
|
||||
if event != "Value Change" and not doc.is_new():
|
||||
# reload the doc for the latest values & comments,
|
||||
# except for validate type event.
|
||||
doc = frappe.get_doc(doc.doctype, doc.name)
|
||||
|
||||
context = {"doc": doc, "alert": alert, "comments": None}
|
||||
|
||||
if doc.get("_comments"):
|
||||
context["comments"] = json.loads(doc.get("_comments"))
|
||||
|
||||
if "{" in subject:
|
||||
subject = frappe.render_template(alert.subject, {"doc": doc, "alert": alert})
|
||||
subject = frappe.render_template(alert.subject, context)
|
||||
|
||||
frappe.sendmail(recipients=recipients, subject=subject,
|
||||
message= frappe.render_template(alert.message, {"doc": doc, "alert":alert}),
|
||||
message= frappe.render_template(alert.message, context),
|
||||
bulk=True, reference_doctype = doc.doctype, reference_name = doc.name,
|
||||
attachments = [frappe.attach_print(doc.doctype, doc.name)] if alert.attach_print else None)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
import time
|
||||
import _socket, poplib
|
||||
import socket, poplib
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import extract_email_id, convert_utc_to_user_timezone, now, cint, cstr, strip
|
||||
|
|
@ -48,7 +48,7 @@ class POP3Server:
|
|||
# connection established!
|
||||
return True
|
||||
|
||||
except _socket.error:
|
||||
except socket.error:
|
||||
# Invalid mail server -- due to refusing connection
|
||||
frappe.msgprint(_('Invalid Mail Server. Please rectify and try again.'))
|
||||
raise
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ app_publisher = "Frappe Technologies Pvt. Ltd."
|
|||
app_description = "Full stack web framework with Python, Javascript, MariaDB, Redis, Node"
|
||||
|
||||
app_icon = "octicon octicon-circuit-board"
|
||||
app_version = "6.10.0"
|
||||
app_version = "6.10.1"
|
||||
app_color = "orange"
|
||||
source_link = "https://github.com/frappe/frappe"
|
||||
app_license = "MIT"
|
||||
|
|
|
|||
|
|
@ -326,10 +326,26 @@ ul.linked-with-list li {
|
|||
border-bottom: 1px solid #d1d8dd;
|
||||
}
|
||||
/* jquery ui */
|
||||
.ui-datepicker .ui-datepicker-header {
|
||||
border-radius: 0px !important;
|
||||
}
|
||||
.ui-datepicker select.ui-datepicker-month,
|
||||
.ui-datepicker select.ui-datepicker-year {
|
||||
display: inline;
|
||||
}
|
||||
.ui-datepicker select.ui-datepicker-month {
|
||||
margin-right: 3px;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-title {
|
||||
line-height: inherit !important;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
.ui-datepicker-today .ui-state-default {
|
||||
background-color: #EBEFF2 !important;
|
||||
}
|
||||
.ui-state-default {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.hidden-xs-inline,
|
||||
.hidden-xs-inline-block {
|
||||
display: none;
|
||||
|
|
|
|||
|
|
@ -523,10 +523,12 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({
|
|||
datepicker_options: {
|
||||
altFormat:'yy-mm-dd',
|
||||
changeYear: true,
|
||||
changeMonth: true,
|
||||
yearRange: "-70Y:+10Y",
|
||||
},
|
||||
make_input: function() {
|
||||
this._super();
|
||||
this.set_t_for_today();
|
||||
this.set_datepicker();
|
||||
},
|
||||
set_datepicker: function() {
|
||||
|
|
@ -534,6 +536,15 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({
|
|||
(frappe.boot.sysdefaults.date_format || 'yyyy-mm-dd').replace("yyyy", "yy")
|
||||
this.$input.datepicker(this.datepicker_options);
|
||||
},
|
||||
set_t_for_today: function() {
|
||||
var me = this;
|
||||
this.$input.on("keydown", function(e) {
|
||||
if(e.which===84) { // 84 === t
|
||||
me.set_value(frappe.datetime.str_to_user(frappe.datetime.nowdate()));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
parse: function(value) {
|
||||
if(value) {
|
||||
value = dateutil.user_to_str(value);
|
||||
|
|
@ -878,7 +889,7 @@ frappe.ui.form.ControlAttachImage = frappe.ui.form.ControlAttach.extend({
|
|||
this.$wrapper.on("refresh", function() {
|
||||
me.set_image();
|
||||
});
|
||||
|
||||
|
||||
this.set_image();
|
||||
},
|
||||
set_image: function() {
|
||||
|
|
|
|||
|
|
@ -134,10 +134,30 @@ ul.linked-with-list li {
|
|||
|
||||
/* jquery ui */
|
||||
|
||||
.ui-datepicker .ui-datepicker-header {
|
||||
border-radius: 0px !important;
|
||||
}
|
||||
|
||||
.ui-datepicker select.ui-datepicker-month, .ui-datepicker select.ui-datepicker-year {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.ui-datepicker select.ui-datepicker-month {
|
||||
margin-right: 3px;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-title {
|
||||
line-height: inherit !important;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.ui-datepicker-today .ui-state-default {
|
||||
background-color: @light-border-color !important;
|
||||
}
|
||||
|
||||
.ui-state-default {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.hidden-xs-inline, .hidden-xs-inline-block {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -371,12 +371,6 @@ $.extend(frappe, {
|
|||
// blur
|
||||
if(!$('#freeze').length) {
|
||||
var freeze = $('<div id="freeze" class="modal-backdrop fade"></div>')
|
||||
.on("click", function() {
|
||||
if (cur_frm && cur_frm.cur_grid) {
|
||||
cur_frm.cur_grid.toggle_view();
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.appendTo("body");
|
||||
|
||||
freeze.html(repl('<div class="freeze-message-container"><div class="freeze-message">%(msg)s</div></div>',
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -1,6 +1,6 @@
|
|||
from setuptools import setup, find_packages
|
||||
|
||||
version = "6.10.0"
|
||||
version = "6.10.1"
|
||||
|
||||
with open("requirements.txt", "r") as f:
|
||||
install_requires = f.readlines()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue