mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
do better with loop cleanup (#3245)
* do better with loop cleanup * changelog * remove redundant line * Do this a bit better than the initial pass * Improve windows support Make some other things coroutines to work with improved design * Wish we'd have done this right from the start... * Update deps surrounding this - see bpo-23057 - neccessary for windows users - nice for consistent support channel info / feature availability * dep issue * Fix tests * duplication plugin py version * actually handle this * Reconfigure some checks with codeclimate, disable pylint for now * style * Is my exasperation showing yet? * handle some stupid stuff * meh * dep changelog
This commit is contained in:
parent
22268eed9d
commit
a80e20067c
396
.bandit.yml
Normal file
396
.bandit.yml
Normal file
@ -0,0 +1,396 @@
|
|||||||
|
|
||||||
|
### Bandit config file generated
|
||||||
|
|
||||||
|
### This config may optionally select a subset of tests to run or skip by
|
||||||
|
### filling out the 'tests' and 'skips' lists given below. If no tests are
|
||||||
|
### specified for inclusion then it is assumed all tests are desired. The skips
|
||||||
|
### set will remove specific tests from the include set. This can be controlled
|
||||||
|
### using the -t/-s CLI options. Note that the same test ID should not appear
|
||||||
|
### in both 'tests' and 'skips', this would be nonsensical and is detected by
|
||||||
|
### Bandit at runtime.
|
||||||
|
|
||||||
|
# Available tests:
|
||||||
|
# B101 : assert_used
|
||||||
|
# B102 : exec_used
|
||||||
|
# B103 : set_bad_file_permissions
|
||||||
|
# B104 : hardcoded_bind_all_interfaces
|
||||||
|
# B105 : hardcoded_password_string
|
||||||
|
# B106 : hardcoded_password_funcarg
|
||||||
|
# B107 : hardcoded_password_default
|
||||||
|
# B108 : hardcoded_tmp_directory
|
||||||
|
# B110 : try_except_pass
|
||||||
|
# B112 : try_except_continue
|
||||||
|
# B201 : flask_debug_true
|
||||||
|
# B301 : pickle
|
||||||
|
# B302 : marshal
|
||||||
|
# B303 : md5
|
||||||
|
# B304 : ciphers
|
||||||
|
# B305 : cipher_modes
|
||||||
|
# B306 : mktemp_q
|
||||||
|
# B307 : eval
|
||||||
|
# B308 : mark_safe
|
||||||
|
# B309 : httpsconnection
|
||||||
|
# B310 : urllib_urlopen
|
||||||
|
# B311 : random
|
||||||
|
# B312 : telnetlib
|
||||||
|
# B313 : xml_bad_cElementTree
|
||||||
|
# B314 : xml_bad_ElementTree
|
||||||
|
# B315 : xml_bad_expatreader
|
||||||
|
# B316 : xml_bad_expatbuilder
|
||||||
|
# B317 : xml_bad_sax
|
||||||
|
# B318 : xml_bad_minidom
|
||||||
|
# B319 : xml_bad_pulldom
|
||||||
|
# B320 : xml_bad_etree
|
||||||
|
# B321 : ftplib
|
||||||
|
# B322 : input
|
||||||
|
# B323 : unverified_context
|
||||||
|
# B324 : hashlib_new_insecure_functions
|
||||||
|
# B325 : tempnam
|
||||||
|
# B401 : import_telnetlib
|
||||||
|
# B402 : import_ftplib
|
||||||
|
# B403 : import_pickle
|
||||||
|
# B404 : import_subprocess
|
||||||
|
# B405 : import_xml_etree
|
||||||
|
# B406 : import_xml_sax
|
||||||
|
# B407 : import_xml_expat
|
||||||
|
# B408 : import_xml_minidom
|
||||||
|
# B409 : import_xml_pulldom
|
||||||
|
# B410 : import_lxml
|
||||||
|
# B411 : import_xmlrpclib
|
||||||
|
# B412 : import_httpoxy
|
||||||
|
# B413 : import_pycrypto
|
||||||
|
# B501 : request_with_no_cert_validation
|
||||||
|
# B502 : ssl_with_bad_version
|
||||||
|
# B503 : ssl_with_bad_defaults
|
||||||
|
# B504 : ssl_with_no_version
|
||||||
|
# B505 : weak_cryptographic_key
|
||||||
|
# B506 : yaml_load
|
||||||
|
# B507 : ssh_no_host_key_verification
|
||||||
|
# B601 : paramiko_calls
|
||||||
|
# B602 : subprocess_popen_with_shell_equals_true
|
||||||
|
# B603 : subprocess_without_shell_equals_true
|
||||||
|
# B604 : any_other_function_with_shell_equals_true
|
||||||
|
# B605 : start_process_with_a_shell
|
||||||
|
# B606 : start_process_with_no_shell
|
||||||
|
# B607 : start_process_with_partial_path
|
||||||
|
# B608 : hardcoded_sql_expressions
|
||||||
|
# B609 : linux_commands_wildcard_injection
|
||||||
|
# B610 : django_extra_used
|
||||||
|
# B611 : django_rawsql_used
|
||||||
|
# B701 : jinja2_autoescape_false
|
||||||
|
# B702 : use_of_mako_templates
|
||||||
|
# B703 : django_mark_safe
|
||||||
|
|
||||||
|
# (optional) list included test IDs here, eg '[B101, B406]':
|
||||||
|
tests:
|
||||||
|
|
||||||
|
# (optional) list skipped test IDs here, eg '[B101, B406]':
|
||||||
|
skips: ['B322']
|
||||||
|
|
||||||
|
### (optional) plugin settings - some test plugins require configuration data
|
||||||
|
### that may be given here, per-plugin. All bandit test plugins have a built in
|
||||||
|
### set of sensible defaults and these will be used if no configuration is
|
||||||
|
### provided. It is not necessary to provide settings for every (or any) plugin
|
||||||
|
### if the defaults are acceptable.
|
||||||
|
|
||||||
|
any_other_function_with_shell_equals_true:
|
||||||
|
no_shell:
|
||||||
|
- os.execl
|
||||||
|
- os.execle
|
||||||
|
- os.execlp
|
||||||
|
- os.execlpe
|
||||||
|
- os.execv
|
||||||
|
- os.execve
|
||||||
|
- os.execvp
|
||||||
|
- os.execvpe
|
||||||
|
- os.spawnl
|
||||||
|
- os.spawnle
|
||||||
|
- os.spawnlp
|
||||||
|
- os.spawnlpe
|
||||||
|
- os.spawnv
|
||||||
|
- os.spawnve
|
||||||
|
- os.spawnvp
|
||||||
|
- os.spawnvpe
|
||||||
|
- os.startfile
|
||||||
|
shell:
|
||||||
|
- os.system
|
||||||
|
- os.popen
|
||||||
|
- os.popen2
|
||||||
|
- os.popen3
|
||||||
|
- os.popen4
|
||||||
|
- popen2.popen2
|
||||||
|
- popen2.popen3
|
||||||
|
- popen2.popen4
|
||||||
|
- popen2.Popen3
|
||||||
|
- popen2.Popen4
|
||||||
|
- commands.getoutput
|
||||||
|
- commands.getstatusoutput
|
||||||
|
subprocess:
|
||||||
|
- subprocess.Popen
|
||||||
|
- subprocess.call
|
||||||
|
- subprocess.check_call
|
||||||
|
- subprocess.check_output
|
||||||
|
- subprocess.run
|
||||||
|
hardcoded_tmp_directory:
|
||||||
|
tmp_dirs:
|
||||||
|
- /tmp
|
||||||
|
- /var/tmp
|
||||||
|
- /dev/shm
|
||||||
|
linux_commands_wildcard_injection:
|
||||||
|
no_shell:
|
||||||
|
- os.execl
|
||||||
|
- os.execle
|
||||||
|
- os.execlp
|
||||||
|
- os.execlpe
|
||||||
|
- os.execv
|
||||||
|
- os.execve
|
||||||
|
- os.execvp
|
||||||
|
- os.execvpe
|
||||||
|
- os.spawnl
|
||||||
|
- os.spawnle
|
||||||
|
- os.spawnlp
|
||||||
|
- os.spawnlpe
|
||||||
|
- os.spawnv
|
||||||
|
- os.spawnve
|
||||||
|
- os.spawnvp
|
||||||
|
- os.spawnvpe
|
||||||
|
- os.startfile
|
||||||
|
shell:
|
||||||
|
- os.system
|
||||||
|
- os.popen
|
||||||
|
- os.popen2
|
||||||
|
- os.popen3
|
||||||
|
- os.popen4
|
||||||
|
- popen2.popen2
|
||||||
|
- popen2.popen3
|
||||||
|
- popen2.popen4
|
||||||
|
- popen2.Popen3
|
||||||
|
- popen2.Popen4
|
||||||
|
- commands.getoutput
|
||||||
|
- commands.getstatusoutput
|
||||||
|
subprocess:
|
||||||
|
- subprocess.Popen
|
||||||
|
- subprocess.call
|
||||||
|
- subprocess.check_call
|
||||||
|
- subprocess.check_output
|
||||||
|
- subprocess.run
|
||||||
|
ssl_with_bad_defaults:
|
||||||
|
bad_protocol_versions:
|
||||||
|
- PROTOCOL_SSLv2
|
||||||
|
- SSLv2_METHOD
|
||||||
|
- SSLv23_METHOD
|
||||||
|
- PROTOCOL_SSLv3
|
||||||
|
- PROTOCOL_TLSv1
|
||||||
|
- SSLv3_METHOD
|
||||||
|
- TLSv1_METHOD
|
||||||
|
ssl_with_bad_version:
|
||||||
|
bad_protocol_versions:
|
||||||
|
- PROTOCOL_SSLv2
|
||||||
|
- SSLv2_METHOD
|
||||||
|
- SSLv23_METHOD
|
||||||
|
- PROTOCOL_SSLv3
|
||||||
|
- PROTOCOL_TLSv1
|
||||||
|
- SSLv3_METHOD
|
||||||
|
- TLSv1_METHOD
|
||||||
|
start_process_with_a_shell:
|
||||||
|
no_shell:
|
||||||
|
- os.execl
|
||||||
|
- os.execle
|
||||||
|
- os.execlp
|
||||||
|
- os.execlpe
|
||||||
|
- os.execv
|
||||||
|
- os.execve
|
||||||
|
- os.execvp
|
||||||
|
- os.execvpe
|
||||||
|
- os.spawnl
|
||||||
|
- os.spawnle
|
||||||
|
- os.spawnlp
|
||||||
|
- os.spawnlpe
|
||||||
|
- os.spawnv
|
||||||
|
- os.spawnve
|
||||||
|
- os.spawnvp
|
||||||
|
- os.spawnvpe
|
||||||
|
- os.startfile
|
||||||
|
shell:
|
||||||
|
- os.system
|
||||||
|
- os.popen
|
||||||
|
- os.popen2
|
||||||
|
- os.popen3
|
||||||
|
- os.popen4
|
||||||
|
- popen2.popen2
|
||||||
|
- popen2.popen3
|
||||||
|
- popen2.popen4
|
||||||
|
- popen2.Popen3
|
||||||
|
- popen2.Popen4
|
||||||
|
- commands.getoutput
|
||||||
|
- commands.getstatusoutput
|
||||||
|
subprocess:
|
||||||
|
- subprocess.Popen
|
||||||
|
- subprocess.call
|
||||||
|
- subprocess.check_call
|
||||||
|
- subprocess.check_output
|
||||||
|
- subprocess.run
|
||||||
|
start_process_with_no_shell:
|
||||||
|
no_shell:
|
||||||
|
- os.execl
|
||||||
|
- os.execle
|
||||||
|
- os.execlp
|
||||||
|
- os.execlpe
|
||||||
|
- os.execv
|
||||||
|
- os.execve
|
||||||
|
- os.execvp
|
||||||
|
- os.execvpe
|
||||||
|
- os.spawnl
|
||||||
|
- os.spawnle
|
||||||
|
- os.spawnlp
|
||||||
|
- os.spawnlpe
|
||||||
|
- os.spawnv
|
||||||
|
- os.spawnve
|
||||||
|
- os.spawnvp
|
||||||
|
- os.spawnvpe
|
||||||
|
- os.startfile
|
||||||
|
shell:
|
||||||
|
- os.system
|
||||||
|
- os.popen
|
||||||
|
- os.popen2
|
||||||
|
- os.popen3
|
||||||
|
- os.popen4
|
||||||
|
- popen2.popen2
|
||||||
|
- popen2.popen3
|
||||||
|
- popen2.popen4
|
||||||
|
- popen2.Popen3
|
||||||
|
- popen2.Popen4
|
||||||
|
- commands.getoutput
|
||||||
|
- commands.getstatusoutput
|
||||||
|
subprocess:
|
||||||
|
- subprocess.Popen
|
||||||
|
- subprocess.call
|
||||||
|
- subprocess.check_call
|
||||||
|
- subprocess.check_output
|
||||||
|
- subprocess.run
|
||||||
|
start_process_with_partial_path:
|
||||||
|
no_shell:
|
||||||
|
- os.execl
|
||||||
|
- os.execle
|
||||||
|
- os.execlp
|
||||||
|
- os.execlpe
|
||||||
|
- os.execv
|
||||||
|
- os.execve
|
||||||
|
- os.execvp
|
||||||
|
- os.execvpe
|
||||||
|
- os.spawnl
|
||||||
|
- os.spawnle
|
||||||
|
- os.spawnlp
|
||||||
|
- os.spawnlpe
|
||||||
|
- os.spawnv
|
||||||
|
- os.spawnve
|
||||||
|
- os.spawnvp
|
||||||
|
- os.spawnvpe
|
||||||
|
- os.startfile
|
||||||
|
shell:
|
||||||
|
- os.system
|
||||||
|
- os.popen
|
||||||
|
- os.popen2
|
||||||
|
- os.popen3
|
||||||
|
- os.popen4
|
||||||
|
- popen2.popen2
|
||||||
|
- popen2.popen3
|
||||||
|
- popen2.popen4
|
||||||
|
- popen2.Popen3
|
||||||
|
- popen2.Popen4
|
||||||
|
- commands.getoutput
|
||||||
|
- commands.getstatusoutput
|
||||||
|
subprocess:
|
||||||
|
- subprocess.Popen
|
||||||
|
- subprocess.call
|
||||||
|
- subprocess.check_call
|
||||||
|
- subprocess.check_output
|
||||||
|
- subprocess.run
|
||||||
|
subprocess_popen_with_shell_equals_true:
|
||||||
|
no_shell:
|
||||||
|
- os.execl
|
||||||
|
- os.execle
|
||||||
|
- os.execlp
|
||||||
|
- os.execlpe
|
||||||
|
- os.execv
|
||||||
|
- os.execve
|
||||||
|
- os.execvp
|
||||||
|
- os.execvpe
|
||||||
|
- os.spawnl
|
||||||
|
- os.spawnle
|
||||||
|
- os.spawnlp
|
||||||
|
- os.spawnlpe
|
||||||
|
- os.spawnv
|
||||||
|
- os.spawnve
|
||||||
|
- os.spawnvp
|
||||||
|
- os.spawnvpe
|
||||||
|
- os.startfile
|
||||||
|
shell:
|
||||||
|
- os.system
|
||||||
|
- os.popen
|
||||||
|
- os.popen2
|
||||||
|
- os.popen3
|
||||||
|
- os.popen4
|
||||||
|
- popen2.popen2
|
||||||
|
- popen2.popen3
|
||||||
|
- popen2.popen4
|
||||||
|
- popen2.Popen3
|
||||||
|
- popen2.Popen4
|
||||||
|
- commands.getoutput
|
||||||
|
- commands.getstatusoutput
|
||||||
|
subprocess:
|
||||||
|
- subprocess.Popen
|
||||||
|
- subprocess.call
|
||||||
|
- subprocess.check_call
|
||||||
|
- subprocess.check_output
|
||||||
|
- subprocess.run
|
||||||
|
subprocess_without_shell_equals_true:
|
||||||
|
no_shell:
|
||||||
|
- os.execl
|
||||||
|
- os.execle
|
||||||
|
- os.execlp
|
||||||
|
- os.execlpe
|
||||||
|
- os.execv
|
||||||
|
- os.execve
|
||||||
|
- os.execvp
|
||||||
|
- os.execvpe
|
||||||
|
- os.spawnl
|
||||||
|
- os.spawnle
|
||||||
|
- os.spawnlp
|
||||||
|
- os.spawnlpe
|
||||||
|
- os.spawnv
|
||||||
|
- os.spawnve
|
||||||
|
- os.spawnvp
|
||||||
|
- os.spawnvpe
|
||||||
|
- os.startfile
|
||||||
|
shell:
|
||||||
|
- os.system
|
||||||
|
- os.popen
|
||||||
|
- os.popen2
|
||||||
|
- os.popen3
|
||||||
|
- os.popen4
|
||||||
|
- popen2.popen2
|
||||||
|
- popen2.popen3
|
||||||
|
- popen2.popen4
|
||||||
|
- popen2.Popen3
|
||||||
|
- popen2.Popen4
|
||||||
|
- commands.getoutput
|
||||||
|
- commands.getstatusoutput
|
||||||
|
subprocess:
|
||||||
|
- subprocess.Popen
|
||||||
|
- subprocess.call
|
||||||
|
- subprocess.check_call
|
||||||
|
- subprocess.check_output
|
||||||
|
- subprocess.run
|
||||||
|
try_except_continue:
|
||||||
|
check_typed_exception: false
|
||||||
|
try_except_pass:
|
||||||
|
check_typed_exception: false
|
||||||
|
weak_cryptographic_key:
|
||||||
|
weak_key_size_dsa_high: 1024
|
||||||
|
weak_key_size_dsa_medium: 2048
|
||||||
|
weak_key_size_ec_high: 160
|
||||||
|
weak_key_size_ec_medium: 224
|
||||||
|
weak_key_size_rsa_high: 1024
|
||||||
|
weak_key_size_rsa_medium: 2048
|
||||||
|
|
||||||
@ -2,14 +2,15 @@ version: "2" # required to adjust maintainability checks
|
|||||||
checks:
|
checks:
|
||||||
argument-count:
|
argument-count:
|
||||||
config:
|
config:
|
||||||
threshold: 6
|
threshold: 8 # work on this later
|
||||||
complex-logic:
|
complex-logic:
|
||||||
enabled: false # Disabled in favor of using Radon for this
|
enabled: false # Disabled in favor of using Radon for this
|
||||||
config:
|
config:
|
||||||
threshold: 4
|
threshold: 4
|
||||||
file-lines:
|
file-lines:
|
||||||
|
enabled: false # enable after audio stuff...
|
||||||
config:
|
config:
|
||||||
threshold: 1000 # I would set this lower if not for cogs as command containers.
|
threshold: 2000 # I would set this lower if not for cogs as command containers.
|
||||||
method-complexity:
|
method-complexity:
|
||||||
enabled: false # Disabled in favor of using Radon for this
|
enabled: false # Disabled in favor of using Radon for this
|
||||||
config:
|
config:
|
||||||
@ -24,7 +25,7 @@ checks:
|
|||||||
threshold: 25 # I'm fine with long methods, cautious about the complexity of a single method.
|
threshold: 25 # I'm fine with long methods, cautious about the complexity of a single method.
|
||||||
nested-control-flow:
|
nested-control-flow:
|
||||||
config:
|
config:
|
||||||
threshold: 4
|
threshold: 6
|
||||||
return-statements:
|
return-statements:
|
||||||
config:
|
config:
|
||||||
threshold: 6
|
threshold: 6
|
||||||
@ -33,12 +34,19 @@ checks:
|
|||||||
config:
|
config:
|
||||||
threshold: # language-specific defaults. an override will affect all languages.
|
threshold: # language-specific defaults. an override will affect all languages.
|
||||||
identical-code:
|
identical-code:
|
||||||
|
enabled: false
|
||||||
config:
|
config:
|
||||||
threshold: # language-specific defaults. an override will affect all languages.
|
threshold: # language-specific defaults. an override will affect all languages.
|
||||||
plugins:
|
plugins:
|
||||||
bandit:
|
bandit:
|
||||||
enabled: true
|
enabled: false
|
||||||
radon:
|
radon:
|
||||||
enabled: true
|
enabled: false
|
||||||
config:
|
config:
|
||||||
threshold: "D"
|
threshold: "D"
|
||||||
|
duplication:
|
||||||
|
enabled: false
|
||||||
|
config:
|
||||||
|
languages:
|
||||||
|
python:
|
||||||
|
python_version: 3
|
||||||
|
|||||||
@ -5,7 +5,7 @@ notifications:
|
|||||||
email: false
|
email: false
|
||||||
|
|
||||||
python:
|
python:
|
||||||
- 3.7.3
|
- 3.8.1
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- PIPENV_IGNORE_VIRTUALENVS=1
|
- PIPENV_IGNORE_VIRTUALENVS=1
|
||||||
@ -30,7 +30,7 @@ jobs:
|
|||||||
# These jobs only occur on tag creation if the prior ones succeed
|
# These jobs only occur on tag creation if the prior ones succeed
|
||||||
- stage: PyPi Deployment
|
- stage: PyPi Deployment
|
||||||
if: tag IS present
|
if: tag IS present
|
||||||
python: 3.7.2
|
python: 3.8.1
|
||||||
env:
|
env:
|
||||||
- DEPLOYING=true
|
- DEPLOYING=true
|
||||||
- TOXENV=py36
|
- TOXENV=py36
|
||||||
@ -46,7 +46,7 @@ jobs:
|
|||||||
tags: true
|
tags: true
|
||||||
- stage: Crowdin Deployment
|
- stage: Crowdin Deployment
|
||||||
if: tag IS present
|
if: tag IS present
|
||||||
python: 3.7.2
|
python: 3.8.1
|
||||||
env:
|
env:
|
||||||
- DEPLOYING=true
|
- DEPLOYING=true
|
||||||
- TOXENV=py36
|
- TOXENV=py36
|
||||||
|
|||||||
2
Makefile
2
Makefile
@ -1,4 +1,4 @@
|
|||||||
PYTHON ?= python3.7
|
PYTHON ?= python3.8
|
||||||
|
|
||||||
# Python Code Style
|
# Python Code Style
|
||||||
reformat:
|
reformat:
|
||||||
|
|||||||
4
changelog.d/3245.dep.rst
Normal file
4
changelog.d/3245.dep.rst
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
Update python minimum requirement to 3.8.1
|
||||||
|
|
||||||
|
Update JRE to Java 11
|
||||||
|
|
||||||
1
changelog.d/3245.misc.rst
Normal file
1
changelog.d/3245.misc.rst
Normal file
@ -0,0 +1 @@
|
|||||||
|
Do a little better with loop cleanup
|
||||||
@ -17,10 +17,10 @@ Installing the pre-requirements
|
|||||||
Please install the pre-requirements using the commands listed for your operating system.
|
Please install the pre-requirements using the commands listed for your operating system.
|
||||||
|
|
||||||
The pre-requirements are:
|
The pre-requirements are:
|
||||||
- Python 3.7.0 or greater
|
- Python 3.8.1 or greater
|
||||||
- Pip 9.0 or greater
|
- Pip 18.1 or greater
|
||||||
- Git
|
- Git
|
||||||
- Java Runtime Environment 8 or later (for audio support)
|
- Java Runtime Environment 11 or later (for audio support)
|
||||||
|
|
||||||
We also recommend installing some basic compiler tools, in case our dependencies don't provide
|
We also recommend installing some basic compiler tools, in case our dependencies don't provide
|
||||||
pre-built "wheels" for your architecture.
|
pre-built "wheels" for your architecture.
|
||||||
@ -47,7 +47,7 @@ CentOS and RHEL 7
|
|||||||
yum -y groupinstall development
|
yum -y groupinstall development
|
||||||
yum -y install https://centos7.iuscommunity.org/ius-release.rpm
|
yum -y install https://centos7.iuscommunity.org/ius-release.rpm
|
||||||
sudo yum install zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel \
|
sudo yum install zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel \
|
||||||
openssl-devel xz xz-devel libffi-devel findutils git2u java-1.8.0-openjdk
|
openssl-devel xz xz-devel libffi-devel findutils git2u java-11-openjdk
|
||||||
|
|
||||||
Complete the rest of the installation by `installing Python 3.7 with pyenv <install-python-pyenv>`.
|
Complete the rest of the installation by `installing Python 3.7 with pyenv <install-python-pyenv>`.
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ them with apt:
|
|||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install python3 python3-dev python3-venv python3-pip git default-jre-headless \
|
sudo apt install python3 python3-dev python3-venv python3-pip git openjdk-11-jre \
|
||||||
build-essential
|
build-essential
|
||||||
|
|
||||||
Debian and Raspbian Stretch
|
Debian and Raspbian Stretch
|
||||||
@ -81,9 +81,9 @@ Debian/Raspbian Stretch. This guide will tell you how. First, run the following
|
|||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev \
|
sudo apt install build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev \
|
||||||
libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev \
|
libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev \
|
||||||
liblzma-dev python3-openssl git default-jre-headless
|
liblzma-dev python3-openssl git openjdk-11-jre
|
||||||
|
|
||||||
Complete the rest of the installation by `installing Python 3.7 with pyenv <install-python-pyenv>`.
|
Complete the rest of the installation by `installing Python 3.8 with pyenv <install-python-pyenv>`.
|
||||||
|
|
||||||
.. _install-fedora:
|
.. _install-fedora:
|
||||||
|
|
||||||
@ -119,10 +119,10 @@ one-by-one:
|
|||||||
brew install python --with-brewed-openssl
|
brew install python --with-brewed-openssl
|
||||||
brew install git
|
brew install git
|
||||||
brew tap caskroom/versions
|
brew tap caskroom/versions
|
||||||
brew cask install homebrew/cask-versions/adoptopenjdk8
|
brew cask install homebrew/cask-versions/adoptopenjdk11
|
||||||
|
|
||||||
It's possible you will have network issues. If so, go in your Applications folder, inside it, go in
|
It's possible you will have network issues. If so, go in your Applications folder, inside it, go in
|
||||||
the Python 3.7 folder then double click ``Install certificates.command``.
|
the Python 3.8 folder then double click ``Install certificates.command``.
|
||||||
|
|
||||||
.. _install-opensuse:
|
.. _install-opensuse:
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ openSUSE
|
|||||||
openSUSE Leap
|
openSUSE Leap
|
||||||
*************
|
*************
|
||||||
|
|
||||||
We recommend installing a community package to get Python 3.7 on openSUSE Leap. This package will
|
We recommend installing a community package to get Python 3.8 on openSUSE Leap. This package will
|
||||||
be installed to the ``/opt`` directory.
|
be installed to the ``/opt`` directory.
|
||||||
|
|
||||||
First, add the Opt-Python community repository:
|
First, add the Opt-Python community repository:
|
||||||
@ -147,7 +147,7 @@ Now install the pre-requirements with zypper:
|
|||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
sudo zypper install opt-python37 opt-python37-setuptools git-core java-11-openjdk-headless
|
sudo zypper install opt-python38 opt-python38-setuptools git-core java-11-openjdk-headless
|
||||||
sudo zypper install -t pattern devel_basis
|
sudo zypper install -t pattern devel_basis
|
||||||
|
|
||||||
Since Python is now installed to ``/opt/python``, we should add it to PATH. You can add a file in
|
Since Python is now installed to ``/opt/python``, we should add it to PATH. You can add a file in
|
||||||
@ -162,7 +162,7 @@ Now, install pip with easy_install:
|
|||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
sudo /opt/python/bin/easy_install-3.7 pip
|
sudo /opt/python/bin/easy_install-3.8 pip
|
||||||
|
|
||||||
openSUSE Tumbleweed
|
openSUSE Tumbleweed
|
||||||
*******************
|
*******************
|
||||||
@ -181,10 +181,9 @@ with zypper:
|
|||||||
Ubuntu
|
Ubuntu
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
||||||
.. note:: **Ubuntu 16.04 Users**
|
.. note:: **Ubuntu Python Availability**
|
||||||
|
|
||||||
You must add a 3rd-party repository to install Python 3.7 on Ubuntu 16.04 with apt. We
|
We recommend using the deadsnakes ppa to ensure up to date python availability.
|
||||||
recommend the ``deadsnakes`` repository:
|
|
||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
@ -196,7 +195,7 @@ Install the pre-requirements with apt:
|
|||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install python3.7 python3.7-dev python3.7-venv python3-pip git default-jre-headless \
|
sudo apt install python3.8 python3.8-dev python3.8-venv python3-pip git default-jre-headless \
|
||||||
build-essential
|
build-essential
|
||||||
|
|
||||||
.. _install-python-pyenv:
|
.. _install-python-pyenv:
|
||||||
@ -210,7 +209,7 @@ Installing Python with pyenv
|
|||||||
If you followed one of the sections above, and weren't linked here afterwards, you should skip
|
If you followed one of the sections above, and weren't linked here afterwards, you should skip
|
||||||
this section.
|
this section.
|
||||||
|
|
||||||
On distributions where Python 3.7 needs to be compiled from source, we recommend the use of pyenv.
|
On distributions where Python 3.8 needs to be compiled from source, we recommend the use of pyenv.
|
||||||
This simplifies the compilation process and has the added bonus of simplifying setting up Red in a
|
This simplifies the compilation process and has the added bonus of simplifying setting up Red in a
|
||||||
virtual environment.
|
virtual environment.
|
||||||
|
|
||||||
@ -225,7 +224,7 @@ Then run the following command:
|
|||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
CONFIGURE_OPTS=--enable-optimizations pyenv install 3.7.4 -v
|
CONFIGURE_OPTS=--enable-optimizations pyenv install 3.8.1 -v
|
||||||
|
|
||||||
This may take a long time to complete, depending on your hardware. For some machines (such as
|
This may take a long time to complete, depending on your hardware. For some machines (such as
|
||||||
Raspberry Pis and micro-tier VPSes), it may take over an hour; in this case, you may wish to remove
|
Raspberry Pis and micro-tier VPSes), it may take over an hour; in this case, you may wish to remove
|
||||||
@ -237,9 +236,9 @@ After that is finished, run:
|
|||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
pyenv global 3.7.4
|
pyenv global 3.8.1
|
||||||
|
|
||||||
Pyenv is now installed and your system should be configured to run Python 3.7.
|
Pyenv is now installed and your system should be configured to run Python 3.8.
|
||||||
|
|
||||||
------------------------------
|
------------------------------
|
||||||
Creating a Virtual Environment
|
Creating a Virtual Environment
|
||||||
@ -259,23 +258,23 @@ Choose one of the following commands to install Red.
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
If you're not inside an activated virtual environment, include the ``--user`` flag with all
|
If you're not inside an activated virtual environment, include the ``--user`` flag with all
|
||||||
``python3.7 -m pip install`` commands, like this:
|
``python3.8 -m pip install`` commands, like this:
|
||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
python3.7 -m pip install --user -U Red-DiscordBot
|
python3.8 -m pip install --user -U Red-DiscordBot
|
||||||
|
|
||||||
To install without additional config backend support:
|
To install without additional config backend support:
|
||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
python3.7 -m pip install -U Red-DiscordBot
|
python3.8 -m pip install -U Red-DiscordBot
|
||||||
|
|
||||||
Or, to install with PostgreSQL support:
|
Or, to install with PostgreSQL support:
|
||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
python3.7 -m pip install -U Red-DiscordBot[postgres]
|
python3.8 -m pip install -U Red-DiscordBot[postgres]
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ Then run each of the following commands:
|
|||||||
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
|
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
|
||||||
choco install git --params "/GitOnlyOnPath /WindowsTerminal" -y
|
choco install git --params "/GitOnlyOnPath /WindowsTerminal" -y
|
||||||
choco install visualstudio2019-workload-vctools -y
|
choco install visualstudio2019-workload-vctools -y
|
||||||
choco install python3 --version=3.7.5 -y
|
choco install python3 --version=3.8.1 -y
|
||||||
|
|
||||||
For Audio support, you should also run the following command before exiting:
|
For Audio support, you should also run the following command before exiting:
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ Manually installing dependencies
|
|||||||
|
|
||||||
* `MSVC Build tools <https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2019>`_
|
* `MSVC Build tools <https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2019>`_
|
||||||
|
|
||||||
* `Python <https://www.python.org/downloads/>`_ - Red needs Python 3.7.2 or greater
|
* `Python <https://www.python.org/downloads/>`_ - Red needs Python 3.8.1 or greater
|
||||||
|
|
||||||
.. attention:: Please make sure that the box to add Python to PATH is CHECKED, otherwise
|
.. attention:: Please make sure that the box to add Python to PATH is CHECKED, otherwise
|
||||||
you may run into issues when trying to run Red.
|
you may run into issues when trying to run Red.
|
||||||
@ -77,12 +77,12 @@ Installing Red
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
If you're not inside an activated virtual environment, use ``py -3.7`` in place of
|
If you're not inside an activated virtual environment, use ``py -3.8`` in place of
|
||||||
``python``, and include the ``--user`` flag with all ``pip install`` commands, like this:
|
``python``, and include the ``--user`` flag with all ``pip install`` commands, like this:
|
||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
py -3.7 -m pip install --user -U Red-DiscordBot
|
py -3.8 -m pip install --user -U Red-DiscordBot
|
||||||
|
|
||||||
* Normal installation:
|
* Normal installation:
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ Installing Red
|
|||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
python3.7 -m pip install -U Red-DiscordBot[postgres]
|
python3.8 -m pip install -U Red-DiscordBot[postgres]
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|||||||
2
make.bat
2
make.bat
@ -22,7 +22,7 @@ black -l 99 --check --target-version py37 !PYFILES!
|
|||||||
exit /B %ERRORLEVEL%
|
exit /B %ERRORLEVEL%
|
||||||
|
|
||||||
:newenv
|
:newenv
|
||||||
py -3.7 -m venv --clear .venv
|
py -3.8 -m venv --clear .venv
|
||||||
.\.venv\Scripts\python -m pip install -U pip setuptools
|
.\.venv\Scripts\python -m pip install -U pip setuptools
|
||||||
goto syncenv
|
goto syncenv
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ from typing import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
MIN_PYTHON_VERSION = (3, 7, 0)
|
MIN_PYTHON_VERSION = (3, 8, 1)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"MIN_PYTHON_VERSION",
|
"MIN_PYTHON_VERSION",
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
# Discord Version check
|
# Discord Version check
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import functools
|
||||||
import getpass
|
import getpass
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
@ -10,7 +11,9 @@ import os
|
|||||||
import pip
|
import pip
|
||||||
import platform
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
|
import signal
|
||||||
import sys
|
import sys
|
||||||
|
from argparse import Namespace
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@ -24,17 +27,11 @@ from redbot import _update_event_loop_policy, __version__
|
|||||||
_update_event_loop_policy()
|
_update_event_loop_policy()
|
||||||
|
|
||||||
import redbot.logging
|
import redbot.logging
|
||||||
from redbot.core.bot import Red, ExitCodes
|
from redbot.core.bot import Red
|
||||||
from redbot.core.cog_manager import CogManagerUI
|
|
||||||
from redbot.core.global_checks import init_global_checks
|
|
||||||
from redbot.core.events import init_events
|
|
||||||
from redbot.core.cli import interactive_config, confirm, parse_cli_flags
|
from redbot.core.cli import interactive_config, confirm, parse_cli_flags
|
||||||
from redbot.core.core_commands import Core, license_info_command
|
|
||||||
from redbot.setup import get_data_dir, get_name, save_config
|
from redbot.setup import get_data_dir, get_name, save_config
|
||||||
from redbot.core.dev_commands import Dev
|
from redbot.core import data_manager, drivers
|
||||||
from redbot.core import __version__, modlog, bank, data_manager, drivers
|
|
||||||
from redbot.core._sharedlibdeprecation import SharedLibImportWarner
|
from redbot.core._sharedlibdeprecation import SharedLibImportWarner
|
||||||
from signal import SIGTERM
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger("red.main")
|
log = logging.getLogger("red.main")
|
||||||
@ -46,16 +43,6 @@ log = logging.getLogger("red.main")
|
|||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
async def _get_prefix_and_token(red, indict):
|
|
||||||
"""
|
|
||||||
Again, please blame <@269933075037814786> for this.
|
|
||||||
:param indict:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
indict["token"] = await red._config.token()
|
|
||||||
indict["prefix"] = await red._config.prefix()
|
|
||||||
|
|
||||||
|
|
||||||
def _get_instance_names():
|
def _get_instance_names():
|
||||||
with data_manager.config_file.open(encoding="utf-8") as fs:
|
with data_manager.config_file.open(encoding="utf-8") as fs:
|
||||||
data = json.load(fs)
|
data = json.load(fs)
|
||||||
@ -115,7 +102,7 @@ def debug_info():
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
def edit_instance(red, cli_flags):
|
async def edit_instance(red, cli_flags):
|
||||||
no_prompt = cli_flags.no_prompt
|
no_prompt = cli_flags.no_prompt
|
||||||
token = cli_flags.token
|
token = cli_flags.token
|
||||||
owner = cli_flags.owner
|
owner = cli_flags.owner
|
||||||
@ -138,8 +125,8 @@ def edit_instance(red, cli_flags):
|
|||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
_edit_token(red, token, no_prompt)
|
await _edit_token(red, token, no_prompt)
|
||||||
_edit_owner(red, owner, no_prompt)
|
await _edit_owner(red, owner, no_prompt)
|
||||||
|
|
||||||
data = deepcopy(data_manager.basic_config)
|
data = deepcopy(data_manager.basic_config)
|
||||||
name = _edit_instance_name(old_name, new_name, confirm_overwrite, no_prompt)
|
name = _edit_instance_name(old_name, new_name, confirm_overwrite, no_prompt)
|
||||||
@ -150,7 +137,7 @@ def edit_instance(red, cli_flags):
|
|||||||
save_config(old_name, {}, remove=True)
|
save_config(old_name, {}, remove=True)
|
||||||
|
|
||||||
|
|
||||||
def _edit_token(red, token, no_prompt):
|
async def _edit_token(red, token, no_prompt):
|
||||||
if token:
|
if token:
|
||||||
if not len(token) >= 50:
|
if not len(token) >= 50:
|
||||||
print(
|
print(
|
||||||
@ -158,13 +145,13 @@ def _edit_token(red, token, no_prompt):
|
|||||||
" Instance's token will remain unchanged.\n"
|
" Instance's token will remain unchanged.\n"
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
red.loop.run_until_complete(red._config.token.set(token))
|
await red._config.token.set(token)
|
||||||
elif not no_prompt and confirm("Would you like to change instance's token?", default=False):
|
elif not no_prompt and confirm("Would you like to change instance's token?", default=False):
|
||||||
interactive_config(red, False, True, print_header=False)
|
await interactive_config(red, False, True, print_header=False)
|
||||||
print("Token updated.\n")
|
print("Token updated.\n")
|
||||||
|
|
||||||
|
|
||||||
def _edit_owner(red, owner, no_prompt):
|
async def _edit_owner(red, owner, no_prompt):
|
||||||
if owner:
|
if owner:
|
||||||
if not (15 <= len(str(owner)) <= 21):
|
if not (15 <= len(str(owner)) <= 21):
|
||||||
print(
|
print(
|
||||||
@ -172,7 +159,7 @@ def _edit_owner(red, owner, no_prompt):
|
|||||||
" Instance's owner will remain unchanged."
|
" Instance's owner will remain unchanged."
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
red.loop.run_until_complete(red._config.owner.set(owner))
|
await red._config.owner.set(owner)
|
||||||
elif not no_prompt and confirm("Would you like to change instance's owner?", default=False):
|
elif not no_prompt and confirm("Would you like to change instance's owner?", default=False):
|
||||||
print(
|
print(
|
||||||
"Remember:\n"
|
"Remember:\n"
|
||||||
@ -188,7 +175,7 @@ def _edit_owner(red, owner, no_prompt):
|
|||||||
print("That doesn't look like a valid Discord user id.")
|
print("That doesn't look like a valid Discord user id.")
|
||||||
continue
|
continue
|
||||||
owner_id = int(owner_id)
|
owner_id = int(owner_id)
|
||||||
red.loop.run_until_complete(red._config.owner.set(owner_id))
|
await red._config.owner.set(owner_id)
|
||||||
print("Owner updated.")
|
print("Owner updated.")
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
@ -259,14 +246,72 @@ def _copy_data(data):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def sigterm_handler(red, log):
|
async def run_bot(red: Red, cli_flags: Namespace):
|
||||||
log.info("SIGTERM received. Quitting...")
|
|
||||||
await red.shutdown(restart=False)
|
driver_cls = drivers.get_driver_class()
|
||||||
|
|
||||||
|
await driver_cls.initialize(**data_manager.storage_details())
|
||||||
|
|
||||||
|
redbot.logging.init_logging(
|
||||||
|
level=cli_flags.logging_level, location=data_manager.core_data_path() / "logs"
|
||||||
|
)
|
||||||
|
|
||||||
|
log.debug("====Basic Config====")
|
||||||
|
log.debug("Data Path: %s", data_manager._base_data_path())
|
||||||
|
log.debug("Storage Type: %s", data_manager.storage_type())
|
||||||
|
|
||||||
|
if cli_flags.edit:
|
||||||
|
try:
|
||||||
|
edit_instance(red, cli_flags)
|
||||||
|
except (KeyboardInterrupt, EOFError):
|
||||||
|
print("Aborted!")
|
||||||
|
finally:
|
||||||
|
await driver_cls.teardown()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
# lib folder has to be in sys.path before trying to load any 3rd-party cog (GH-3061)
|
||||||
|
# We might want to change handling of requirements in Downloader at later date
|
||||||
|
LIB_PATH = data_manager.cog_data_path(raw_name="Downloader") / "lib"
|
||||||
|
LIB_PATH.mkdir(parents=True, exist_ok=True)
|
||||||
|
if str(LIB_PATH) not in sys.path:
|
||||||
|
sys.path.append(str(LIB_PATH))
|
||||||
|
sys.meta_path.insert(0, SharedLibImportWarner())
|
||||||
|
|
||||||
|
if cli_flags.token:
|
||||||
|
token = cli_flags.token
|
||||||
|
else:
|
||||||
|
token = os.environ.get("RED_TOKEN", None)
|
||||||
|
if not token:
|
||||||
|
token = await red._config.token()
|
||||||
|
|
||||||
|
prefix = cli_flags.prefix or await red._config.prefix()
|
||||||
|
|
||||||
|
if not (token and prefix):
|
||||||
|
if cli_flags.no_prompt is False:
|
||||||
|
new_token = await interactive_config(
|
||||||
|
red, token_set=bool(token), prefix_set=bool(prefix)
|
||||||
|
)
|
||||||
|
if new_token:
|
||||||
|
token = new_token
|
||||||
|
else:
|
||||||
|
log.critical("Token and prefix must be set in order to login.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if cli_flags.dry_run:
|
||||||
|
await red.http.close()
|
||||||
|
sys.exit(0)
|
||||||
|
try:
|
||||||
|
await red.start(token, bot=True, cli_flags=cli_flags)
|
||||||
|
except discord.LoginFailure:
|
||||||
|
log.critical("This token doesn't seem to be valid.")
|
||||||
|
db_token = await red._config.token()
|
||||||
|
if db_token and not cli_flags.no_prompt:
|
||||||
|
if confirm("\nDo you want to reset the token?"):
|
||||||
|
await red._config.token.set("")
|
||||||
|
print("Token has been reset.")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def handle_early_exit_flags(cli_flags: Namespace):
|
||||||
description = "Red V3"
|
|
||||||
cli_flags = parse_cli_flags(sys.argv[1:])
|
|
||||||
if cli_flags.list_instances:
|
if cli_flags.list_instances:
|
||||||
list_instances()
|
list_instances()
|
||||||
elif cli_flags.version:
|
elif cli_flags.version:
|
||||||
@ -278,111 +323,75 @@ def main():
|
|||||||
elif not cli_flags.instance_name and (not cli_flags.no_instance or cli_flags.edit):
|
elif not cli_flags.instance_name and (not cli_flags.no_instance or cli_flags.edit):
|
||||||
print("Error: No instance name was provided!")
|
print("Error: No instance name was provided!")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if cli_flags.no_instance:
|
|
||||||
print(
|
|
||||||
"\033[1m"
|
|
||||||
"Warning: The data will be placed in a temporary folder and removed on next system "
|
|
||||||
"reboot."
|
|
||||||
"\033[0m"
|
|
||||||
)
|
|
||||||
cli_flags.instance_name = "temporary_red"
|
|
||||||
data_manager.create_temp_config()
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
|
|
||||||
data_manager.load_basic_configuration(cli_flags.instance_name)
|
|
||||||
driver_cls = drivers.get_driver_class()
|
|
||||||
loop.run_until_complete(driver_cls.initialize(**data_manager.storage_details()))
|
|
||||||
redbot.logging.init_logging(
|
|
||||||
level=cli_flags.logging_level, location=data_manager.core_data_path() / "logs"
|
|
||||||
)
|
|
||||||
|
|
||||||
log.debug("====Basic Config====")
|
async def shutdown_handler(red, signal_type=None):
|
||||||
log.debug("Data Path: %s", data_manager._base_data_path())
|
if signal_type:
|
||||||
log.debug("Storage Type: %s", data_manager.storage_type())
|
log.info("%s received. Quitting...", signal_type)
|
||||||
|
exit_code = 0
|
||||||
|
else:
|
||||||
|
log.info("Shutting down from unhandled exception")
|
||||||
|
exit_code = 1
|
||||||
|
await red.logout()
|
||||||
|
await red.loop.shutdown_asyncgens()
|
||||||
|
pending = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()]
|
||||||
|
[task.cancel() for task in pending]
|
||||||
|
await asyncio.gather(*pending, loop=red.loop, return_exceptions=True)
|
||||||
|
sys.exit(exit_code)
|
||||||
|
|
||||||
red = Red(
|
|
||||||
cli_flags=cli_flags, description=description, dm_help=None, fetch_offline_members=True
|
|
||||||
)
|
|
||||||
loop.run_until_complete(red._maybe_update_config())
|
|
||||||
|
|
||||||
if cli_flags.edit:
|
def exception_handler(red, loop, context):
|
||||||
try:
|
msg = context.get("exception", context["message"])
|
||||||
edit_instance(red, cli_flags)
|
if isinstance(msg, KeyboardInterrupt):
|
||||||
except (KeyboardInterrupt, EOFError):
|
# Windows support is ugly, I'm sorry
|
||||||
print("Aborted!")
|
logging.error("Received KeyboardInterrupt, treating as interrupt")
|
||||||
finally:
|
signal_type = signal.SIGINT
|
||||||
loop.run_until_complete(driver_cls.teardown())
|
else:
|
||||||
sys.exit(0)
|
logging.critical("Caught fatal exception: %s", msg)
|
||||||
|
signal_type = None
|
||||||
|
loop.create_task(shutdown_handler(red, signal_type))
|
||||||
|
|
||||||
init_global_checks(red)
|
|
||||||
init_events(red, cli_flags)
|
|
||||||
|
|
||||||
# lib folder has to be in sys.path before trying to load any 3rd-party cog (GH-3061)
|
def main():
|
||||||
# We might want to change handling of requirements in Downloader at later date
|
cli_flags = parse_cli_flags(sys.argv[1:])
|
||||||
LIB_PATH = data_manager.cog_data_path(raw_name="Downloader") / "lib"
|
handle_early_exit_flags(cli_flags)
|
||||||
LIB_PATH.mkdir(parents=True, exist_ok=True)
|
|
||||||
if str(LIB_PATH) not in sys.path:
|
|
||||||
sys.path.append(str(LIB_PATH))
|
|
||||||
sys.meta_path.insert(0, SharedLibImportWarner())
|
|
||||||
|
|
||||||
red.add_cog(Core(red))
|
|
||||||
red.add_cog(CogManagerUI())
|
|
||||||
red.add_command(license_info_command)
|
|
||||||
if cli_flags.dev:
|
|
||||||
red.add_cog(Dev())
|
|
||||||
# noinspection PyProtectedMember
|
|
||||||
loop.run_until_complete(modlog._init(red))
|
|
||||||
# noinspection PyProtectedMember
|
|
||||||
bank._init()
|
|
||||||
|
|
||||||
if os.name == "posix":
|
|
||||||
loop.add_signal_handler(SIGTERM, lambda: asyncio.ensure_future(sigterm_handler(red, log)))
|
|
||||||
tmp_data = {}
|
|
||||||
loop.run_until_complete(_get_prefix_and_token(red, tmp_data))
|
|
||||||
token = os.environ.get("RED_TOKEN", tmp_data["token"])
|
|
||||||
if cli_flags.token:
|
|
||||||
token = cli_flags.token
|
|
||||||
prefix = cli_flags.prefix or tmp_data["prefix"]
|
|
||||||
if not (token and prefix):
|
|
||||||
if cli_flags.no_prompt is False:
|
|
||||||
new_token = interactive_config(red, token_set=bool(token), prefix_set=bool(prefix))
|
|
||||||
if new_token:
|
|
||||||
token = new_token
|
|
||||||
else:
|
|
||||||
log.critical("Token and prefix must be set in order to login.")
|
|
||||||
sys.exit(1)
|
|
||||||
loop.run_until_complete(_get_prefix_and_token(red, tmp_data))
|
|
||||||
|
|
||||||
if cli_flags.dry_run:
|
|
||||||
loop.run_until_complete(red.http.close())
|
|
||||||
sys.exit(0)
|
|
||||||
try:
|
try:
|
||||||
loop.run_until_complete(red.start(token, bot=True, cli_flags=cli_flags))
|
loop = asyncio.get_event_loop()
|
||||||
except discord.LoginFailure:
|
|
||||||
log.critical("This token doesn't seem to be valid.")
|
|
||||||
db_token = loop.run_until_complete(red._config.token())
|
|
||||||
if db_token and not cli_flags.no_prompt:
|
|
||||||
if confirm("\nDo you want to reset the token?"):
|
|
||||||
loop.run_until_complete(red._config.token.set(""))
|
|
||||||
print("Token has been reset.")
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
log.info("Keyboard interrupt detected. Quitting...")
|
|
||||||
loop.run_until_complete(red.logout())
|
|
||||||
red._shutdown_mode = ExitCodes.SHUTDOWN
|
|
||||||
except Exception as e:
|
|
||||||
log.critical("Fatal exception", exc_info=e)
|
|
||||||
loop.run_until_complete(red.logout())
|
|
||||||
finally:
|
|
||||||
pending = asyncio.Task.all_tasks(loop=red.loop)
|
|
||||||
gathered = asyncio.gather(*pending, loop=red.loop, return_exceptions=True)
|
|
||||||
gathered.cancel()
|
|
||||||
try:
|
|
||||||
loop.run_until_complete(red.rpc.close())
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
sys.exit(red._shutdown_mode.value)
|
if cli_flags.no_instance:
|
||||||
|
print(
|
||||||
|
"\033[1m"
|
||||||
|
"Warning: The data will be placed in a temporary folder and removed on next system "
|
||||||
|
"reboot."
|
||||||
|
"\033[0m"
|
||||||
|
)
|
||||||
|
cli_flags.instance_name = "temporary_red"
|
||||||
|
data_manager.create_temp_config()
|
||||||
|
|
||||||
|
data_manager.load_basic_configuration(cli_flags.instance_name)
|
||||||
|
|
||||||
|
red = Red(
|
||||||
|
cli_flags=cli_flags, description=description, dm_help=None, fetch_offline_members=True
|
||||||
|
)
|
||||||
|
|
||||||
|
if os.name != "nt":
|
||||||
|
# None of this works on windows, and we have to catch KeyboardInterrupt in a global handler!
|
||||||
|
# At least it's not a redundant handler...
|
||||||
|
signals = (signal.SIGHUP, signal.SIGTERM, signal.SIGINT)
|
||||||
|
for s in signals:
|
||||||
|
loop.add_signal_handler(
|
||||||
|
s, lambda s=s: asyncio.create_task(shutdown_handler(red, s))
|
||||||
|
)
|
||||||
|
|
||||||
|
exc_handler = functools.partial(exception_handler, red)
|
||||||
|
loop.set_exception_handler(exc_handler)
|
||||||
|
# We actually can't use asyncio.run and have graceful cleanup on Windows...
|
||||||
|
loop.create_task(run_bot(red, cli_flags))
|
||||||
|
loop.run_forever()
|
||||||
|
finally:
|
||||||
|
loop.close()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
description = "Red V3"
|
||||||
main()
|
main()
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import datetime
|
import datetime
|
||||||
from typing import Union, List, Optional
|
from typing import Union, List, Optional, TYPE_CHECKING
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
@ -8,9 +10,12 @@ import discord
|
|||||||
from redbot.core.utils.chat_formatting import humanize_number
|
from redbot.core.utils.chat_formatting import humanize_number
|
||||||
from . import Config, errors, commands
|
from . import Config, errors, commands
|
||||||
from .i18n import Translator
|
from .i18n import Translator
|
||||||
from .bot import Red
|
|
||||||
from .errors import BankPruneError
|
from .errors import BankPruneError
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .bot import Red
|
||||||
|
|
||||||
_ = Translator("Bank API", __file__)
|
_ = Translator("Bank API", __file__)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import asyncio
|
|||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
@ -13,8 +14,12 @@ from types import MappingProxyType
|
|||||||
import discord
|
import discord
|
||||||
from discord.ext.commands import when_mentioned_or
|
from discord.ext.commands import when_mentioned_or
|
||||||
|
|
||||||
from . import Config, i18n, commands, errors, drivers
|
from . import Config, i18n, commands, errors, drivers, modlog, bank
|
||||||
from .cog_manager import CogManager
|
from .cog_manager import CogManager, CogManagerUI
|
||||||
|
from .core_commands import license_info_command, Core
|
||||||
|
from .dev_commands import Dev
|
||||||
|
from .events import init_events
|
||||||
|
from .global_checks import init_global_checks
|
||||||
|
|
||||||
from .rpc import RPCMixin
|
from .rpc import RPCMixin
|
||||||
from .utils import common_filters
|
from .utils import common_filters
|
||||||
@ -43,6 +48,7 @@ class RedBase(commands.GroupMixin, commands.bot.BotBase, RPCMixin): # pylint: d
|
|||||||
|
|
||||||
def __init__(self, *args, cli_flags=None, bot_dir: Path = Path.cwd(), **kwargs):
|
def __init__(self, *args, cli_flags=None, bot_dir: Path = Path.cwd(), **kwargs):
|
||||||
self._shutdown_mode = ExitCodes.CRITICAL
|
self._shutdown_mode = ExitCodes.CRITICAL
|
||||||
|
self._cli_flags = cli_flags
|
||||||
self._config = Config.get_core_conf(force_registration=False)
|
self._config = Config.get_core_conf(force_registration=False)
|
||||||
self._co_owners = cli_flags.co_owner
|
self._co_owners = cli_flags.co_owner
|
||||||
self.rpc_enabled = cli_flags.rpc
|
self.rpc_enabled = cli_flags.rpc
|
||||||
@ -392,6 +398,18 @@ class RedBase(commands.GroupMixin, commands.bot.BotBase, RPCMixin): # pylint: d
|
|||||||
"""
|
"""
|
||||||
await self._maybe_update_config()
|
await self._maybe_update_config()
|
||||||
|
|
||||||
|
init_global_checks(self)
|
||||||
|
init_events(self, cli_flags)
|
||||||
|
|
||||||
|
self.add_cog(Core(self))
|
||||||
|
self.add_cog(CogManagerUI())
|
||||||
|
self.add_command(license_info_command)
|
||||||
|
if cli_flags.dev:
|
||||||
|
self.add_cog(Dev())
|
||||||
|
|
||||||
|
await modlog._init(self)
|
||||||
|
bank._init()
|
||||||
|
|
||||||
packages = []
|
packages = []
|
||||||
|
|
||||||
if cli_flags.no_cogs is False:
|
if cli_flags.no_cogs is False:
|
||||||
@ -971,6 +989,10 @@ class Red(RedBase, discord.AutoShardedClient):
|
|||||||
"""Logs out of Discord and closes all connections."""
|
"""Logs out of Discord and closes all connections."""
|
||||||
await super().logout()
|
await super().logout()
|
||||||
await drivers.get_driver_class().teardown()
|
await drivers.get_driver_class().teardown()
|
||||||
|
try:
|
||||||
|
await self.rpc.close()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
async def shutdown(self, *, restart: bool = False):
|
async def shutdown(self, *, restart: bool = False):
|
||||||
"""Gracefully quit Red.
|
"""Gracefully quit Red.
|
||||||
@ -990,6 +1012,7 @@ class Red(RedBase, discord.AutoShardedClient):
|
|||||||
self._shutdown_mode = ExitCodes.RESTART
|
self._shutdown_mode = ExitCodes.RESTART
|
||||||
|
|
||||||
await self.logout()
|
await self.logout()
|
||||||
|
sys.exit(self._shutdown_mode)
|
||||||
|
|
||||||
|
|
||||||
class ExitCodes(Enum):
|
class ExitCodes(Enum):
|
||||||
|
|||||||
@ -33,9 +33,8 @@ def confirm(text: str, default: Optional[bool] = None) -> bool:
|
|||||||
print("Error: invalid input")
|
print("Error: invalid input")
|
||||||
|
|
||||||
|
|
||||||
def interactive_config(red, token_set, prefix_set, *, print_header=True):
|
async def interactive_config(red, token_set, prefix_set, *, print_header=True):
|
||||||
loop = asyncio.get_event_loop()
|
token = None
|
||||||
token = ""
|
|
||||||
|
|
||||||
if print_header:
|
if print_header:
|
||||||
print("Red - Discord Bot | Configuration process\n")
|
print("Red - Discord Bot | Configuration process\n")
|
||||||
@ -51,9 +50,9 @@ def interactive_config(red, token_set, prefix_set, *, print_header=True):
|
|||||||
token = input("> ")
|
token = input("> ")
|
||||||
if not len(token) >= 50:
|
if not len(token) >= 50:
|
||||||
print("That doesn't look like a valid token.")
|
print("That doesn't look like a valid token.")
|
||||||
token = ""
|
token = None
|
||||||
if token:
|
if token:
|
||||||
loop.run_until_complete(red._config.token.set(token))
|
await red._config.token.set(token)
|
||||||
|
|
||||||
if not prefix_set:
|
if not prefix_set:
|
||||||
prefix = ""
|
prefix = ""
|
||||||
@ -70,7 +69,7 @@ def interactive_config(red, token_set, prefix_set, *, print_header=True):
|
|||||||
if not confirm("Your prefix seems overly long. Are you sure that it's correct?"):
|
if not confirm("Your prefix seems overly long. Are you sure that it's correct?"):
|
||||||
prefix = ""
|
prefix = ""
|
||||||
if prefix:
|
if prefix:
|
||||||
loop.run_until_complete(red._config.prefix.set([prefix]))
|
await red._config.prefix.set([prefix])
|
||||||
|
|
||||||
return token
|
return token
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import codecs
|
|||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
import asyncio
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
@ -17,7 +16,6 @@ from redbot.core.commands import RedHelpFormatter
|
|||||||
from .. import __version__ as red_version, version_info as red_version_info, VersionInfo
|
from .. import __version__ as red_version, version_info as red_version_info, VersionInfo
|
||||||
from . import commands
|
from . import commands
|
||||||
from .config import get_latest_confs
|
from .config import get_latest_confs
|
||||||
from .data_manager import storage_type
|
|
||||||
from .utils.chat_formatting import inline, bordered, format_perms_list, humanize_timedelta
|
from .utils.chat_formatting import inline, bordered, format_perms_list, humanize_timedelta
|
||||||
from .utils import fuzzy_command_search, format_fuzzy_results
|
from .utils import fuzzy_command_search, format_fuzzy_results
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import List, Union, Optional, cast
|
from typing import List, Union, Optional, cast, TYPE_CHECKING
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
from redbot.core import Config
|
from redbot.core import Config
|
||||||
from redbot.core.bot import Red
|
|
||||||
|
|
||||||
from .utils.common_filters import (
|
from .utils.common_filters import (
|
||||||
filter_invites,
|
filter_invites,
|
||||||
@ -17,6 +18,9 @@ from .i18n import Translator
|
|||||||
|
|
||||||
from .generic_casetypes import all_generics
|
from .generic_casetypes import all_generics
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from redbot.core.bot import Red
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Case",
|
"Case",
|
||||||
"CaseType",
|
"CaseType",
|
||||||
|
|||||||
11
setup.cfg
11
setup.cfg
@ -18,13 +18,13 @@ classifiers =
|
|||||||
License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
||||||
Natural Language :: English
|
Natural Language :: English
|
||||||
Operating System :: OS Independent
|
Operating System :: OS Independent
|
||||||
Programming Language :: Python :: 3.7
|
Programming Language :: Python :: 3.8
|
||||||
Topic :: Communications :: Chat
|
Topic :: Communications :: Chat
|
||||||
Topic :: Documentation :: Sphinx
|
Topic :: Documentation :: Sphinx
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
packages = find_namespace:
|
packages = find_namespace:
|
||||||
python_requires = >=3.7
|
python_requires = >=3.8.1
|
||||||
install_requires =
|
install_requires =
|
||||||
aiohttp==3.5.4
|
aiohttp==3.5.4
|
||||||
aiohttp-json-rpc==0.12.1
|
aiohttp-json-rpc==0.12.1
|
||||||
@ -87,9 +87,8 @@ style =
|
|||||||
black==19.3b0
|
black==19.3b0
|
||||||
toml==0.10.0
|
toml==0.10.0
|
||||||
test =
|
test =
|
||||||
astroid==2.2.5
|
astroid==2.3.3
|
||||||
atomicwrites==1.3.0
|
atomicwrites==1.3.0
|
||||||
importlib-metadata==0.19
|
|
||||||
isort==4.3.21
|
isort==4.3.21
|
||||||
lazy-object-proxy==1.4.2
|
lazy-object-proxy==1.4.2
|
||||||
mccabe==0.6.1
|
mccabe==0.6.1
|
||||||
@ -99,9 +98,9 @@ test =
|
|||||||
py==1.8.0
|
py==1.8.0
|
||||||
pylint==2.3.1
|
pylint==2.3.1
|
||||||
pyparsing==2.4.2
|
pyparsing==2.4.2
|
||||||
pytest==5.1.2
|
pytest==5.3.2
|
||||||
pytest-asyncio==0.10.0
|
pytest-asyncio==0.10.0
|
||||||
pytest-mock==1.11.2
|
pytest-mock==1.13.0
|
||||||
six==1.12.0
|
six==1.12.0
|
||||||
typed-ast==1.4.0
|
typed-ast==1.4.0
|
||||||
wcwidth==0.1.7
|
wcwidth==0.1.7
|
||||||
|
|||||||
@ -25,18 +25,11 @@ class FakeCompletedProcess(NamedTuple):
|
|||||||
stderr: bytes = b""
|
stderr: bytes = b""
|
||||||
|
|
||||||
|
|
||||||
async def async_return(ret: Any):
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def _mock_run(
|
def _mock_run(
|
||||||
mocker: MockFixture, repo: Repo, returncode: int, stdout: bytes = b"", stderr: bytes = b""
|
mocker: MockFixture, repo: Repo, returncode: int, stdout: bytes = b"", stderr: bytes = b""
|
||||||
):
|
):
|
||||||
return mocker.patch.object(
|
return mocker.patch.object(
|
||||||
repo,
|
repo, "_run", autospec=True, return_value=FakeCompletedProcess(returncode, stdout, stderr)
|
||||||
"_run",
|
|
||||||
autospec=True,
|
|
||||||
return_value=async_return(FakeCompletedProcess(returncode, stdout, stderr)),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -46,11 +39,7 @@ def _mock_setup_repo(mocker: MockFixture, repo: Repo, commit: str):
|
|||||||
return mocker.DEFAULT
|
return mocker.DEFAULT
|
||||||
|
|
||||||
return mocker.patch.object(
|
return mocker.patch.object(
|
||||||
repo,
|
repo, "_setup_repo", autospec=True, side_effect=update_commit, return_value=None
|
||||||
"_setup_repo",
|
|
||||||
autospec=True,
|
|
||||||
side_effect=update_commit,
|
|
||||||
return_value=async_return(None),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -153,15 +142,13 @@ async def test_is_module_modified(mocker, repo):
|
|||||||
repo,
|
repo,
|
||||||
"_get_file_update_statuses",
|
"_get_file_update_statuses",
|
||||||
autospec=True,
|
autospec=True,
|
||||||
return_value=async_return(
|
return_value={
|
||||||
{
|
"added_file.txt": "A",
|
||||||
"added_file.txt": "A",
|
"mycog/__init__.py": "M",
|
||||||
"mycog/__init__.py": "M",
|
"sample_file1.txt": "D",
|
||||||
"sample_file1.txt": "D",
|
"sample_file2.txt": "D",
|
||||||
"sample_file2.txt": "D",
|
"sample_file3.txt": "A",
|
||||||
"sample_file3.txt": "A",
|
},
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
ret = await repo._is_module_modified(module, old_rev)
|
ret = await repo._is_module_modified(module, old_rev)
|
||||||
m.assert_called_once_with(old_rev, new_rev)
|
m.assert_called_once_with(old_rev, new_rev)
|
||||||
@ -249,11 +236,11 @@ async def test_checkout(mocker, repo):
|
|||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_checkout_ctx_manager(mocker, repo):
|
async def test_checkout_ctx_manager(mocker, repo):
|
||||||
commit = "c950fc05a540dd76b944719c2a3302da2e2f3090"
|
commit = "c950fc05a540dd76b944719c2a3302da2e2f3090"
|
||||||
m = mocker.patch.object(repo, "_checkout", autospec=True, return_value=async_return(None))
|
m = mocker.patch.object(repo, "_checkout", autospec=True, return_value=None)
|
||||||
old_commit = repo.commit
|
old_commit = repo.commit
|
||||||
async with repo.checkout(commit):
|
async with repo.checkout(commit):
|
||||||
m.assert_called_with(commit, force_checkout=False)
|
m.assert_called_with(commit, force_checkout=False)
|
||||||
m.return_value = async_return(None)
|
m.return_value = None
|
||||||
|
|
||||||
m.assert_called_with(old_commit, force_checkout=False)
|
m.assert_called_with(old_commit, force_checkout=False)
|
||||||
|
|
||||||
@ -261,7 +248,7 @@ async def test_checkout_ctx_manager(mocker, repo):
|
|||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_checkout_await(mocker, repo):
|
async def test_checkout_await(mocker, repo):
|
||||||
commit = "c950fc05a540dd76b944719c2a3302da2e2f3090"
|
commit = "c950fc05a540dd76b944719c2a3302da2e2f3090"
|
||||||
m = mocker.patch.object(repo, "_checkout", autospec=True, return_value=async_return(None))
|
m = mocker.patch.object(repo, "_checkout", autospec=True, return_value=None)
|
||||||
await repo.checkout(commit)
|
await repo.checkout(commit)
|
||||||
|
|
||||||
m.assert_called_once_with(commit, force_checkout=False)
|
m.assert_called_once_with(commit, force_checkout=False)
|
||||||
@ -293,7 +280,7 @@ async def test_clone_without_branch(mocker, repo):
|
|||||||
repo.commit = ""
|
repo.commit = ""
|
||||||
m = _mock_run(mocker, repo, 0)
|
m = _mock_run(mocker, repo, 0)
|
||||||
_mock_setup_repo(mocker, repo, commit)
|
_mock_setup_repo(mocker, repo, commit)
|
||||||
mocker.patch.object(repo, "current_branch", autospec=True, return_value=async_return(branch))
|
mocker.patch.object(repo, "current_branch", autospec=True, return_value=branch)
|
||||||
|
|
||||||
await repo.clone()
|
await repo.clone()
|
||||||
|
|
||||||
@ -309,10 +296,8 @@ async def test_update(mocker, repo):
|
|||||||
new_commit = "a0ccc2390883c85a361f5a90c72e1b07958939fa"
|
new_commit = "a0ccc2390883c85a361f5a90c72e1b07958939fa"
|
||||||
m = _mock_run(mocker, repo, 0)
|
m = _mock_run(mocker, repo, 0)
|
||||||
_mock_setup_repo(mocker, repo, new_commit)
|
_mock_setup_repo(mocker, repo, new_commit)
|
||||||
mocker.patch.object(
|
mocker.patch.object(repo, "latest_commit", autospec=True, return_value=old_commit)
|
||||||
repo, "latest_commit", autospec=True, return_value=async_return(old_commit)
|
mocker.patch.object(repo, "hard_reset", autospec=True, return_value=None)
|
||||||
)
|
|
||||||
mocker.patch.object(repo, "hard_reset", autospec=True, return_value=async_return(None))
|
|
||||||
ret = await repo.update()
|
ret = await repo.update()
|
||||||
|
|
||||||
assert ret == (old_commit, new_commit)
|
assert ret == (old_commit, new_commit)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python3.7
|
#!/usr/bin/env python3.8
|
||||||
"""Script to bump pinned dependencies in setup.cfg.
|
"""Script to bump pinned dependencies in setup.cfg.
|
||||||
|
|
||||||
This script aims to help update our list of pinned primary and
|
This script aims to help update our list of pinned primary and
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python3.7
|
#!/usr/bin/env python3.8
|
||||||
"""Script to edit test repo used by Downloader git integration tests.
|
"""Script to edit test repo used by Downloader git integration tests.
|
||||||
|
|
||||||
This script aims to help update the human-readable version of repo
|
This script aims to help update the human-readable version of repo
|
||||||
|
|||||||
8
tox.ini
8
tox.ini
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[tox]
|
[tox]
|
||||||
envlist =
|
envlist =
|
||||||
py37
|
py38
|
||||||
docs
|
docs
|
||||||
style
|
style
|
||||||
skip_missing_interpreters = True
|
skip_missing_interpreters = True
|
||||||
@ -19,7 +19,7 @@ extras = voice, test
|
|||||||
commands =
|
commands =
|
||||||
python -m compileall ./redbot/cogs
|
python -m compileall ./redbot/cogs
|
||||||
pytest
|
pytest
|
||||||
pylint ./redbot
|
# pylint ./redbot
|
||||||
|
|
||||||
[testenv:postgres]
|
[testenv:postgres]
|
||||||
description = Run pytest with PostgreSQL backend
|
description = Run pytest with PostgreSQL backend
|
||||||
@ -48,7 +48,7 @@ setenv =
|
|||||||
# This is just for Windows
|
# This is just for Windows
|
||||||
# Prioritise make.bat over any make.exe which might be on PATH
|
# Prioritise make.bat over any make.exe which might be on PATH
|
||||||
PATHEXT=.BAT;.EXE
|
PATHEXT=.BAT;.EXE
|
||||||
basepython = python3.7
|
basepython = python3.8
|
||||||
extras = docs
|
extras = docs
|
||||||
commands =
|
commands =
|
||||||
sphinx-build -d "{toxworkdir}/docs_doctree" docs "{toxworkdir}/docs_out/html" -W -bhtml
|
sphinx-build -d "{toxworkdir}/docs_doctree" docs "{toxworkdir}/docs_out/html" -W -bhtml
|
||||||
@ -64,7 +64,7 @@ setenv =
|
|||||||
# This is just for Windows
|
# This is just for Windows
|
||||||
# Prioritise make.bat over any make.exe which might be on PATH
|
# Prioritise make.bat over any make.exe which might be on PATH
|
||||||
PATHEXT=.BAT;.EXE
|
PATHEXT=.BAT;.EXE
|
||||||
basepython = python3.7
|
basepython = python3.8
|
||||||
extras = style
|
extras = style
|
||||||
commands =
|
commands =
|
||||||
make stylecheck
|
make stylecheck
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user