mirror of
https://github.com/Paillat-dev/pycord-reactive-views.git
synced 2026-01-02 01:06:18 +00:00
👷 Work in progress
This commit is contained in:
82
.idea/inspectionProfiles/Project_Default.xml
generated
82
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -1,7 +1,53 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
<component name="InspectionProjectProfileManager">
|
||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="CommandLineInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="CythonUsageBeforeDeclarationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PoetryPackageVersionsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyAbstractClassInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyArgumentListInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyAssignmentToLoopOrWithParameterInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyAsyncCallInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyAttributeOutsideInitInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyBDDParametersInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyBroadExceptionInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyByteLiteralInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyCallingNonCallableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyChainedComparisonsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyClassHasNoInitInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyClassVarInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyComparisonWithNoneInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyDataclassInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyDecoratorInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyDefaultArgumentInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyDeprecationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyDictCreationInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyDictDuplicateKeysInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyDocstringTypesInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyDunderSlotsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyExceptClausesOrderInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyExceptionInheritInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyFinalInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyFromFutureImportInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyGlobalUndefinedInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyInconsistentIndentationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyIncorrectDocstringInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyInitNewSignatureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="PyInterpreterInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="PyInterpreterInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyListCreationInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyMethodFirstArgAssignmentInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyMethodMayBeStaticInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyMethodOverridingInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyMethodParametersInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyMissingConstructorInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyNamedTupleInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyNestedDecoratorsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyNewStyleGenericSyntaxInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyNonAsciiCharInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyNoneFunctionAssignmentInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyOldStyleClassesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyOverloadsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyOverridesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="PyPackageRequirementsInspection" enabled="false" level="WARNING" enabled_by_default="false">
|
<inspection_tool class="PyPackageRequirementsInspection" enabled="false" level="WARNING" enabled_by_default="false">
|
||||||
<option name="ignoredPackages">
|
<option name="ignoredPackages">
|
||||||
<value>
|
<value>
|
||||||
@@ -11,5 +57,41 @@
|
|||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PyPandasSeriesToListInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyPep8Inspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyPep8NamingInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyPropertyAccessInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyPropertyDefinitionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyProtectedMemberInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyProtocolInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyRedeclarationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyRedundantParenthesesInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyRelativeImportInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyReturnFromInitInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PySetFunctionToLiteralInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyShadowingBuiltinsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyShadowingNamesInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PySimplifyBooleanCheckInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PySingleQuotedDocstringInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyStatementEffectInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyStringFormatInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyStubPackagesAdvertiser" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyStubPackagesCompatibilityInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PySuperArgumentsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyTestParametrizedInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyTestUnpassedFixtureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyTrailingSemicolonInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyTupleAssignmentBalanceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyTupleItemAssignmentInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyTypeCheckerInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyTypeHintsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyTypedDictInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyUnboundLocalVariableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyUnnecessaryBackslashInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyUnreachableCodeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyUnusedLocalInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyVulnerableApiCodeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PyrightInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
||||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
6
.idea/inspectionProfiles/profiles_settings.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<settings>
|
|
||||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
|
||||||
<version value="1.0" />
|
|
||||||
</settings>
|
|
||||||
</component>
|
|
||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -3,5 +3,5 @@
|
|||||||
<component name="Black">
|
<component name="Black">
|
||||||
<option name="sdkName" value="Python 3.11 (www)" />
|
<option name="sdkName" value="Python 3.11 (www)" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11.2 WSL (Debian): (/home/jerem/.local/share/pdm/venvs/pycord-reactive-views-myCslMhv-3.11/bin/python3)" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (pycord-reactive-views)" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
||||||
3
.idea/pycord-reactive-views.iml
generated
3
.idea/pycord-reactive-views.iml
generated
@@ -3,8 +3,9 @@
|
|||||||
<component name="NewModuleRootManager">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.11.2 WSL (Debian): (/home/jerem/.local/share/pdm/venvs/pycord-reactive-views-myCslMhv-3.11/bin/python3)" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.12 (pycord-reactive-views)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PyDocumentationSettings">
|
<component name="PyDocumentationSettings">
|
||||||
|
|||||||
53
examples/counter.py
Normal file
53
examples/counter.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# ruff: noqa: INP001
|
||||||
|
import os
|
||||||
|
|
||||||
|
import discord
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from pycord_reactive_views import ReactiveButton, ReactiveValue, ReactiveView
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
bot = discord.Bot()
|
||||||
|
|
||||||
|
|
||||||
|
class Counter(ReactiveView):
|
||||||
|
"""A simple counter view that increments a counter when a button is clicked."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.counter = 0
|
||||||
|
self.counter_button = ReactiveButton(
|
||||||
|
label=ReactiveValue(lambda: str(self.counter), "0"),
|
||||||
|
style=ReactiveValue(
|
||||||
|
lambda: discord.ButtonStyle.primary if self.counter % 2 == 0 else discord.ButtonStyle.secondary,
|
||||||
|
discord.ButtonStyle.primary,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.reset_button = ReactiveButton(
|
||||||
|
label="Reset",
|
||||||
|
style=discord.ButtonStyle.danger,
|
||||||
|
disabled=ReactiveValue(lambda: self.counter == 0, default=True),
|
||||||
|
)
|
||||||
|
self.counter_button.callback = self._button_callback
|
||||||
|
self.reset_button.callback = self._reset_callback
|
||||||
|
self.add_item(self.counter_button)
|
||||||
|
self.add_item(self.reset_button)
|
||||||
|
|
||||||
|
async def _button_callback(self, interaction: discord.Interaction) -> None:
|
||||||
|
await interaction.response.defer()
|
||||||
|
self.counter += 1
|
||||||
|
await self.update()
|
||||||
|
|
||||||
|
async def _reset_callback(self, interaction: discord.Interaction) -> None:
|
||||||
|
await interaction.response.defer()
|
||||||
|
self.counter = 0
|
||||||
|
await self.update()
|
||||||
|
|
||||||
|
|
||||||
|
@bot.slash_command()
|
||||||
|
async def counter(ctx: discord.ApplicationContext) -> None:
|
||||||
|
"""Send the counter view."""
|
||||||
|
await Counter().send(ctx)
|
||||||
|
|
||||||
|
|
||||||
|
bot.run(os.getenv("TOKEN"))
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import discord
|
|
||||||
from pycord_reactive_views import ReactiveButton, ReactiveView
|
|
||||||
|
|
||||||
bot = discord.Bot()
|
|
||||||
|
|
||||||
|
|
||||||
class Counter(ReactiveView):
|
|
||||||
"""A simple counter view that increments a counter when a button is clicked."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
self.counter = 0
|
|
||||||
self.counter_button = ReactiveButton(value=lambda: self.counter)
|
|
||||||
self.counter_button.callback = self._button_callback
|
|
||||||
self.add_item(self.counter_button)
|
|
||||||
|
|
||||||
async def _button_callback(self, interaction: discord.Interaction):
|
|
||||||
await interaction.response.defer()
|
|
||||||
self.counter += 1
|
|
||||||
13
pdm.lock
generated
13
pdm.lock
generated
@@ -5,7 +5,7 @@
|
|||||||
groups = ["default", "dev"]
|
groups = ["default", "dev"]
|
||||||
strategy = ["inherit_metadata"]
|
strategy = ["inherit_metadata"]
|
||||||
lock_version = "4.5.0"
|
lock_version = "4.5.0"
|
||||||
content_hash = "sha256:fe19e8fbc71b42f70e7f42def3e0dad93de1c2fcf9e5a252b4fa606c3ea5b2f7"
|
content_hash = "sha256:ce0276a2b471885bb42d49ce0aa48f39564637bfc4dbc67a04a8fc57e0920415"
|
||||||
|
|
||||||
[[metadata.targets]]
|
[[metadata.targets]]
|
||||||
requires_python = ">=3.11"
|
requires_python = ">=3.11"
|
||||||
@@ -224,6 +224,17 @@ files = [
|
|||||||
{file = "py_cord-2.6.0.tar.gz", hash = "sha256:bbc0349542965d05e4b18cc4424136206430a8cc911fda12a0a57df6fdf9cd9c"},
|
{file = "py_cord-2.6.0.tar.gz", hash = "sha256:bbc0349542965d05e4b18cc4424136206430a8cc911fda12a0a57df6fdf9cd9c"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-dotenv"
|
||||||
|
version = "1.0.1"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "Read key-value pairs from a .env file and set them as environment variables"
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
|
||||||
|
{file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff"
|
name = "ruff"
|
||||||
version = "0.5.5"
|
version = "0.5.5"
|
||||||
|
|||||||
137
pyproject.toml
137
pyproject.toml
@@ -33,20 +33,144 @@ name = "pycord_reactive_views"
|
|||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
line-length = 120
|
line-length = 120
|
||||||
target-version = "py311"
|
target-version = "py311"
|
||||||
select = ["E", "F", "I", "N", "W", "B", "C", "D"]
|
fix = true
|
||||||
ignore = ["D100", "D104", "D107"]
|
|
||||||
|
|
||||||
[tool.ruff.pydocstyle]
|
|
||||||
convention = "google"
|
|
||||||
|
|
||||||
[tool.ruff.per-file-ignores]
|
[tool.ruff.per-file-ignores]
|
||||||
"__init__.py" = ["F401"]
|
"__init__.py" = ["F401"]
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["ALL"]
|
||||||
|
|
||||||
|
ignore = [
|
||||||
|
"C90", # mccabe
|
||||||
|
"CPY", # flake8-copyright
|
||||||
|
"EM", # flake8-errmsg
|
||||||
|
"SLF", # flake8-self
|
||||||
|
"ARG", # flake8-unused-arguments
|
||||||
|
"TD", # flake8-todos
|
||||||
|
"FIX", # flake8-fixme
|
||||||
|
"PD", # pandas-vet
|
||||||
|
|
||||||
|
"D100", # Missing docstring in public module
|
||||||
|
"D104", # Missing docstring in public package
|
||||||
|
"D105", # Missing docstring in magic method
|
||||||
|
"D106", # Missing docstring in public nested class
|
||||||
|
"D107", # Missing docstring in __init__
|
||||||
|
"D203", # Blank line required before class docstring
|
||||||
|
"D213", # Multi-line summary should start at the second line (incompatible with D212)
|
||||||
|
"D301", # Use r""" if any backslashes in a docstring
|
||||||
|
"D401", # First line of docstring should be in imperative mood
|
||||||
|
"D404", # First word of the docstring should not be "This"
|
||||||
|
"D405", # Section name should be properly capitalized
|
||||||
|
"D406", # Section name should end with a newline
|
||||||
|
"D407", # Missing dashed underline after section
|
||||||
|
"D408", # Section underline should be in the line following the section's name
|
||||||
|
"D409", # Section underline should match the length of its name
|
||||||
|
"D410", # Missing blank line after section
|
||||||
|
"D411", # Missing blank line before section
|
||||||
|
"D412", # No blank lines allowed between a section header and its content
|
||||||
|
"D413", # Missing blank line after last section
|
||||||
|
"D414", # Section has no content
|
||||||
|
"D416", # Section name should end with a colon
|
||||||
|
"D417", # Missing argument description in the docstring
|
||||||
|
|
||||||
|
"ANN101", # Missing type annotation for self in method
|
||||||
|
"ANN102", # Missing type annotation for cls in classmethod
|
||||||
|
"ANN204", # Missing return type annotation for special method
|
||||||
|
"ANN401", # Dynamically typed expressions (typing.Any) disallowed
|
||||||
|
|
||||||
|
"SIM102", # use a single if statement instead of nested if statements
|
||||||
|
"SIM108", # Use ternary operator {contents} instead of if-else-block
|
||||||
|
|
||||||
|
"G001", # Logging statement uses str.format
|
||||||
|
"G004", # Logging statement uses f-string
|
||||||
|
"G003", # Logging statement uses +
|
||||||
|
|
||||||
|
"B904", # Raise without `from` within an `except` clause
|
||||||
|
|
||||||
|
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
|
||||||
|
"PLR2004", # Using unnamed numerical constants
|
||||||
|
"PGH003", # Using specific rule codes in type ignores
|
||||||
|
"E731", # Don't asign a lambda expression, use a def
|
||||||
|
"S311", # Use `secrets` for random number generation, not `random`
|
||||||
|
"TRY003", # Avoid specifying long messages outside the exception class
|
||||||
|
|
||||||
|
# Redundant rules with ruff-format:
|
||||||
|
"E111", # Indentation of a non-multiple of 4 spaces
|
||||||
|
"E114", # Comment with indentation of a non-multiple of 4 spaces
|
||||||
|
"E117", # Cheks for over-indented code
|
||||||
|
"D206", # Checks for docstrings indented with tabs
|
||||||
|
"D300", # Checks for docstring that use ''' instead of """
|
||||||
|
"Q000", # Checks of inline strings that use wrong quotes (' instead of ")
|
||||||
|
"Q001", # Multiline string that use wrong quotes (''' instead of """)
|
||||||
|
"Q002", # Checks for docstrings that use wrong quotes (''' instead of """)
|
||||||
|
"Q003", # Checks for avoidable escaped quotes ("\"" -> '"')
|
||||||
|
"COM812", # Missing trailing comma (in multi-line lists/tuples/...)
|
||||||
|
"COM819", # Prohibited trailing comma (in single-line lists/tuples/...)
|
||||||
|
"ISC001", # Single line implicit string concatenation ("hi" "hey" -> "hihey")
|
||||||
|
"ISC002", # Multi line implicit string concatenation
|
||||||
|
|
||||||
|
"DOC501"
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.ruff.lint.isort]
|
||||||
|
order-by-type = false
|
||||||
|
case-sensitive = true
|
||||||
|
combine-as-imports = true
|
||||||
|
|
||||||
|
# Redundant rules with ruff-format
|
||||||
|
force-single-line = false # forces all imports to appear on their own line
|
||||||
|
force-wrap-aliases = false # Split imports with multiple members and at least one alias
|
||||||
|
lines-after-imports = -1 # The number of blank lines to place after imports
|
||||||
|
lines-between-types = 0 # Number of lines to place between "direct" and import from imports
|
||||||
|
split-on-trailing-comma = false # if last member of multiline import has a comma, don't fold it to single line
|
||||||
|
|
||||||
|
[tool.ruff.lint.pylint]
|
||||||
|
max-args = 15
|
||||||
|
max-branches = 15
|
||||||
|
max-locals = 15
|
||||||
|
max-nested-blocks = 5
|
||||||
|
max-returns = 8
|
||||||
|
max-statements = 75
|
||||||
|
|
||||||
|
[tool.ruff.lint.per-file-ignores]
|
||||||
|
"tests/**.py" = [
|
||||||
|
"ANN", # annotations
|
||||||
|
"D", # docstrings
|
||||||
|
"S101", # Use of assert
|
||||||
|
]
|
||||||
|
".github/scripts/**.py" = [
|
||||||
|
"INP001", # Implicit namespace package
|
||||||
|
]
|
||||||
|
"alembic-migrations/env.py" = [
|
||||||
|
"INP001", # Implicit namespace package
|
||||||
|
]
|
||||||
|
"alembic-migrations/versions/*" = [
|
||||||
|
"INP001", # Implicit namespace package
|
||||||
|
"D103", # Missing docstring in public function
|
||||||
|
"D400", # First line should end with a period
|
||||||
|
"D415", # First line should end with a period, question mark, or exclamation point
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.ruff.format]
|
||||||
|
line-ending = "lf"
|
||||||
|
|
||||||
[tool.basedpyright]
|
[tool.basedpyright]
|
||||||
include = ["src"]
|
include = ["src"]
|
||||||
exclude = ["**/__pycache__"]
|
exclude = ["**/__pycache__"]
|
||||||
venv = "env311"
|
venv = "env311"
|
||||||
pythonVersion = "3.11"
|
pythonPlatform = "All"
|
||||||
|
pythonVersion = "3.12"
|
||||||
|
typeCheckingMode = "all"
|
||||||
|
|
||||||
|
reportAny = false
|
||||||
|
reportUnusedCallResult = false
|
||||||
|
|
||||||
|
reportUnknownArgumentType = false
|
||||||
|
reportUnknownVariableType = false
|
||||||
|
reportUnknownMemberType = false
|
||||||
|
reportUnknownParameterType = false
|
||||||
|
reportUnknownLambdaType = false
|
||||||
|
|
||||||
[tool.pdm]
|
[tool.pdm]
|
||||||
distribution = true
|
distribution = true
|
||||||
@@ -54,6 +178,7 @@ distribution = true
|
|||||||
dev = [
|
dev = [
|
||||||
"basedpyright>=1.15.0",
|
"basedpyright>=1.15.0",
|
||||||
"ruff>=0.5.5",
|
"ruff>=0.5.5",
|
||||||
|
"python-dotenv>=1.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
This directoy stores each Python Package.
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
from .components import ReactiveButton
|
||||||
|
from .utils import ReactiveValue
|
||||||
|
from .view import ReactiveView
|
||||||
|
|
||||||
|
__all__ = ["ReactiveButton", "ReactiveView", "ReactiveValue"]
|
||||||
|
|||||||
53
src/pycord_reactive_views/components.py
Normal file
53
src/pycord_reactive_views/components.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import discord
|
||||||
|
|
||||||
|
from .utils import MaybeReactiveValue, ReactiveValue, is_reactive
|
||||||
|
|
||||||
|
|
||||||
|
class Reactive:
|
||||||
|
"""A class that can be used with reactive values."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.reactives: dict[str, ReactiveValue[Any]] = {}
|
||||||
|
self.super_kwargs: dict[str, Any] = {}
|
||||||
|
|
||||||
|
def add_reactive(self, key: str, value: MaybeReactiveValue[Any]) -> None:
|
||||||
|
"""Add a reactive value to the view."""
|
||||||
|
if is_reactive(value):
|
||||||
|
self.reactives[key] = value
|
||||||
|
if value.default:
|
||||||
|
setattr(self, key, value.default)
|
||||||
|
else:
|
||||||
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
async def refresh(self) -> None:
|
||||||
|
"""Refresh the reactive values."""
|
||||||
|
for key, value in self.reactives.items():
|
||||||
|
setattr(self, key, await value())
|
||||||
|
|
||||||
|
|
||||||
|
class ReactiveButton(discord.ui.Button, Reactive): # pyright: ignore[reportUnsafeMultipleInheritance,reportMissingTypeArgument]
|
||||||
|
"""A button that can be used with reactive values."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
style: MaybeReactiveValue[discord.ButtonStyle] = discord.ButtonStyle.secondary,
|
||||||
|
label: MaybeReactiveValue[str | None] = None,
|
||||||
|
disabled: MaybeReactiveValue[bool] = False,
|
||||||
|
custom_id: str | None = None,
|
||||||
|
url: MaybeReactiveValue[str | None] = None,
|
||||||
|
emoji: MaybeReactiveValue[str | discord.Emoji | discord.PartialEmoji | None] = None,
|
||||||
|
sku_id: int | None = None,
|
||||||
|
row: MaybeReactiveValue[int | None] = None,
|
||||||
|
):
|
||||||
|
discord.ui.Button.__init__(self)
|
||||||
|
Reactive.__init__(self)
|
||||||
|
self.add_reactive("style", style)
|
||||||
|
self.add_reactive("label", label)
|
||||||
|
self.add_reactive("disabled", disabled)
|
||||||
|
self.add_reactive("url", url)
|
||||||
|
self.add_reactive("emoji", emoji)
|
||||||
|
self.add_reactive("row", row)
|
||||||
3
src/pycord_reactive_views/utils/__init__.py
Normal file
3
src/pycord_reactive_views/utils/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from .reactivity import MaybeReactiveValue, ReactiveValue, is_reactive
|
||||||
|
|
||||||
|
__all__ = ["ReactiveValue", "MaybeReactiveValue", "is_reactive"]
|
||||||
44
src/pycord_reactive_views/utils/reactivity.py
Normal file
44
src/pycord_reactive_views/utils/reactivity.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
from collections.abc import Awaitable, Callable
|
||||||
|
from inspect import isawaitable
|
||||||
|
from typing import TypeGuard, TypeVar
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
|
class Unset:
|
||||||
|
"""A class to represent an unset value."""
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
UNSET = Unset()
|
||||||
|
|
||||||
|
|
||||||
|
class ReactiveValue[T]:
|
||||||
|
"""A value that can be a constant, a callable, or an async callable."""
|
||||||
|
|
||||||
|
def __init__(self, func: Callable[[], T] | Callable[[], Awaitable[T]], default: T | Unset = UNSET):
|
||||||
|
"""Create a new reactive value."""
|
||||||
|
self._func: Callable[[], T] | Callable[[], Awaitable[T]] = func
|
||||||
|
self.default = default
|
||||||
|
|
||||||
|
async def __call__(self) -> T:
|
||||||
|
"""Call the function and return the value.
|
||||||
|
|
||||||
|
:raises TypeError: If the value is not callable
|
||||||
|
"""
|
||||||
|
if callable(self._func):
|
||||||
|
ret = self._func()
|
||||||
|
if isawaitable(ret):
|
||||||
|
return await ret
|
||||||
|
return ret
|
||||||
|
raise TypeError("ReactiveValue must be a callable")
|
||||||
|
|
||||||
|
|
||||||
|
MaybeReactiveValue = T | ReactiveValue[T]
|
||||||
|
|
||||||
|
|
||||||
|
def is_reactive(value: MaybeReactiveValue[T]) -> TypeGuard[ReactiveValue[T]]:
|
||||||
|
"""Check if a value is a reactive value."""
|
||||||
|
return isinstance(value, ReactiveValue)
|
||||||
57
src/pycord_reactive_views/view.py
Normal file
57
src/pycord_reactive_views/view.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
from typing import Self, override
|
||||||
|
|
||||||
|
import discord
|
||||||
|
|
||||||
|
from .components import ReactiveButton
|
||||||
|
|
||||||
|
|
||||||
|
class ReactiveView(discord.ui.View):
|
||||||
|
"""A view that can be used with reactive components."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
timeout: float | None = 180.0,
|
||||||
|
disable_on_timeout: bool = False,
|
||||||
|
):
|
||||||
|
super().__init__(timeout=timeout, disable_on_timeout=disable_on_timeout)
|
||||||
|
self._reactives: list[ReactiveButton] = []
|
||||||
|
|
||||||
|
@override
|
||||||
|
def add_item(self, item: discord.ui.Item[Self]) -> None:
|
||||||
|
if isinstance(item, ReactiveButton):
|
||||||
|
self._reactives.append(item)
|
||||||
|
super().add_item(item)
|
||||||
|
|
||||||
|
async def _get_embed(self) -> discord.Embed | None:
|
||||||
|
"""Get the discord embed to be displayed in the message."""
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def _get_embeds(self) -> list[discord.Embed]:
|
||||||
|
"""Get the discord embeds to be displayed in the message."""
|
||||||
|
return []
|
||||||
|
|
||||||
|
async def _get_content(self) -> str | None:
|
||||||
|
"""Get the content to be displayed in the message."""
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def update(self) -> None:
|
||||||
|
"""Update the view with new components.
|
||||||
|
|
||||||
|
:raises ValueError: If the view has no message (not yet sent?), can't update
|
||||||
|
"""
|
||||||
|
for reactive in self._reactives:
|
||||||
|
await reactive.refresh()
|
||||||
|
if not self.message:
|
||||||
|
raise ValueError("View has no message (not yet sent?), can't refresh")
|
||||||
|
if embeds := await self._get_embeds():
|
||||||
|
await self.message.edit(content=await self._get_content(), embeds=embeds, view=self)
|
||||||
|
else:
|
||||||
|
await self.message.edit(content=await self._get_content(), view=self)
|
||||||
|
|
||||||
|
async def send(self, ctx: discord.ApplicationContext | discord.Interaction) -> None:
|
||||||
|
"""Send the view to a context."""
|
||||||
|
if embeds := await self._get_embeds():
|
||||||
|
await ctx.respond(content=await self._get_content(), embeds=embeds, view=self)
|
||||||
|
else:
|
||||||
|
await ctx.respond(content=await self._get_content(), view=self)
|
||||||
Reference in New Issue
Block a user