aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.flake82
-rw-r--r--.github/FUNDING.yml2
-rw-r--r--.pre-commit-config.yaml15
-rw-r--r--CONTRIBUTING.md151
-rw-r--r--Pipfile5
-rw-r--r--Pipfile.lock71
-rwxr-xr-xmanage.py1
-rw-r--r--pydis_site/apps/api/admin.py6
-rw-r--r--pydis_site/apps/api/migrations/0036_removing_snake_apis.py25
-rw-r--r--pydis_site/apps/api/migrations/0038_merge_20190719_1817.py14
-rw-r--r--pydis_site/apps/api/models/__init__.py4
-rw-r--r--pydis_site/apps/api/models/bot/__init__.py4
-rw-r--r--pydis_site/apps/api/models/bot/bot_setting.py1
-rw-r--r--pydis_site/apps/api/models/bot/documentation_link.py1
-rw-r--r--pydis_site/apps/api/models/bot/infraction.py1
-rw-r--r--pydis_site/apps/api/models/bot/off_topic_channel_name.py1
-rw-r--r--pydis_site/apps/api/models/bot/reminder.py1
-rw-r--r--pydis_site/apps/api/models/bot/role.py1
-rw-r--r--pydis_site/apps/api/models/bot/snake_fact.py18
-rw-r--r--pydis_site/apps/api/models/bot/snake_idiom.py18
-rw-r--r--pydis_site/apps/api/models/bot/snake_name.py25
-rw-r--r--pydis_site/apps/api/models/bot/special_snake.py28
-rw-r--r--pydis_site/apps/api/models/bot/tag.py5
-rw-r--r--pydis_site/apps/api/models/bot/user.py1
-rw-r--r--pydis_site/apps/api/models/utils.py1
-rw-r--r--pydis_site/apps/api/serializers.py46
-rw-r--r--pydis_site/apps/api/tests/test_models.py12
-rw-r--r--pydis_site/apps/api/tests/test_snake_names.py67
-rw-r--r--pydis_site/apps/api/urls.py23
-rw-r--r--pydis_site/apps/api/views.py1
-rw-r--r--pydis_site/apps/api/viewsets/__init__.py4
-rw-r--r--pydis_site/apps/api/viewsets/bot/__init__.py4
-rw-r--r--pydis_site/apps/api/viewsets/bot/infraction.py5
-rw-r--r--pydis_site/apps/api/viewsets/bot/nomination.py1
-rw-r--r--pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py4
-rw-r--r--pydis_site/apps/api/viewsets/bot/snake_fact.py30
-rw-r--r--pydis_site/apps/api/viewsets/bot/snake_idiom.py30
-rw-r--r--pydis_site/apps/api/viewsets/bot/snake_name.py69
-rw-r--r--pydis_site/apps/api/viewsets/bot/special_snake.py33
-rw-r--r--pydis_site/apps/home/models/repository_metadata.py1
-rw-r--r--pydis_site/apps/home/templatetags/extra_filters.py1
-rw-r--r--pydis_site/apps/home/templatetags/wiki_extra.py9
-rw-r--r--pydis_site/apps/home/tests/test_repodata_helpers.py6
-rw-r--r--pydis_site/apps/home/views/home.py8
-rw-r--r--pydis_site/utils/resources.py5
45 files changed, 233 insertions, 528 deletions
diff --git a/.flake8 b/.flake8
index e2face09..4157e507 100644
--- a/.flake8
+++ b/.flake8
@@ -4,7 +4,7 @@ ignore=
# Missing Docstrings
D100,D104,D107,
# Docstring Whitespace
- D202,D203,D204,D212,D214,D215,
+ D203,D212,D214,D215,
# Docstring Quotes
D301,D302,
# Docstring Content
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..6d9919ef
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,2 @@
+patreon: python_discord
+custom: https://www.redbubble.com/people/pythondiscord
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 00000000..c20c0d85
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,15 @@
+repos:
+- repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v2.2.3
+ hooks:
+ - id: flake8
+ exclude: migrations/
+ additional_dependencies: [
+ "pydocstyle<4.0",
+ "flake8-bandit",
+ "flake8-bugbear",
+ "flake8-docstrings",
+ "flake8-import-order ",
+ "flake8-string-format",
+ "flake8-tidy-imports"
+ ] \ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3a9b1dc8..052bf731 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,69 +1,106 @@
# Contributing to one of our projects
-Our projects are open-source, and are deployed as commits are
-pushed to the `master` branch on each repository. We've created
-a set of guidelines here in order to keep everything clean and
-in working order. Please note that contributions may be rejected
-on the basis of a contributor failing to follow the guidelines.
+Our projects are open-source and are automatically deployed whenever commits are pushed to the `master` branch on each repository, so we've created a set of guidelines in order to keep everything clean and in working order.
+
+Note that contributions may be rejected on the basis of a contributor failing to follow these guidelines.
## Rules
1. **No force-pushes** or modifying the Git history in any way.
-1. If you have direct access to the repository,
- **create a branch for your changes** and
- create a merge request for that branch.
- If not, fork it and work on a separate branch there.
- * Some repositories require this and will reject
- any direct pushes to `master`. Make this a habit!
-1. If someone is working on a merge request,
- **do not open your own merge request for the same task**.
- Instead, leave some comments on the existing merge request.
- Communication is key, and there's no point in two separate
- implementations of the same thing.
- * One option is to fork the other contributor's repository,
- and submit your changes to their branch with your own merge
- request. If you do this, we suggest following these guidelines
- when interacting with their repository as well.
-1. **Adhere to the prevailing code style**, which we enforce using
- [flake8](http://flake8.pycqa.org/en/latest/index.html).
- * Additionally, run `flake8` against your code before
- you push it. Your commit will be rejected by the build server
- if it fails to lint.
- * Keep the coverage at 100%. Your reason not to do so is not good enough.
- * No pushes to `master` without a really really good reason.
- If you're unsure, it is not good enough.
- * Update the `CHANGELOG.md` file as necessary.
- Maintainers will tag releases as appropriate.
-1. **Don't fight the framework**. Every framework has its flaws, but
- the frameworks we've picked out have been carefully
- chosen for their particular merits. If you can avoid it,
- please resist reimplementing swathes of framework logic - the
- work has already been done for you!
-1. **Work as a team** and cooperate where possible. Keep things
- friendly, and help each other out - these are shared
- projects, and nobody likes to have their feet trodden on.
-1. **Internal projects are internal**. As a contributor,
- you have access to information that the rest of the server
- does not. With this trust comes responsibility - do not
- release any information you have learned as a result of
- your contributor position. We are very strict about
- announcing things at specific times, and many staff members
- will not appreciate a disruption of the announcement schedule.
-
-Above all, the needs of our community should come before the wants
-of an individual. Work together, build solutions to problems and
-try to do so in a way that people can learn from easily.
-Abuse of our trust may result in the loss of your
-Contributor role, especially in relation to Rule 7.
+2. If you have direct access to the repository, **create a branch for your changes** and create a pull request for that branch. If not, create a branch on a fork of the repository and create a pull request from there.
+ * It's common practice for a repository to reject direct pushes to `master`, so make branching a habit!
+3. **Adhere to the prevailing code style**, which we enforce using [flake8](http://flake8.pycqa.org/en/latest/index.html).
+ * Run `flake8` against your code **before** you push it. Your commit will be rejected by the build server if it fails to lint.
+ * [Git Hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) are a powerful tool that can be a daunting to set up. Fortunately, [`pre-commit`](https://github.com/pre-commit/pre-commit) abstracts this process away from you and is provided as a dev dependency for this project. Run `pipenv run precommit` when setting up the project and you'll never have to worry about breaking the build for linting errors.
+4. **Make great commits**. A well structured git log is key to a project's maintainability; it efficiently provides insight into when and *why* things were done for future maintainers of the project.
+ * Commits should be as narrow in scope as possible. Commits that span hundreds of lines across multiple unrelated functions and/or files are very hard for maintainers to follow. After about a week they'll probably be hard for you to follow too.
+ * Try to avoid making minor commits for fixing typos or linting errors. Since you've already set up a pre-commit hook to run `flake8` before a commit, you shouldn't be committing linting issues anyway.
+ * A more in-depth guide to writing great commit messages can be found in Chris Beam's [*How to Write a Git Commit Message*](https://chris.beams.io/posts/git-commit/)
+5. **Avoid frequent pushes to the main repository**. This goes for PRs opened against your fork as well. Our test build pipelines are triggered every time a push to the repository (or PR) is made. Try to batch your commits until you've finished working for that session, or you've reached a point where collaborators need your commits to continue their own work. This also provides you the opportunity to amend commits for minor changes rather than having to commit them on their own because you've already pushed.
+ * This includes merging master into your branch. Try to leave merging from master for after your PR passes review; a maintainer will bring your PR up to date before merging. Exceptions to this include: resolving merge conflicts, needing something that was pushed to master for your branch, or something was pushed to master that could potentionally affect the functionality of what you're writing.
+6. **Don't fight the framework**. Every framework has its flaws, but the frameworks we've picked out have been carefully chosen for their particular merits. If you can avoid it, please resist reimplementing swathes of framework logic - the work has already been done for you!
+7. If someone is working on an issue or pull request, **do not open your own pull request for the same task**. Instead, collaborate with the author(s) of the existing pull request. Duplicate PRs opened without communicating with the other author(s) and/or PyDis staff will be closed. Communication is key, and there's no point in two separate implementations of the same thing.
+ * One option is to fork the other contributor's repository and submit your changes to their branch with your own pull request. We suggest following these guidelines when interacting with their repository as well.
+ * The author(s) of inactive PRs and claimed issues will be be pinged after a week of inactivity for an update. Continued inactivity may result in the issue being released back to the community and/or PR closure.
+8. **Work as a team** and collaborate wherever possible. Keep things friendly and help each other out - these are shared projects and nobody likes to have their feet trodden on.
+9. **Internal projects are internal**. As a contributor, you have access to information that the rest of the server does not. With this trust comes responsibility - do not release any information you have learned as a result of your contributor position. We are very strict about announcing things at specific times, and many staff members will not appreciate a disruption of the announcement schedule.
+10. All API changes **must be validated against the bot** before PRing. Please don't leave this for reviewers to discover. Guides for setting up the developer environment can be [found below](#developer-environment).
+11. All static content, such as images or audio, **must be licensed for open public use**.
+ * Static content must be hosted by a service designed to do so. Failing to do so is known as "leeching" and is frowned upon, as it generates extra bandwidth costs to the host without providing benefit. It would be best if appropriately licensed content is added to the repository itself so it can be served by PyDis' infrastructure.
+
+Above all, the needs of our community should come before the wants of an individual. Work together, build solutions to problems and try to do so in a way that people can learn from easily. Abuse of our trust may result in the loss of your Contributor role, especially in relation to Rule 7.
## Changes to this arrangement
-All projects evolve over time, and this contribution
-guide is no different. This document may also be subject to pull
-requests or changes by contributors, where you
-believe you have something valuable to add or change.
+All projects evolve over time, and this contribution guide is no different. This document is open to pull requests or changes by contributors. If you believe you have something valuable to add or change, please don't hesitate to do so in a PR.
+
+## Supplemental Information
+### Developer Environment
+Instructions for setting up environments for both the site and the bot can be found on the PyDis Wiki:
+ * [Site](https://wiki.pythondiscord.com/wiki/contributing/project/site)
+ * [Bot](https://wiki.pythondiscord.com/wiki/contributing/project/bot)
+
+When pulling down changes from GitHub, remember to sync your environment using `pipenv sync --dev` to ensure you're using the most up-to-date versions the project's dependencies.
+
+### Type Hinting
+[PEP 484](https://www.python.org/dev/peps/pep-0484/) formally specifies type hints for Python functions, added to the Python Standard Library in version 3.5. Type hints are recognized by most modern code editing tools and provide useful insight into both the input and output types of a function, preventing the user from having to go through the codebase to determine these types.
+
+For example:
+
+```py
+def foo(input_1: int, input_2: dict) -> bool:
+```
+
+Tells us that `foo` accepts an `int` and a `dict` and returns a `bool`.
+
+All function declarations should be type hinted in code contributed to the PyDis organization.
+
+For more information, see *[PEP 483](https://www.python.org/dev/peps/pep-0483/) - The Theory of Type Hints* and Python's documentation for the [`typing`](https://docs.python.org/3/library/typing.html) module.
+
+### AutoDoc Formatting Directives
+Many documentation packages provide support for automatic documentation generation from the codebase's docstrings. These tools utilize special formatting directives to enable richer formatting in the generated documentation.
+
+For example:
+
+```py
+def foo(bar: int, baz: dict=None) -> bool:
+ """
+ Does some things with some stuff.
+
+ :param bar: Some input
+ :param baz: Optional, some other input
+
+ :return: Some boolean
+ """
+```
+
+Since PyDis does not utilize automatic documentation generation, use of this syntax should not be used in code contributed to the organization. Should the purpose and type of the input variables not be easily discernable from the variable name and type annotation, a prose explanation can be used. Explicit references to variables, functions, classes, etc. should be wrapped with backticks (`` ` ``).
+
+For example, the above docstring would become:
+
+```py
+def foo(bar: int, baz: dict=None) -> bool:
+ """
+ Does some things with some stuff.
+
+ This function takes an index, `bar` and checks for its presence in the database `baz`, passed as a dictionary. Returns `False` if `baz` is not passed.
+ """
+```
+
+### Logging Levels
+The project currently defines [`logging`](https://docs.python.org/3/library/logging.html) levels as follows:
+* **TRACE:** Use this for tracing every step of a complex process. That way we can see which step of the process failed. Err on the side of verbose. **Note:** This is a PyDis-implemented logging level.
+* **DEBUG:** Someone is interacting with the application, and the application is behaving as expected.
+* **INFO:** Something completely ordinary happened. Like a cog loading during startup.
+* **WARNING:** Someone is interacting with the application in an unexpected way or the application is responding in an unexpected way, but without causing an error.
+* **ERROR:** An error that affects the specific part that is being interacted with
+* **CRITICAL:** An error that affects the whole application.
+
+### Work in Progress (WIP) PRs
+Github [has introduced a new PR feature](https://github.blog/2019-02-14-introducing-draft-pull-requests/) that allows the PR author to mark it as a WIP. This provides both a visual and functional indicator that the contents of the PR are in a draft state and not yet ready for formal review.
+
+This feature should be utilized in place of the traditional method of prepending `[WIP]` to the PR title.
## Footnotes
-This document was inspired by the
-[Glowstone contribution guidelines](https://github.com/GlowstoneMC/Glowstone/blob/dev/docs/CONTRIBUTING.md).
+This document was inspired by the [Glowstone contribution guidelines](https://github.com/GlowstoneMC/Glowstone/blob/dev/docs/CONTRIBUTING.md). \ No newline at end of file
diff --git a/Pipfile b/Pipfile
index 036f079c..6d76831b 100644
--- a/Pipfile
+++ b/Pipfile
@@ -7,6 +7,7 @@ verify_ssl = true
flake8 = "~=3.7.7"
flake8-bandit = "==1.0.2"
flake8-bugbear = "~=19.3.0"
+flake8-docstrings = "~=1.3.0"
flake8-import-order = "~=0.18.1"
flake8-string-format = "~=0.2.3"
flake8-tidy-imports = "~=2.0.0"
@@ -14,8 +15,8 @@ mccabe = "~=0.6.1"
pep8-naming = "~=0.8.2"
coverage = "~=4.5.3"
unittest-xml-reporting = "~=2.5.1"
-flake8-docstrings = "~=1.3.0"
pydocstyle = "==3.0.0"
+pre-commit = "~=1.17.0"
[packages]
django = "~=2.2"
@@ -41,3 +42,5 @@ python_version = "3.7"
makemigrations = "python manage.py makemigrations"
django_shell = "python manage.py shell"
test = "python manage.py test"
+lint = "flake8 pydis_site"
+precommit = "pre-commit install"
diff --git a/Pipfile.lock b/Pipfile.lock
index b40b06c1..963dccab 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "2f1eaa80a71489a59f71001ad4af39e8e570f8d7ebca33b475d2c530811ad084"
+ "sha256": "bfe5ac803d58497ad94fa877fcb502f96176167924d8c3ebfcc73aa463e468fd"
},
"pipfile-spec": 6,
"requires": {
@@ -237,6 +237,13 @@
}
},
"develop": {
+ "aspy.yaml": {
+ "hashes": [
+ "sha256:463372c043f70160a9ec950c3f1e4c3a82db5fca01d334b6bc89c7164d744bdc",
+ "sha256:e7c742382eff2caed61f87a39d13f99109088e5e93f04d76eb8d4b28aa143f45"
+ ],
+ "version": "==1.3.0"
+ },
"attrs": {
"hashes": [
"sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79",
@@ -251,6 +258,13 @@
],
"version": "==1.6.2"
},
+ "cfgv": {
+ "hashes": [
+ "sha256:32edbe09de6f4521224b87822103a8c16a614d31a894735f7a5b3bcf0eb3c37e",
+ "sha256:3bd31385cd2bebddbba8012200aaf15aa208539f1b33973759b4d02fc2148da5"
+ ],
+ "version": "==2.0.0"
+ },
"coverage": {
"hashes": [
"sha256:3684fabf6b87a369017756b551cef29e505cb155ddb892a7a29277b978da88b9",
@@ -297,11 +311,11 @@
},
"flake8": {
"hashes": [
- "sha256:859996073f341f2670741b51ec1e67a01da142831aa1fdc6242dbf88dffbe661",
- "sha256:a796a115208f5c03b18f332f7c11729812c8c3ded6c46319c59b53efd3819da8"
+ "sha256:19241c1cbc971b9962473e4438a2ca19749a7dd002dd1a946eaba171b4114548",
+ "sha256:8e9dfa3cecb2400b3738a42c54c3043e821682b9c840b0448c0503f781130696"
],
"index": "pypi",
- "version": "==3.7.7"
+ "version": "==3.7.8"
},
"flake8-bandit": {
"hashes": [
@@ -372,6 +386,20 @@
],
"version": "==2.1.11"
},
+ "identify": {
+ "hashes": [
+ "sha256:0a11379b46d06529795442742a043dc2fa14cd8c995ae81d1febbc5f1c014c87",
+ "sha256:43a5d24ffdb07bc7e21faf68b08e9f526a1f41f0056073f480291539ef961dfd"
+ ],
+ "version": "==1.4.5"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:6dfd58dfe281e8d240937776065dd3624ad5469c835248219bd16cf2e12dbeb7",
+ "sha256:cb6ee23b46173539939964df59d3d72c3e0c1b5d54b84f1d8a7e912fe43612db"
+ ],
+ "version": "==0.18"
+ },
"mccabe": {
"hashes": [
"sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
@@ -380,6 +408,12 @@
"index": "pypi",
"version": "==0.6.1"
},
+ "nodeenv": {
+ "hashes": [
+ "sha256:ad8259494cf1c9034539f6cced78a1da4840a4b157e23640bc4a0c0546b0cb7a"
+ ],
+ "version": "==1.3.3"
+ },
"pbr": {
"hashes": [
"sha256:36ebd78196e8c9588c972f5571230a059ff83783fabbbbedecc07be263ccd7e6",
@@ -395,6 +429,14 @@
"index": "pypi",
"version": "==0.8.2"
},
+ "pre-commit": {
+ "hashes": [
+ "sha256:92e406d556190503630fd801958379861c94884693a032ba66629d0351fdccd4",
+ "sha256:cccc39051bc2457b0c0f7152a411f8e05e3ba2fe1a5613e4ee0833c1c1985ce3"
+ ],
+ "index": "pypi",
+ "version": "==1.17.0"
+ },
"pycodestyle": {
"hashes": [
"sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56",
@@ -462,6 +504,13 @@
],
"version": "==1.30.1"
},
+ "toml": {
+ "hashes": [
+ "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
+ "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
+ ],
+ "version": "==0.10.0"
+ },
"unittest-xml-reporting": {
"hashes": [
"sha256:140982e4b58e4052d9ecb775525b246a96bfc1fc26097806e05ea06e9166dd6c",
@@ -469,6 +518,20 @@
],
"index": "pypi",
"version": "==2.5.1"
+ },
+ "virtualenv": {
+ "hashes": [
+ "sha256:b7335cddd9260a3dd214b73a2521ffc09647bde3e9457fcca31dc3be3999d04a",
+ "sha256:d28ca64c0f3f125f59cabf13e0a150e1c68e5eea60983cc4395d88c584495783"
+ ],
+ "version": "==16.6.1"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:4970c3758f4e89a7857a973b1e2a5d75bcdc47794442f2e2dd4fe8e0466e809a",
+ "sha256:8a5712cfd3bb4248015eb3b0b3c54a5f6ee3f2425963ef2a0125b8bc40aafaec"
+ ],
+ "version": "==0.5.2"
}
}
}
diff --git a/manage.py b/manage.py
index 37cca124..b257ea65 100755
--- a/manage.py
+++ b/manage.py
@@ -6,7 +6,6 @@ import sys
# Separate definition to ease calling this in other scripts.
def main():
"""Entry point for Django management script."""
-
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pydis_site.settings')
try:
from django.core.management import execute_from_command_line
diff --git a/pydis_site/apps/api/admin.py b/pydis_site/apps/api/admin.py
index a5b75fa9..c3784317 100644
--- a/pydis_site/apps/api/admin.py
+++ b/pydis_site/apps/api/admin.py
@@ -5,8 +5,6 @@ from .models import (
DocumentationLink, Infraction,
MessageDeletionContext, Nomination,
OffTopicChannelName, Role,
- SnakeFact, SnakeIdiom,
- SnakeName, SpecialSnake,
Tag, User
)
@@ -19,9 +17,5 @@ admin.site.register(MessageDeletionContext)
admin.site.register(Nomination)
admin.site.register(OffTopicChannelName)
admin.site.register(Role)
-admin.site.register(SnakeFact)
-admin.site.register(SnakeIdiom)
-admin.site.register(SnakeName)
-admin.site.register(SpecialSnake)
admin.site.register(Tag)
admin.site.register(User)
diff --git a/pydis_site/apps/api/migrations/0036_removing_snake_apis.py b/pydis_site/apps/api/migrations/0036_removing_snake_apis.py
new file mode 100644
index 00000000..624afc95
--- /dev/null
+++ b/pydis_site/apps/api/migrations/0036_removing_snake_apis.py
@@ -0,0 +1,25 @@
+# Generated by Django 2.2.3 on 2019-07-10 09:07
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0035_create_table_log_entry'),
+ ]
+
+ operations = [
+ migrations.DeleteModel(
+ name='SnakeFact',
+ ),
+ migrations.DeleteModel(
+ name='SnakeIdiom',
+ ),
+ migrations.DeleteModel(
+ name='SnakeName',
+ ),
+ migrations.DeleteModel(
+ name='SpecialSnake',
+ ),
+ ]
diff --git a/pydis_site/apps/api/migrations/0038_merge_20190719_1817.py b/pydis_site/apps/api/migrations/0038_merge_20190719_1817.py
new file mode 100644
index 00000000..532bcb70
--- /dev/null
+++ b/pydis_site/apps/api/migrations/0038_merge_20190719_1817.py
@@ -0,0 +1,14 @@
+# Generated by Django 2.2.3 on 2019-07-19 22:17
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0037_nomination_field_name_change'),
+ ('api', '0036_removing_snake_apis'),
+ ]
+
+ operations = [
+ ]
diff --git a/pydis_site/apps/api/models/__init__.py b/pydis_site/apps/api/models/__init__.py
index 4645bda2..a7eccb04 100644
--- a/pydis_site/apps/api/models/__init__.py
+++ b/pydis_site/apps/api/models/__init__.py
@@ -9,10 +9,6 @@ from .bot import ( # noqa
OffTopicChannelName,
Reminder,
Role,
- SnakeFact,
- SnakeIdiom,
- SnakeName,
- SpecialSnake,
Tag,
User
)
diff --git a/pydis_site/apps/api/models/bot/__init__.py b/pydis_site/apps/api/models/bot/__init__.py
index fb313193..b805924a 100644
--- a/pydis_site/apps/api/models/bot/__init__.py
+++ b/pydis_site/apps/api/models/bot/__init__.py
@@ -8,9 +8,5 @@ from .nomination import Nomination # noqa
from .off_topic_channel_name import OffTopicChannelName # noqa
from .reminder import Reminder # noqa
from .role import Role # noqa
-from .snake_fact import SnakeFact # noqa
-from .snake_idiom import SnakeIdiom # noqa
-from .snake_name import SnakeName # noqa
-from .special_snake import SpecialSnake # noqa
from .tag import Tag # noqa
from .user import User # noqa
diff --git a/pydis_site/apps/api/models/bot/bot_setting.py b/pydis_site/apps/api/models/bot/bot_setting.py
index ee9838b7..a52f3e34 100644
--- a/pydis_site/apps/api/models/bot/bot_setting.py
+++ b/pydis_site/apps/api/models/bot/bot_setting.py
@@ -7,7 +7,6 @@ from pydis_site.apps.api.models.utils import ModelReprMixin
def validate_bot_setting_name(name):
"""Raises a ValidationError if the given name is not a known setting."""
-
known_settings = (
'defcon',
)
diff --git a/pydis_site/apps/api/models/bot/documentation_link.py b/pydis_site/apps/api/models/bot/documentation_link.py
index 30379396..f844ae04 100644
--- a/pydis_site/apps/api/models/bot/documentation_link.py
+++ b/pydis_site/apps/api/models/bot/documentation_link.py
@@ -23,5 +23,4 @@ class DocumentationLink(ModelReprMixin, models.Model):
def __str__(self):
"""Returns the package and URL for the current documentation link, for display purposes."""
-
return f"{self.package} - {self.base_url}"
diff --git a/pydis_site/apps/api/models/bot/infraction.py b/pydis_site/apps/api/models/bot/infraction.py
index 7669352f..da91d6c2 100644
--- a/pydis_site/apps/api/models/bot/infraction.py
+++ b/pydis_site/apps/api/models/bot/infraction.py
@@ -60,7 +60,6 @@ class Infraction(ModelReprMixin, models.Model):
def __str__(self):
"""Returns some info on the current infraction, for display purposes."""
-
s = f"#{self.id}: {self.type} on {self.user_id}"
if self.expires_at:
s += f" until {self.expires_at}"
diff --git a/pydis_site/apps/api/models/bot/off_topic_channel_name.py b/pydis_site/apps/api/models/bot/off_topic_channel_name.py
index 2f55a131..0891f811 100644
--- a/pydis_site/apps/api/models/bot/off_topic_channel_name.py
+++ b/pydis_site/apps/api/models/bot/off_topic_channel_name.py
@@ -16,5 +16,4 @@ class OffTopicChannelName(ModelReprMixin, models.Model):
def __str__(self):
"""Returns the current off-topic name, for display purposes."""
-
return self.name
diff --git a/pydis_site/apps/api/models/bot/reminder.py b/pydis_site/apps/api/models/bot/reminder.py
index ae45b5de..decc9391 100644
--- a/pydis_site/apps/api/models/bot/reminder.py
+++ b/pydis_site/apps/api/models/bot/reminder.py
@@ -42,5 +42,4 @@ class Reminder(ModelReprMixin, models.Model):
def __str__(self):
"""Returns some info on the current reminder, for display purposes."""
-
return f"{self.content} on {self.expiration} by {self.author}"
diff --git a/pydis_site/apps/api/models/bot/role.py b/pydis_site/apps/api/models/bot/role.py
index ad043bd6..34e74009 100644
--- a/pydis_site/apps/api/models/bot/role.py
+++ b/pydis_site/apps/api/models/bot/role.py
@@ -46,5 +46,4 @@ class Role(ModelReprMixin, models.Model):
def __str__(self):
"""Returns the name of the current role, for display purposes."""
-
return self.name
diff --git a/pydis_site/apps/api/models/bot/snake_fact.py b/pydis_site/apps/api/models/bot/snake_fact.py
deleted file mode 100644
index c960cbc4..00000000
--- a/pydis_site/apps/api/models/bot/snake_fact.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from django.db import models
-
-from pydis_site.apps.api.models.utils import ModelReprMixin
-
-
-class SnakeFact(ModelReprMixin, models.Model):
- """A snake fact used by the bot's snake cog."""
-
- fact = models.CharField(
- primary_key=True,
- max_length=200,
- help_text="A fact about snakes."
- )
-
- def __str__(self):
- """Returns the current snake fact, for display purposes."""
-
- return self.fact
diff --git a/pydis_site/apps/api/models/bot/snake_idiom.py b/pydis_site/apps/api/models/bot/snake_idiom.py
deleted file mode 100644
index 0e8f5e94..00000000
--- a/pydis_site/apps/api/models/bot/snake_idiom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from django.db import models
-
-from pydis_site.apps.api.models.utils import ModelReprMixin
-
-
-class SnakeIdiom(ModelReprMixin, models.Model):
- """A snake idiom used by the snake cog."""
-
- idiom = models.CharField(
- primary_key=True,
- max_length=140,
- help_text="A saying about a snake."
- )
-
- def __str__(self):
- """Returns the current idiom, for display purposes."""
-
- return self.idiom
diff --git a/pydis_site/apps/api/models/bot/snake_name.py b/pydis_site/apps/api/models/bot/snake_name.py
deleted file mode 100644
index b6ea6202..00000000
--- a/pydis_site/apps/api/models/bot/snake_name.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from django.core.validators import RegexValidator
-from django.db import models
-
-from pydis_site.apps.api.models.utils import ModelReprMixin
-
-
-class SnakeName(ModelReprMixin, models.Model):
- """A snake name used by the bot's snake cog."""
-
- name = models.CharField(
- primary_key=True,
- max_length=100,
- help_text="The regular name for this snake, e.g. 'Python'.",
- validators=[RegexValidator(regex=r'^([^0-9])+$')]
- )
- scientific = models.CharField(
- max_length=150,
- help_text="The scientific name for this snake, e.g. 'Python bivittatus'.",
- validators=[RegexValidator(regex=r'^([^0-9])+$')]
- )
-
- def __str__(self):
- """Returns the regular and scientific name of the current snake, for display purposes."""
-
- return f"{self.name} ({self.scientific})"
diff --git a/pydis_site/apps/api/models/bot/special_snake.py b/pydis_site/apps/api/models/bot/special_snake.py
deleted file mode 100644
index 662ff8e3..00000000
--- a/pydis_site/apps/api/models/bot/special_snake.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from django.contrib.postgres import fields as pgfields
-from django.core.validators import RegexValidator
-from django.db import models
-
-from pydis_site.apps.api.models.utils import ModelReprMixin
-
-
-class SpecialSnake(ModelReprMixin, models.Model):
- """A special snake's name, info and image from our database used by the bot's snake cog."""
-
- name = models.CharField(
- max_length=140,
- primary_key=True,
- help_text='A special snake name.',
- validators=[RegexValidator(regex=r'^([^0-9])+$')]
- )
- info = models.TextField(
- help_text='Info about a special snake.'
- )
- images = pgfields.ArrayField(
- models.URLField(),
- help_text='Images displaying this special snake.'
- )
-
- def __str__(self):
- """Returns the name of the current snake, for display purposes."""
-
- return self.name
diff --git a/pydis_site/apps/api/models/bot/tag.py b/pydis_site/apps/api/models/bot/tag.py
index 99819e42..01b49525 100644
--- a/pydis_site/apps/api/models/bot/tag.py
+++ b/pydis_site/apps/api/models/bot/tag.py
@@ -10,7 +10,6 @@ from pydis_site.apps.api.models.utils import ModelReprMixin
def validate_tag_embed_fields(fields):
"""Raises a ValidationError if any of the given embed fields is invalid."""
-
field_validators = {
'name': (MaxLengthValidator(limit_value=256),),
'value': (MaxLengthValidator(limit_value=1024),)
@@ -30,7 +29,6 @@ def validate_tag_embed_fields(fields):
def validate_tag_embed_footer(footer):
"""Raises a ValidationError if the given footer is invalid."""
-
field_validators = {
'text': (
MinLengthValidator(
@@ -56,7 +54,6 @@ def validate_tag_embed_footer(footer):
def validate_tag_embed_author(author):
"""Raises a ValidationError if the given author is invalid."""
-
field_validators = {
'name': (
MinLengthValidator(
@@ -120,7 +117,6 @@ def validate_tag_embed(embed):
is raised which in turn will allow Django to display errors
as appropriate.
"""
-
all_keys = {
'title', 'type', 'description', 'url', 'timestamp',
'color', 'footer', 'image', 'thumbnail', 'video',
@@ -184,5 +180,4 @@ class Tag(ModelReprMixin, models.Model):
def __str__(self):
"""Returns the title of this tag, for display purposes."""
-
return self.title
diff --git a/pydis_site/apps/api/models/bot/user.py b/pydis_site/apps/api/models/bot/user.py
index 8b995b59..d4deb630 100644
--- a/pydis_site/apps/api/models/bot/user.py
+++ b/pydis_site/apps/api/models/bot/user.py
@@ -50,5 +50,4 @@ class User(ModelReprMixin, models.Model):
def __str__(self):
"""Returns the name and discriminator for the current user, for display purposes."""
-
return f"{self.name}#{self.discriminator}"
diff --git a/pydis_site/apps/api/models/utils.py b/pydis_site/apps/api/models/utils.py
index 8f590392..0540c4de 100644
--- a/pydis_site/apps/api/models/utils.py
+++ b/pydis_site/apps/api/models/utils.py
@@ -6,7 +6,6 @@ class ModelReprMixin:
def __repr__(self):
"""Returns the current model class name and initialisation parameters."""
-
attributes = ' '.join(
f'{attribute}={value!r}'
for attribute, value in sorted(
diff --git a/pydis_site/apps/api/serializers.py b/pydis_site/apps/api/serializers.py
index f1200d34..51ad9276 100644
--- a/pydis_site/apps/api/serializers.py
+++ b/pydis_site/apps/api/serializers.py
@@ -9,8 +9,6 @@ from .models import (
LogEntry, MessageDeletionContext,
Nomination, OffTopicChannelName,
Reminder, Role,
- SnakeFact, SnakeIdiom,
- SnakeName, SpecialSnake,
Tag, User
)
@@ -75,7 +73,6 @@ class MessageDeletionContextSerializer(ModelSerializer):
itself, this serializer also allows for passing the `deletedmessage_set` element
which contains messages that were deleted as part of this context.
"""
-
messages = validated_data.pop('deletedmessage_set')
deletion_context = MessageDeletionContext.objects.create(**validated_data)
for message in messages:
@@ -110,7 +107,6 @@ class InfractionSerializer(ModelSerializer):
def validate(self, attrs):
"""Validate data constraints for the given data and abort if it is invalid."""
-
infr_type = attrs.get('type')
expires_at = attrs.get('expires_at')
@@ -133,7 +129,6 @@ class ExpandedInfractionSerializer(InfractionSerializer):
def to_representation(self, instance):
"""Return the dictionary representation of this infraction."""
-
ret = super().to_representation(instance)
user = User.objects.get(id=ret['user'])
@@ -178,50 +173,9 @@ class OffTopicChannelNameSerializer(ModelSerializer):
Additionally, this allows off topic channel name routes to simply return an
array of names instead of objects, saving on bandwidth.
"""
-
return obj.name
-class SnakeFactSerializer(ModelSerializer):
- """A class providing (de-)serialization of `SnakeFact` instances."""
-
- class Meta:
- """Metadata defined for the Django REST Framework."""
-
- model = SnakeFact
- fields = ('fact',)
-
-
-class SnakeIdiomSerializer(ModelSerializer):
- """A class providing (de-)serialization of `SnakeIdiom` instances."""
-
- class Meta:
- """Metadata defined for the Django REST Framework."""
-
- model = SnakeIdiom
- fields = ('idiom',)
-
-
-class SnakeNameSerializer(ModelSerializer):
- """A class providing (de-)serialization of `SnakeName` instances."""
-
- class Meta:
- """Metadata defined for the Django REST Framework."""
-
- model = SnakeName
- fields = ('name', 'scientific')
-
-
-class SpecialSnakeSerializer(ModelSerializer):
- """A class providing (de-)serialization of `SpecialSnake` instances."""
-
- class Meta:
- """Metadata defined for the Django REST Framework."""
-
- model = SpecialSnake
- fields = ('name', 'images', 'info')
-
-
class ReminderSerializer(ModelSerializer):
"""A class providing (de-)serialization of `Reminder` instances."""
diff --git a/pydis_site/apps/api/tests/test_models.py b/pydis_site/apps/api/tests/test_models.py
index a958419d..cfc8464e 100644
--- a/pydis_site/apps/api/tests/test_models.py
+++ b/pydis_site/apps/api/tests/test_models.py
@@ -7,10 +7,7 @@ from ..models import (
Infraction, Message,
MessageDeletionContext, ModelReprMixin,
OffTopicChannelName, Reminder,
- Role, SnakeFact,
- SnakeIdiom, SnakeName,
- SpecialSnake, Tag,
- User
+ Role, Tag, User
)
@@ -52,13 +49,6 @@ class StringDunderMethodTests(SimpleTestCase):
'test', 'http://example.com', 'http://example.com'
),
OffTopicChannelName(name='bob-the-builders-playground'),
- SnakeFact(fact='snakes are cute'),
- SnakeIdiom(idiom='snake snacks'),
- SnakeName(name='python', scientific='3'),
- SpecialSnake(
- name='Pythagoras Pythonista',
- info='The only python snake that is born a triangle'
- ),
Role(
id=5, name='test role',
colour=0x5, permissions=0
diff --git a/pydis_site/apps/api/tests/test_snake_names.py b/pydis_site/apps/api/tests/test_snake_names.py
deleted file mode 100644
index 41dfae63..00000000
--- a/pydis_site/apps/api/tests/test_snake_names.py
+++ /dev/null
@@ -1,67 +0,0 @@
-from django_hosts.resolvers import reverse
-
-from .base import APISubdomainTestCase
-from ..models import SnakeName
-
-
-class StatusTests(APISubdomainTestCase):
- def setUp(self):
- super().setUp()
- self.client.force_authenticate(user=None)
-
- def test_cannot_read_snake_name_list(self):
- url = reverse('bot:snakename-list', host='api')
- response = self.client.get(url)
-
- self.assertEqual(response.status_code, 401)
-
- def test_cannot_read_snake_names_with_get_all_param(self):
- url = reverse('bot:snakename-list', host='api')
- response = self.client.get(f'{url}?get_all=True')
-
- self.assertEqual(response.status_code, 401)
-
-
-class EmptyDatabaseSnakeNameTests(APISubdomainTestCase):
- def test_endpoint_returns_empty_object(self):
- url = reverse('bot:snakename-list', host='api')
- response = self.client.get(url)
-
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.json(), {})
-
- def test_endpoint_returns_empty_list_with_get_all_param(self):
- url = reverse('bot:snakename-list', host='api')
- response = self.client.get(f'{url}?get_all=True')
-
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.json(), [])
-
-
-class SnakeNameListTests(APISubdomainTestCase):
- @classmethod
- def setUpTestData(cls): # noqa
- cls.snake_python = SnakeName.objects.create(name='Python', scientific='Totally.')
-
- def test_endpoint_returns_all_snakes_with_get_all_param(self):
- url = reverse('bot:snakename-list', host='api')
- response = self.client.get(f'{url}?get_all=True')
-
- self.assertEqual(response.status_code, 200)
- self.assertEqual(
- response.json(),
- [
- {
- 'name': self.snake_python.name,
- 'scientific': self.snake_python.scientific
- }
- ]
- )
-
- def test_endpoint_returns_single_snake_without_get_all_param(self):
- url = reverse('bot:snakename-list', host='api')
- response = self.client.get(url)
- self.assertEqual(response.json(), {
- 'name': self.snake_python.name,
- 'scientific': self.snake_python.scientific
- })
diff --git a/pydis_site/apps/api/urls.py b/pydis_site/apps/api/urls.py
index 724d7e2b..ac6704c8 100644
--- a/pydis_site/apps/api/urls.py
+++ b/pydis_site/apps/api/urls.py
@@ -7,10 +7,7 @@ from .viewsets import (
DocumentationLinkViewSet, InfractionViewSet,
LogEntryViewSet, NominationViewSet,
OffTopicChannelNameViewSet, ReminderViewSet,
- RoleViewSet, SnakeFactViewSet,
- SnakeIdiomViewSet, SnakeNameViewSet,
- SpecialSnakeViewSet, TagViewSet,
- UserViewSet
+ RoleViewSet, TagViewSet, UserViewSet
)
@@ -50,23 +47,6 @@ bot_router.register(
RoleViewSet
)
bot_router.register(
- 'snake-facts',
- SnakeFactViewSet
-)
-bot_router.register(
- 'snake-idioms',
- SnakeIdiomViewSet
-)
-bot_router.register(
- 'snake-names',
- SnakeNameViewSet,
- base_name='snakename'
-)
-bot_router.register(
- 'special-snakes',
- SpecialSnakeViewSet
-)
-bot_router.register(
'tags',
TagViewSet
)
@@ -80,7 +60,6 @@ urlpatterns = (
# Build URLs using something like...
#
# from django_hosts.resolvers import reverse
- # snake_name_endpoint = reverse('bot:snakename-list', host='api') # `bot/` endpoints
path('bot/', include((bot_router.urls, 'api'), namespace='bot')),
path('logs', LogEntryViewSet.as_view({'post': 'create'}), name='logs'),
path('healthcheck', HealthcheckView.as_view(), name='healthcheck'),
diff --git a/pydis_site/apps/api/views.py b/pydis_site/apps/api/views.py
index c7dbf5c8..e79de5e1 100644
--- a/pydis_site/apps/api/views.py
+++ b/pydis_site/apps/api/views.py
@@ -86,7 +86,6 @@ class RulesView(APIView):
ValueError:
If `target` is not `'md'` or `'html'`.
"""
-
if target == 'html':
return f'<a href="{link}">{description}</a>'
elif target == 'md':
diff --git a/pydis_site/apps/api/viewsets/__init__.py b/pydis_site/apps/api/viewsets/__init__.py
index 553ca2c3..224e6910 100644
--- a/pydis_site/apps/api/viewsets/__init__.py
+++ b/pydis_site/apps/api/viewsets/__init__.py
@@ -7,10 +7,6 @@ from .bot import ( # noqa
OffTopicChannelNameViewSet,
ReminderViewSet,
RoleViewSet,
- SnakeFactViewSet,
- SnakeIdiomViewSet,
- SnakeNameViewSet,
- SpecialSnakeViewSet,
TagViewSet,
UserViewSet
)
diff --git a/pydis_site/apps/api/viewsets/bot/__init__.py b/pydis_site/apps/api/viewsets/bot/__init__.py
index 8e7d1290..465ba5f4 100644
--- a/pydis_site/apps/api/viewsets/bot/__init__.py
+++ b/pydis_site/apps/api/viewsets/bot/__init__.py
@@ -6,9 +6,5 @@ from .nomination import NominationViewSet # noqa
from .off_topic_channel_name import OffTopicChannelNameViewSet # noqa
from .reminder import ReminderViewSet # noqa
from .role import RoleViewSet # noqa
-from .snake_fact import SnakeFactViewSet # noqa
-from .snake_idiom import SnakeIdiomViewSet # noqa
-from .snake_name import SnakeNameViewSet # noqa
-from .special_snake import SpecialSnakeViewSet # noqa
from .tag import TagViewSet # noqa
from .user import UserViewSet # noqa
diff --git a/pydis_site/apps/api/viewsets/bot/infraction.py b/pydis_site/apps/api/viewsets/bot/infraction.py
index d12f0862..c471ca2c 100644
--- a/pydis_site/apps/api/viewsets/bot/infraction.py
+++ b/pydis_site/apps/api/viewsets/bot/infraction.py
@@ -125,7 +125,6 @@ class InfractionViewSet(CreateModelMixin, RetrieveModelMixin, ListModelMixin, Ge
def partial_update(self, request, *_args, **_kwargs):
"""Method that handles the nuts and bolts of updating an Infraction."""
-
for field in request.data:
if field in self.frozen_fields:
raise ValidationError({field: ['This field cannot be updated.']})
@@ -144,7 +143,6 @@ class InfractionViewSet(CreateModelMixin, RetrieveModelMixin, ListModelMixin, Ge
Called by the Django Rest Framework in response to the corresponding HTTP request.
"""
-
self.serializer_class = ExpandedInfractionSerializer
return self.list(*args, **kwargs)
@@ -155,7 +153,6 @@ class InfractionViewSet(CreateModelMixin, RetrieveModelMixin, ListModelMixin, Ge
Called by the Django Rest Framework in response to the corresponding HTTP request.
"""
-
self.serializer_class = ExpandedInfractionSerializer
return self.create(*args, **kwargs)
@@ -166,7 +163,6 @@ class InfractionViewSet(CreateModelMixin, RetrieveModelMixin, ListModelMixin, Ge
Called by the Django Rest Framework in response to the corresponding HTTP request.
"""
-
self.serializer_class = ExpandedInfractionSerializer
return self.retrieve(*args, **kwargs)
@@ -177,6 +173,5 @@ class InfractionViewSet(CreateModelMixin, RetrieveModelMixin, ListModelMixin, Ge
Called by the Django Rest Framework in response to the corresponding HTTP request.
"""
-
self.serializer_class = ExpandedInfractionSerializer
return self.partial_update(*args, **kwargs)
diff --git a/pydis_site/apps/api/viewsets/bot/nomination.py b/pydis_site/apps/api/viewsets/bot/nomination.py
index a9dacd68..8d551697 100644
--- a/pydis_site/apps/api/viewsets/bot/nomination.py
+++ b/pydis_site/apps/api/viewsets/bot/nomination.py
@@ -143,6 +143,7 @@ class NominationViewSet(CreateModelMixin, RetrieveModelMixin, ListModelMixin, Ge
See operation 1 for the response format and status codes.
"""
+
serializer_class = NominationSerializer
queryset = Nomination.objects.all()
filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)
diff --git a/pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py b/pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py
index 4976c291..d977aade 100644
--- a/pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py
+++ b/pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py
@@ -60,14 +60,12 @@ class OffTopicChannelNameViewSet(DestroyModelMixin, ViewSet):
If it doesn't, a HTTP 404 is returned by way of throwing an exception.
"""
-
queryset = self.get_queryset()
name = self.kwargs[self.lookup_field]
return get_object_or_404(queryset, name=name)
def get_queryset(self):
"""Returns a queryset that covers the entire OffTopicChannelName table."""
-
return OffTopicChannelName.objects.all()
def create(self, request):
@@ -76,7 +74,6 @@ class OffTopicChannelNameViewSet(DestroyModelMixin, ViewSet):
Called by the Django Rest Framework in response to the corresponding HTTP request.
"""
-
if 'name' in request.query_params:
create_data = {'name': request.query_params['name']}
serializer = OffTopicChannelNameSerializer(data=create_data)
@@ -95,7 +92,6 @@ class OffTopicChannelNameViewSet(DestroyModelMixin, ViewSet):
Called by the Django Rest Framework in response to the corresponding HTTP request.
"""
-
if 'random_items' in request.query_params:
param = request.query_params['random_items']
try:
diff --git a/pydis_site/apps/api/viewsets/bot/snake_fact.py b/pydis_site/apps/api/viewsets/bot/snake_fact.py
deleted file mode 100644
index 0b2e8ede..00000000
--- a/pydis_site/apps/api/viewsets/bot/snake_fact.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from rest_framework.mixins import ListModelMixin
-from rest_framework.viewsets import GenericViewSet
-
-from pydis_site.apps.api.models.bot.snake_fact import SnakeFact
-from pydis_site.apps.api.serializers import SnakeFactSerializer
-
-
-class SnakeFactViewSet(ListModelMixin, GenericViewSet):
- """
- View providing snake facts created by the Pydis community in the first code jam.
-
- ## Routes
- ### GET /bot/snake-facts
- Returns snake facts from the database.
-
- #### Response format
- >>> [
- ... {'fact': 'Snakes are dangerous'},
- ... {'fact': 'Except for Python, we all love it'}
- ... ]
-
- #### Status codes
- - 200: returned on success
-
- ## Authentication
- Requires an API token.
- """
-
- serializer_class = SnakeFactSerializer
- queryset = SnakeFact.objects.all()
diff --git a/pydis_site/apps/api/viewsets/bot/snake_idiom.py b/pydis_site/apps/api/viewsets/bot/snake_idiom.py
deleted file mode 100644
index 9f274d2f..00000000
--- a/pydis_site/apps/api/viewsets/bot/snake_idiom.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from rest_framework.mixins import ListModelMixin
-from rest_framework.viewsets import GenericViewSet
-
-from pydis_site.apps.api.models.bot.snake_idiom import SnakeIdiom
-from pydis_site.apps.api.serializers import SnakeIdiomSerializer
-
-
-class SnakeIdiomViewSet(ListModelMixin, GenericViewSet):
- """
- View providing snake idioms for the snake cog.
-
- ## Routes
- ### GET /bot/snake-idioms
- Returns snake idioms from the database.
-
- #### Response format
- >>> [
- ... {'idiom': 'Sneky snek'},
- ... {'idiom': 'Snooky Snake'}
- ... ]
-
- #### Status codes
- - 200: returned on success
-
- ## Authentication
- Requires an API token
- """
-
- serializer_class = SnakeIdiomSerializer
- queryset = SnakeIdiom.objects.all()
diff --git a/pydis_site/apps/api/viewsets/bot/snake_name.py b/pydis_site/apps/api/viewsets/bot/snake_name.py
deleted file mode 100644
index 8e63a542..00000000
--- a/pydis_site/apps/api/viewsets/bot/snake_name.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from rest_framework.response import Response
-from rest_framework.viewsets import ViewSet
-
-from pydis_site.apps.api.models.bot.snake_name import SnakeName
-from pydis_site.apps.api.serializers import SnakeNameSerializer
-
-
-class SnakeNameViewSet(ViewSet):
- """
- View providing snake names for the bot's snake cog from our first code jam's winners.
-
- ## Routes
- ### GET /bot/snake-names
- By default, return a single random snake name along with its name and scientific name.
- If the `get_all` query parameter is given, for example using...
- $ curl api.pythondiscord.local:8000/bot/snake-names?get_all=yes
- ... then the API will return all snake names and scientific names in the database.
-
- #### Response format
- Without `get_all` query parameter:
- >>> {
- ... 'name': "Python",
- ... 'scientific': "Langus greatus"
- ... }
-
- If the database is empty for whatever reason, this will return an empty dictionary.
-
- With `get_all` query parameter:
- >>> [
- ... {'name': "Python 3", 'scientific': "Langus greatus"},
- ... {'name': "Python 2", 'scientific': "Langus decentus"}
- ... ]
-
- #### Status codes
- - 200: returned on success
-
- ## Authentication
- Requires a API token.
- """
-
- serializer_class = SnakeNameSerializer
-
- def get_queryset(self):
- """Returns a queryset that covers the entire SnakeName table."""
-
- return SnakeName.objects.all()
-
- def list(self, request):
- """
- DRF method for listing SnakeName entries.
-
- Called by the Django Rest Framework in response to the corresponding HTTP request.
- """
-
- if request.query_params.get('get_all'):
- queryset = self.get_queryset()
- serialized = self.serializer_class(queryset, many=True)
- return Response(serialized.data)
-
- single_snake = SnakeName.objects.order_by('?').first()
- if single_snake is not None:
- body = {
- 'name': single_snake.name,
- 'scientific': single_snake.scientific
- }
-
- return Response(body)
-
- return Response({})
diff --git a/pydis_site/apps/api/viewsets/bot/special_snake.py b/pydis_site/apps/api/viewsets/bot/special_snake.py
deleted file mode 100644
index 446c79a1..00000000
--- a/pydis_site/apps/api/viewsets/bot/special_snake.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from rest_framework.mixins import ListModelMixin
-from rest_framework.viewsets import GenericViewSet
-
-from pydis_site.apps.api.models.bot import SpecialSnake
-from pydis_site.apps.api.serializers import SpecialSnakeSerializer
-
-
-class SpecialSnakeViewSet(ListModelMixin, GenericViewSet):
- """
- View providing special snake names for our bot's snake cog.
-
- ## Routes
- ### GET /bot/special-snakes
- Returns a list of special snake names.
-
- #### Response Format
- >>> [
- ... {
- ... 'name': 'Snakky sneakatus',
- ... 'info': 'Scary snek',
- ... 'image': 'https://discordapp.com/assets/53ef346458017da2062aca5c7955946b.svg'
- ... }
- ... ]
-
- #### Status codes
- - 200: returned on success
-
- ## Authentication
- Requires an API token.
- """
-
- serializer_class = SpecialSnakeSerializer
- queryset = SpecialSnake.objects.all()
diff --git a/pydis_site/apps/home/models/repository_metadata.py b/pydis_site/apps/home/models/repository_metadata.py
index f68d3985..92d2404d 100644
--- a/pydis_site/apps/home/models/repository_metadata.py
+++ b/pydis_site/apps/home/models/repository_metadata.py
@@ -31,5 +31,4 @@ class RepositoryMetadata(models.Model):
def __str__(self):
"""Returns the repo name, for display purposes."""
-
return self.repo_name
diff --git a/pydis_site/apps/home/templatetags/extra_filters.py b/pydis_site/apps/home/templatetags/extra_filters.py
index 8af11591..99ba3dcd 100644
--- a/pydis_site/apps/home/templatetags/extra_filters.py
+++ b/pydis_site/apps/home/templatetags/extra_filters.py
@@ -16,5 +16,4 @@ def starts_with(value: str, arg: str):
{% endif %}
```
"""
-
return value.startswith(arg)
diff --git a/pydis_site/apps/home/templatetags/wiki_extra.py b/pydis_site/apps/home/templatetags/wiki_extra.py
index ab14f7be..2e90af43 100644
--- a/pydis_site/apps/home/templatetags/wiki_extra.py
+++ b/pydis_site/apps/home/templatetags/wiki_extra.py
@@ -1,4 +1,4 @@
-from typing import Any, Dict, Type, Union
+from typing import Any, Dict, List, Type, Union
from django import template
from django.forms import BooleanField, BoundField, CharField, Field, ImageField, ModelChoiceField
@@ -33,7 +33,6 @@ def get_unbound_field(field: Union[BoundField, Field]) -> Field:
Bound fields often don't give you the same level of access to the field's underlying attributes,
so sometimes it helps to have access to the underlying field object.
"""
-
while isinstance(field, BoundField):
field = field.field
@@ -47,7 +46,6 @@ def render(template_path: str, context: Dict[str, Any]):
This was extracted mostly for the sake of mocking it out in the tests - but do note that
the resulting rendered template is wrapped with `mark_safe`, so it will not be escaped.
"""
-
return mark_safe(get_template(template_path).render(context)) # noqa: S703, S308
@@ -67,7 +65,6 @@ def render_field(field: Field, render_labels: bool = True):
Usage: `{% render_field field_obj [render_labels=True/False] %}`
"""
-
unbound_field = get_unbound_field(field)
if not isinstance(render_labels, bool):
@@ -104,11 +101,10 @@ def get_field_options(context: Context, field: BoundField):
{% endif %}
```
"""
-
widget = field.field.widget
if field.value() is None:
- value = []
+ value: List[str] = []
else:
value = [str(field.value())]
@@ -130,7 +126,6 @@ def render_urlpath(value: Union[URLPath, str]):
Usage: `{{ url_path | render_urlpath }}`
"""
-
if isinstance(value, str):
return value or "/"
diff --git a/pydis_site/apps/home/tests/test_repodata_helpers.py b/pydis_site/apps/home/tests/test_repodata_helpers.py
index 59cb2331..df1ffd73 100644
--- a/pydis_site/apps/home/tests/test_repodata_helpers.py
+++ b/pydis_site/apps/home/tests/test_repodata_helpers.py
@@ -34,13 +34,11 @@ class TestRepositoryMetadataHelpers(TestCase):
def setUp(self):
"""Executed before each test method."""
-
self.home_view = HomeView()
@mock.patch('requests.get', side_effect=mocked_requests_get)
def test_returns_metadata(self, _: mock.MagicMock):
"""Test if the _get_repo_data helper actually returns what it should."""
-
metadata = self.home_view._get_repo_data()
self.assertIsInstance(metadata[0], RepositoryMetadata)
@@ -48,7 +46,6 @@ class TestRepositoryMetadataHelpers(TestCase):
def test_returns_cached_metadata(self):
"""Test if the _get_repo_data helper returns cached data when available."""
-
repo_data = RepositoryMetadata(
repo_name="python-discord/site",
description="testrepo",
@@ -65,7 +62,6 @@ class TestRepositoryMetadataHelpers(TestCase):
@mock.patch('requests.get', side_effect=mocked_requests_get)
def test_refresh_stale_metadata(self, _: mock.MagicMock):
"""Test if the _get_repo_data helper will refresh when the data is stale"""
-
repo_data = RepositoryMetadata(
repo_name="python-discord/site",
description="testrepo",
@@ -82,7 +78,6 @@ class TestRepositoryMetadataHelpers(TestCase):
@mock.patch('requests.get', side_effect=mocked_requests_get)
def test_returns_api_data(self, _: mock.MagicMock):
"""Tests if the _get_api_data helper returns what it should."""
-
api_data = self.home_view._get_api_data()
repo = self.home_view.repos[0]
@@ -94,7 +89,6 @@ class TestRepositoryMetadataHelpers(TestCase):
@mock.patch('requests.get', side_effect=mocked_requests_get)
def test_mocked_requests_get(self, mock_get: mock.MagicMock):
"""Tests if our mocked_requests_get is returning what it should."""
-
success_data = mock_get(HomeView.github_api)
fail_data = mock_get("failtest")
diff --git a/pydis_site/apps/home/views/home.py b/pydis_site/apps/home/views/home.py
index e4daf380..03873a72 100644
--- a/pydis_site/apps/home/views/home.py
+++ b/pydis_site/apps/home/views/home.py
@@ -28,12 +28,10 @@ class HomeView(View):
def _get_api_data(self) -> Dict[str, Dict[str, str]]:
"""Call the GitHub API and get information about our repos."""
-
- repo_dict = {repo_name: {} for repo_name in self.repos}
+ repo_dict: Dict[str, dict] = {repo_name: {} for repo_name in self.repos}
# Fetch the data from the GitHub API
- api_data = requests.get(self.github_api)
- api_data = api_data.json()
+ api_data: List[dict] = requests.get(self.github_api).json()
# Process the API data into our dict
for repo in api_data:
@@ -51,7 +49,6 @@ class HomeView(View):
def _get_repo_data(self) -> List[RepositoryMetadata]:
"""Build a list of RepositoryMetadata objects that we can use to populate the front page."""
-
# Try to get site data from the cache
try:
repo_data = RepositoryMetadata.objects.get(repo_name="python-discord/site")
@@ -110,6 +107,5 @@ class HomeView(View):
def get(self, request: WSGIRequest) -> HttpResponse:
"""Collect repo data and render the homepage view"""
-
repo_data = self._get_repo_data()
return render(request, "home/index.html", {"repo_data": repo_data})
diff --git a/pydis_site/utils/resources.py b/pydis_site/utils/resources.py
index ab0df9d7..fcf8bd75 100644
--- a/pydis_site/utils/resources.py
+++ b/pydis_site/utils/resources.py
@@ -10,6 +10,7 @@ import yaml
@dataclass
class URL:
"""A class representing a link to a resource"""
+
icon: str
title: str
url: str
@@ -17,6 +18,7 @@ class URL:
class Resource:
"""A class representing a resource on the resource page"""
+
description: str
name: str
payment: str
@@ -28,7 +30,7 @@ class Resource:
return f"<Resource name={self.name}>"
@classmethod
- def construct_from_yaml(cls, yaml_data: str) -> Resource: # noqa
+ def construct_from_yaml(cls, yaml_data: typing.TextIO) -> Resource: # noqa
resource = cls()
loaded = yaml.safe_load(yaml_data)
@@ -45,6 +47,7 @@ class Resource:
class Category:
"""A class representing a resource on the resources page"""
+
resources: typing.List[Resource]
name: str
description: str