mirror of
https://github.com/Steffo99/async-chain.git
synced 2024-12-03 10:24:19 +00:00
First commit (0.1.0)
This commit is contained in:
commit
6511da99f2
20 changed files with 954 additions and 0 deletions
138
.gitignore
vendored
Normal file
138
.gitignore
vendored
Normal file
|
@ -0,0 +1,138 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
78
.idea/codeStyles/Project.xml
Normal file
78
.idea/codeStyles/Project.xml
Normal file
|
@ -0,0 +1,78 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<HTMLCodeStyleSettings>
|
||||
<option name="HTML_UNIFORM_INDENT" value="true" />
|
||||
<option name="HTML_ATTRIBUTE_WRAP" value="0" />
|
||||
<option name="HTML_TEXT_WRAP" value="0" />
|
||||
<option name="HTML_ALIGN_ATTRIBUTES" value="false" />
|
||||
<option name="HTML_ELEMENTS_TO_INSERT_NEW_LINE_BEFORE" value="address,article,aside,blockquote,details,dialog,dd,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,li,main,nav,ol,p,pre,section,table,ul" />
|
||||
<option name="HTML_ELEMENTS_TO_REMOVE_NEW_LINE_BEFORE" value="a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var" />
|
||||
<option name="HTML_DO_NOT_INDENT_CHILDREN_OF" value="" />
|
||||
<option name="HTML_DONT_ADD_BREAKS_IF_INLINE_CONTENT" value="" />
|
||||
<option name="HTML_ENFORCE_QUOTES" value="true" />
|
||||
<option name="HTML_NEWLINE_BEFORE_FIRST_ATTRIBUTE" value="When multiline" />
|
||||
<option name="HTML_NEWLINE_AFTER_LAST_ATTRIBUTE" value="When multiline" />
|
||||
</HTMLCodeStyleSettings>
|
||||
<JSCodeStyleSettings version="0">
|
||||
<option name="USE_SEMICOLON_AFTER_STATEMENT" value="false" />
|
||||
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||
<option name="REFORMAT_C_STYLE_COMMENTS" value="true" />
|
||||
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
|
||||
<option name="VAR_DECLARATION_WRAP" value="5" />
|
||||
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||
<option name="INDENT_CHAINED_CALLS" value="false" />
|
||||
</JSCodeStyleSettings>
|
||||
<ScalaCodeStyleSettings>
|
||||
<option name="MULTILINE_STRING_CLOSING_QUOTES_ON_NEW_LINE" value="true" />
|
||||
</ScalaCodeStyleSettings>
|
||||
<codeStyleSettings language="HTML">
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="JSON">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="JavaScript">
|
||||
<option name="BLANK_LINES_AFTER_IMPORTS" value="2" />
|
||||
<option name="BLANK_LINES_AROUND_CLASS" value="2" />
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="CATCH_ON_NEW_LINE" value="true" />
|
||||
<option name="FINALLY_ON_NEW_LINE" value="true" />
|
||||
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
|
||||
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
|
||||
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
|
||||
<option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
|
||||
<option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" />
|
||||
<option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
|
||||
<option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" />
|
||||
<option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="5" />
|
||||
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="METHOD_CALL_CHAIN_WRAP" value="5" />
|
||||
<option name="PARENTHESES_EXPRESSION_LPAREN_WRAP" value="true" />
|
||||
<option name="PARENTHESES_EXPRESSION_RPAREN_WRAP" value="true" />
|
||||
<option name="BINARY_OPERATION_WRAP" value="5" />
|
||||
<option name="TERNARY_OPERATION_WRAP" value="5" />
|
||||
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
|
||||
<option name="ARRAY_INITIALIZER_WRAP" value="5" />
|
||||
<option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true" />
|
||||
<option name="ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE" value="true" />
|
||||
<option name="IF_BRACE_FORCE" value="3" />
|
||||
<option name="DOWHILE_BRACE_FORCE" value="3" />
|
||||
<option name="WHILE_BRACE_FORCE" value="3" />
|
||||
<option name="FOR_BRACE_FORCE" value="3" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="LESS">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
5
.idea/codeStyles/codeStyleConfig.xml
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
6
.idea/discord.xml
Normal file
6
.idea/discord.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
</component>
|
||||
</project>
|
74
.idea/inspectionProfiles/Project_Default.xml
Normal file
74
.idea/inspectionProfiles/Project_Default.xml
Normal file
|
@ -0,0 +1,74 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="JupyterPackageInspection" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="LessResolvedByNameOnly" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="LessUnresolvedMixin" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="LessUnresolvedVariable" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="LongLine" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PoetryPackageVersion" enabled="true" level="SERVER PROBLEM" enabled_by_default="true" />
|
||||
<inspection_tool class="ProblematicWhitespace" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyAbstractClassInspection" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="PyAttributeOutsideInitInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyAugmentAssignmentInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyBroadExceptionInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="PyDictDuplicateKeysInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyDocstringTypesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyDunderSlotsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="PyFinalInspection" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="PyFromFutureImportInspection" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="PyGlobalUndefinedInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyInconsistentIndentationInspection" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="PyInterpreterInspection" enabled="true" level="SERVER PROBLEM" enabled_by_default="true" />
|
||||
<inspection_tool class="PyMandatoryEncodingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyMethodMayBeStaticInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="PyMissingTypeHintsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyNestedDecoratorsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyNoneFunctionAssignmentInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyPackageRequirementsInspection" enabled="false" level="ERROR" enabled_by_default="false">
|
||||
<option name="ignoredPackages">
|
||||
<value>
|
||||
<list size="0" />
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||
<option name="ignoredErrors">
|
||||
<list>
|
||||
<option value="N806" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyRelativeImportInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyReturnFromInitInspection" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="PySetFunctionToLiteralInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyStringFormatInspection" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="PyTrailingSemicolonInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyUnnecessaryBackslashInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredIdentifiers">
|
||||
<list>
|
||||
<option value="pydantic.main.BaseModel.__root__" />
|
||||
<option value="telethon.client.telegramclient.TelegramClient.__await__" />
|
||||
<option value="royalnet.engineer.pda.implementations.base.PDAImplementation.register_partial" />
|
||||
<option value="royalnet.engineer.pda.implementations.base.PDAImplementation.register_partialcommand" />
|
||||
<option value="royalnet.engineer.pda.implementations.base.PDAImplementation.register_conversation" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="RegExpAnonymousGroup" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="RegExpEscapedMetaCharacter" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="RegExpOctalEscape" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="RegExpRedundantEscape" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="RegExpRedundantNestedCharacterClass" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="RegExpRepeatedSpace" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="RegExpUnexpectedAnchor" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="ShellCheck" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
9
.idea/misc.xml
Normal file
9
.idea/misc.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ClojureProjectResolveSettings">
|
||||
<currentScheme>IDE</currentScheme>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" project-jdk-name="Poetry (async-chain)" project-jdk-type="Python SDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/async-chain.iml" filepath="$PROJECT_DIR$/async-chain.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
165
LICENSE.txt
Normal file
165
LICENSE.txt
Normal file
|
@ -0,0 +1,165 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
56
README.md
Normal file
56
README.md
Normal file
|
@ -0,0 +1,56 @@
|
|||
# `async-chain`
|
||||
|
||||
A coroutine builder
|
||||
|
||||
|
||||
## What?
|
||||
|
||||
Have you ever felt that the `await` syntax in Python was a bit clunky when chaining multiple methods together?
|
||||
|
||||
```python
|
||||
async def on_message(event):
|
||||
message = await event.get_message()
|
||||
author = await message.get_author()
|
||||
await author.send_message("Hello world!")
|
||||
```
|
||||
|
||||
Or even worse:
|
||||
|
||||
```python
|
||||
async def on_message(event):
|
||||
(await (await (await event.get_message()).get_author()).send_message("Hello world!"))
|
||||
```
|
||||
|
||||
`async-chain` is here to solve your problem!
|
||||
|
||||
```python
|
||||
async def on_message(event):
|
||||
await event.get_message().get_author().send_message("Hello world!")
|
||||
```
|
||||
|
||||
|
||||
## How?
|
||||
|
||||
First, install `async_chain` with your favorite package manager:
|
||||
|
||||
```console
|
||||
$ pip install async_chain
|
||||
```
|
||||
```console
|
||||
$ pipenv install async_chain
|
||||
```
|
||||
```console
|
||||
$ poetry add async_chain
|
||||
```
|
||||
|
||||
Then, add the `@async_chain.method` decorator to any async method you wish to make chainable, and the problem will be
|
||||
magically solved!
|
||||
|
||||
```python
|
||||
import async_chain
|
||||
|
||||
class MyEvent:
|
||||
@async_chain.method
|
||||
async def get_message(self):
|
||||
...
|
||||
```
|
12
async-chain.iml
Normal file
12
async-chain.iml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/async_chain" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/async_chain/tests" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
1
async_chain/__init__.py
Normal file
1
async_chain/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
from .decorators import method_deco as method
|
117
async_chain/chain.py
Normal file
117
async_chain/chain.py
Normal file
|
@ -0,0 +1,117 @@
|
|||
import inspect
|
||||
import typing as t
|
||||
import abc
|
||||
|
||||
|
||||
class Chain(metaclass=abc.ABCMeta):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __getattr__(self, item):
|
||||
return ChainGetAttr(previous=self, item=item)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return ChainGetItem(previous=self, item=item)
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return ChainCall(previous=self, args=args, kwargs=kwargs)
|
||||
|
||||
def __await__(self):
|
||||
return self.__evaluate__().__await__()
|
||||
|
||||
@abc.abstractmethod
|
||||
def __repr__(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
@abc.abstractmethod
|
||||
def __display__(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
@abc.abstractmethod
|
||||
async def __evaluate__(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class ChainStart(Chain):
|
||||
def __init__(self, start: t.Any):
|
||||
super().__init__()
|
||||
self.__start__: t.Any = start
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Chain {self.__display__()}>"
|
||||
|
||||
def __display__(self):
|
||||
return f"{self.__start__!r}"
|
||||
|
||||
async def __evaluate__(self):
|
||||
return self.__start__
|
||||
|
||||
|
||||
class ChainNode(Chain, metaclass=abc.ABCMeta):
|
||||
def __init__(self, previous: Chain):
|
||||
super().__init__()
|
||||
self.__previous__: Chain = previous
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Chain {self.__display__()}>"
|
||||
|
||||
|
||||
class ChainGetAttr(ChainNode):
|
||||
def __init__(self, previous: Chain, item: str):
|
||||
super().__init__(previous=previous)
|
||||
self._item: str = item
|
||||
|
||||
def __display__(self):
|
||||
return f"{self.__previous__.__display__()}.{self._item!s}"
|
||||
|
||||
async def __evaluate__(self):
|
||||
previous = await self.__previous__.__evaluate__()
|
||||
|
||||
current = getattr(previous, self._item)
|
||||
|
||||
if inspect.isawaitable(current):
|
||||
return await current
|
||||
else:
|
||||
return current
|
||||
|
||||
|
||||
class ChainGetItem(ChainNode):
|
||||
def __init__(self, previous: Chain, item: t.Any):
|
||||
super().__init__(previous=previous)
|
||||
self._item: t.Any = item
|
||||
|
||||
def __display__(self):
|
||||
return f"{self.__previous__.__display__()}[{self._item!r}]"
|
||||
|
||||
async def __evaluate__(self):
|
||||
previous = await self.__previous__.__evaluate__()
|
||||
|
||||
current = previous[self._item]
|
||||
|
||||
if inspect.isawaitable(current):
|
||||
return await current
|
||||
else:
|
||||
return current
|
||||
|
||||
|
||||
class ChainCall(ChainNode):
|
||||
def __init__(self, previous: Chain, args, kwargs):
|
||||
super().__init__(previous=previous)
|
||||
self._args = args
|
||||
self._kwargs = kwargs
|
||||
|
||||
def __display__(self):
|
||||
args = map(lambda a: f"{a!r}", self._args)
|
||||
kwargs = map(lambda k, v: f"{k!s}={v!r}", self._kwargs)
|
||||
allargs = ", ".join([*args, *kwargs])
|
||||
return f"{self.__previous__.__display__()}({allargs})"
|
||||
|
||||
async def __evaluate__(self):
|
||||
previous = await self.__previous__.__evaluate__()
|
||||
|
||||
current = previous(*self._args, **self._kwargs)
|
||||
|
||||
if inspect.isawaitable(current):
|
||||
return await current
|
||||
else:
|
||||
return current
|
20
async_chain/decorators.py
Normal file
20
async_chain/decorators.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
import functools
|
||||
from .chain import ChainStart
|
||||
|
||||
|
||||
class FunctionWrapper:
|
||||
def __init__(self, func):
|
||||
self._func = func
|
||||
|
||||
def __repr__(self):
|
||||
return self._func.__name__
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self._func(*args, **kwargs)
|
||||
|
||||
|
||||
def method_deco(func):
|
||||
@functools.wraps(func)
|
||||
def decorated(*args, **kwargs):
|
||||
return ChainStart(start=FunctionWrapper(func))(*args, **kwargs)
|
||||
return decorated
|
65
async_chain/tests/test_integration.py
Normal file
65
async_chain/tests/test_integration.py
Normal file
|
@ -0,0 +1,65 @@
|
|||
import pytest
|
||||
import asyncio
|
||||
import async_chain
|
||||
|
||||
pytestmark = pytest.mark.asyncio
|
||||
|
||||
|
||||
class ExampleClass:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __repr__(self):
|
||||
return f"Example(value={self.value})"
|
||||
|
||||
@async_chain.method
|
||||
async def plus(self, n):
|
||||
await asyncio.sleep(0)
|
||||
return self.__class__(self.value + n)
|
||||
|
||||
@property
|
||||
@async_chain.method
|
||||
async def incremented(self):
|
||||
await asyncio.sleep(0)
|
||||
return self.__class__(self.value + 1)
|
||||
|
||||
|
||||
async def test_class_creation():
|
||||
example = ExampleClass(0)
|
||||
assert example
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def example():
|
||||
return ExampleClass(0)
|
||||
|
||||
|
||||
async def test_method_existence(example):
|
||||
assert hasattr(example, "plus")
|
||||
assert hasattr(example, "minus")
|
||||
assert hasattr(example, "incremented")
|
||||
assert hasattr(example, "decremented")
|
||||
|
||||
|
||||
async def test_chain_single_property(example):
|
||||
one = await example.incremented
|
||||
assert isinstance(one, ExampleClass)
|
||||
assert one.value == 1
|
||||
|
||||
|
||||
async def test_chain_multiple_properties(example):
|
||||
three = await example.incremented.incremented.incremented
|
||||
assert isinstance(three, ExampleClass)
|
||||
assert three.value == 3
|
||||
|
||||
|
||||
async def test_chain_single_method(example):
|
||||
one = await example.plus(1)
|
||||
assert isinstance(one, ExampleClass)
|
||||
assert one.value == 1
|
||||
|
||||
|
||||
async def test_chain_multiple_methods(example):
|
||||
three = await example.plus(1).plus(1).plus(1)
|
||||
assert isinstance(three, ExampleClass)
|
||||
assert three.value == 3
|
BIN
dist/async-chain-0.1.0.tar.gz
vendored
Normal file
BIN
dist/async-chain-0.1.0.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/async_chain-0.1.0-py3-none-any.whl
vendored
Normal file
BIN
dist/async_chain-0.1.0-py3-none-any.whl
vendored
Normal file
Binary file not shown.
169
poetry.lock
generated
Normal file
169
poetry.lock
generated
Normal file
|
@ -0,0 +1,169 @@
|
|||
[[package]]
|
||||
name = "atomicwrites"
|
||||
version = "1.4.0"
|
||||
description = "Atomic file writes."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "21.2.0"
|
||||
description = "Classes Without Boilerplate"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[package.extras]
|
||||
dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"]
|
||||
docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
|
||||
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"]
|
||||
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.4"
|
||||
description = "Cross-platform colored terminal text."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "1.1.1"
|
||||
description = "iniconfig: brain-dead simple config-ini parsing"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "20.9"
|
||||
description = "Core utilities for Python packages"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[package.dependencies]
|
||||
pyparsing = ">=2.0.2"
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "0.13.1"
|
||||
description = "plugin and hook calling mechanisms for python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[package.extras]
|
||||
dev = ["pre-commit", "tox"]
|
||||
|
||||
[[package]]
|
||||
name = "py"
|
||||
version = "1.10.0"
|
||||
description = "library with cross-python path, ini-parsing, io, code, log facilities"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "2.4.7"
|
||||
description = "Python parsing module"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "6.2.4"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
|
||||
attrs = ">=19.2.0"
|
||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||
iniconfig = "*"
|
||||
packaging = "*"
|
||||
pluggy = ">=0.12,<1.0.0a1"
|
||||
py = ">=1.8.2"
|
||||
toml = "*"
|
||||
|
||||
[package.extras]
|
||||
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-asyncio"
|
||||
version = "0.15.1"
|
||||
description = "Pytest support for asyncio."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">= 3.6"
|
||||
|
||||
[package.dependencies]
|
||||
pytest = ">=5.4.0"
|
||||
|
||||
[package.extras]
|
||||
testing = ["coverage", "hypothesis (>=5.7.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.10.2"
|
||||
description = "Python Library for Tom's Obvious, Minimal Language"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "c2b7c085b84345a56b06880b4b394c66fce9dfc78324db16be8289e9d9f750c2"
|
||||
|
||||
[metadata.files]
|
||||
atomicwrites = [
|
||||
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
|
||||
{file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
|
||||
]
|
||||
attrs = [
|
||||
{file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"},
|
||||
{file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"},
|
||||
]
|
||||
colorama = [
|
||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
||||
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
||||
]
|
||||
iniconfig = [
|
||||
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
||||
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
||||
]
|
||||
packaging = [
|
||||
{file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"},
|
||||
{file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"},
|
||||
]
|
||||
pluggy = [
|
||||
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
|
||||
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
|
||||
]
|
||||
py = [
|
||||
{file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"},
|
||||
{file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"},
|
||||
]
|
||||
pyparsing = [
|
||||
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
|
||||
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
|
||||
]
|
||||
pytest = [
|
||||
{file = "pytest-6.2.4-py3-none-any.whl", hash = "sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890"},
|
||||
{file = "pytest-6.2.4.tar.gz", hash = "sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b"},
|
||||
]
|
||||
pytest-asyncio = [
|
||||
{file = "pytest-asyncio-0.15.1.tar.gz", hash = "sha256:2564ceb9612bbd560d19ca4b41347b54e7835c2f792c504f698e05395ed63f6f"},
|
||||
{file = "pytest_asyncio-0.15.1-py3-none-any.whl", hash = "sha256:3042bcdf1c5d978f6b74d96a151c4cfb9dcece65006198389ccd7e6c60eb1eea"},
|
||||
]
|
||||
toml = [
|
||||
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
||||
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
||||
]
|
17
pyproject.toml
Normal file
17
pyproject.toml
Normal file
|
@ -0,0 +1,17 @@
|
|||
[tool.poetry]
|
||||
name = "async-chain"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = ["Stefano Pigozzi <me@steffo.eu>"]
|
||||
license = "LGPL-3.0-or-later"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = "^6.2.4"
|
||||
pytest-asyncio = "^0.15.1"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
Loading…
Reference in a new issue