Skip to content

Commit

Permalink
Merge pull request #53 from djotaku/devel
Browse files Browse the repository at this point in the history
for DDOS issues (and some PEP8)
  • Loading branch information
djotaku authored Feb 5, 2020
2 parents 87ecd2b + 0d76260 commit 41d2cce
Show file tree
Hide file tree
Showing 14 changed files with 257 additions and 88 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/linttest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ jobs:
run: |
pip install flake8
# stop the build if there are Python syntax errors or undefined names
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py settings.py --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py settings.py --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
shell: bash
- name: Test with pytest
run: |
pip install pytest
pytest extralifeunittests.py
pytest test.py
shell: bash
6 changes: 3 additions & 3 deletions .github/workflows/linuxbuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ jobs:
run: |
pip install flake8
# stop the build if there are Python syntax errors or undefined names
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py settings.py --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py settings.py --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pip install pytest
pytest extralifeunittests.py
pytest test.py
- name: Build with Pyinstaller
run: |
pip install pyinstaller
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/windowsbuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ jobs:
run: |
pip install flake8
# stop the build if there are Python syntax errors or undefined names
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py settings.py --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py settings.py --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pip install pytest
pytest extralifeunittests.py
pytest test.py
- name: Build with Pyinstaller
run: |
pip install pyinstaller
Expand Down
18 changes: 12 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
Master will always contain perfectly working code aligned with the latest release.

If you wish to contribute, please do so off of the devel branch and file a pull request with your changes.
If you wish to contribute, please do so off of the devel branch and file a pull request with your changes. If I have another branch pushed to Github that may temporarily be the branch to develop from. Check with me.

The code is up to PEP8 standards I have written unit tests. The following files should be without errors on flake8's test suite (don't worry about >80 char errors):
I strive for the code to be PEP8 compliant. Run the following against your fork:

- extralifedonations.py
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py --count --select=E9,F63,F7,F82 --show-source --statistics

- IPC.py
If it fails, the CI will fail and the pull request will not be merged until it is fixed.

- readparticipantconf.py
My preference is for the following to be error free (don't worry about line-length errors):

- team.py
flake8 extralifedonations.py IPC.py readparticipantconf.py team.py donation.py donor.py extralife_IO.py --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics

But even my code isn't (as of 26 Jan 2020) perfect against that flake8 run, yet.

If that list above becomes out of date, the canonical list of files that need to pass flake8 can be found in the repo under .github/workflows/linttest.yml.

All the unit tests in extralifeunittests.py should pass.

Because the PyQt classes and functions mimic their C/C++ classes and functions, they may violate PEP8 and other Python conventions, so flake8 does not have to pass on files related to the GUI. However, they should pass pydocstyle.

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
![Lint_Test](https://github.com/djotaku/ELDonationTracker/workflows/Lint_Test/badge.svg?branch=devel)

Would you like to be able to update your donations in real-time during a Live Stream or while recording a Let's Play as in the following screenshots?

![Updates while in-game](https://github.com/djotaku/ELDonationTracker/blob/devel/screenshots/IngameUpdates.png)
Expand Down
38 changes: 32 additions & 6 deletions call_settings.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Contains the programming logic for the settings window in the GUI."""

import sys
import json
from PyQt5.QtWidgets import QDialog, QApplication, QFileDialog
Expand All @@ -7,7 +9,15 @@


class MyForm(QDialog):
"""Class for the settings Window."""

def __init__(self, participant_conf):
"""Init for the settings Window.
Grabs the data from the participant.conf file and
uses that to pre-populate the fields in the settings
window.
"""
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
Expand All @@ -25,21 +35,31 @@ def __init__(self, participant_conf):
self.ui.pushButtonRevert.clicked.connect(self.revert)
self.ui.pushButtonSave.clicked.connect(self.save)
self.ui.pushButton_persistentsave.clicked.connect(self.persistent_save)
self.ui.pushButtonSelectFolder.clicked.connect(self.selectfolder)
self.ui.pushButton_tracker_image.clicked.connect(lambda: self.selectfile("image"))
self.ui.pushButton_sound.clicked.connect(lambda: self.selectfile("sound"))
#self.ui.spinBox_DonorsToDisplay.valueChanged.connect(self.donorschanged)
self.ui.pushButtonSelectFolder.clicked.connect(self._selectfolder)
self.ui.pushButton_tracker_image.clicked.connect(lambda: self._selectfile("image"))
self.ui.pushButton_sound.clicked.connect(lambda: self._selectfile("sound"))
# self.ui.spinBox_DonorsToDisplay.valueChanged.connect(self.donorschanged)
if self.donors_to_display is None:
self.ui.spinBox_DonorsToDisplay.setValue(0)
else:
self.ui.spinBox_DonorsToDisplay.setValue(int(self.donors_to_display))

def reload_config(self):
"""Reload the values from the config file.
Called by gui.py before loading the settings window.
"""
(self.ExtraLifeID, self.textFolder,
self.CurrencySymbol, self.TeamID, self.TrackerImage,
self.DonationSound, self.donors_to_display) = self.participant_conf.get_GUI_values()

def revert(self):
"""
Revert the values in the settings window.
If the user made mistakes while editing the config this will
take them back to the values since they opened the window.
"""
self.ui.lineEditParticipantID.setText(self.ExtraLifeID)
self.ui.labelTextFolder.setText(self.textFolder)
self.ui.lineEditCurrencySymbol.setText(self.CurrencySymbol)
Expand Down Expand Up @@ -72,18 +92,23 @@ def _elements_to_save(self):
return config

def save(self):
"""Save the values in the window.
Calls the write_config method from extralife_IO.ParticipantConf
"""
config = self._elements_to_save()
self.participant_conf.write_config(config, True)

def persistent_save(self):
"""Use xdg_config, saves a persistent config to the XDG spot."""
config = self._elements_to_save()
self.participant_conf.write_config(config, False)

def selectfolder(self):
def _selectfolder(self):
directory = QFileDialog.getExistingDirectory(self, "Get Folder")
self.ui.labelTextFolder.setText(directory)

def selectfile(self, whichfile):
def _selectfile(self, whichfile):
the_file = QFileDialog.getOpenFileName(self, "Select File")
if whichfile == "image":
self.ui.label_tracker_image.setText(the_file[0])
Expand All @@ -92,6 +117,7 @@ def selectfile(self, whichfile):


def main(participant_conf):
"""Launch it."""
w = MyForm(participant_conf)
w.exec()

Expand Down
49 changes: 33 additions & 16 deletions call_tracker.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""A window that displays the last donation. Useful during streaming."""

import sys
from PyQt5.QtWidgets import QDialog, QApplication, QGraphicsScene, QGraphicsPixmapItem
from tracker import *
Expand All @@ -8,7 +10,14 @@


class MyForm(QDialog):
"""The class to hold the tracker window."""

def __init__(self, participant_conf):
"""Set up the window.
Loads in the image and sound file the user specified in the
participant.conf settings file.
"""
super().__init__()
# config stuff
self.participant_conf = participant_conf
Expand All @@ -17,39 +26,46 @@ def __init__(self, participant_conf):
self.ui.setupUi(self)
self.scene = QGraphicsScene(self)
self.pixmap = QtGui.QPixmap()
self.loadimage()
self._loadimage()
self.ui.graphicsView.setScene(self.scene)
self.donation_player = QMediaPlayer()
self.loadsound()
self._loadsound()
# timer to update the main text
self.timer = QtCore.QTimer(self)
self.timer.setSingleShot(False)
self.timer.setInterval(20000) # milliseconds
self.timer.timeout.connect(self.loadAndUnload)
self.timer.timeout.connect(self._loadAndUnload)
self.timer.start()

def loadimage(self):
def _loadimage(self):
self.tracker_image = self.participant_conf.get_tracker_image()
self.pixmap.load(self.tracker_image)
self.item = QGraphicsPixmapItem(self.pixmap.scaledToHeight(131))

def loadsound(self):
def _loadsound(self):
sound_to_play = self.participant_conf.get_tracker_sound()
self.donation_sound= QMediaContent(QUrl.fromLocalFile(sound_to_play))
self.donation_player.setMedia(self.donation_sound)

def loadAndUnloadTest(self):
self.loadimage()
self.loadElements()
self.loadsound()
"""Trigger the tracker functionality.
This causes the image and sound to load so that the
user can test to see how it's going to look on their OBS
or XSplit screen as well as to make sure they can hear
the sound. Called by gui.py.
"""
self._loadimage()
self._loadElements()
self._loadsound()
self.donation_player.play()
unloadtimer = QtCore.QTimer(self)
unloadtimer.setSingleShot(True)
unloadtimer.setInterval(5000) # milliseconds
unloadtimer.timeout.connect(self.unloadElements)
unloadtimer.timeout.connect(self._unloadElements)
unloadtimer.start()

def loadAndUnload(self):
def _loadAndUnload(self):
self.folders = self.participant_conf.get_text_folder_only()
IPC = "0"
try:
Expand All @@ -61,17 +77,17 @@ def loadAndUnload(self):
Have you updated the settings?
Have you hit the 'run' button?""")
if IPC == "1":
self.loadimage()
self.loadElements()
self.loadsound()
self._loadimage()
self._loadElements()
self._loadsound()
self.donation_player.play()
unloadtimer = QtCore.QTimer(self)
unloadtimer.setSingleShot(True)
unloadtimer.setInterval(5000) # milliseconds
unloadtimer.timeout.connect(self.unloadElements)
unloadtimer.timeout.connect(self._unloadElements)
unloadtimer.start()

def loadElements(self):
def _loadElements(self):
self.scene.addItem(self.item)
# want to also play a sound
try:
Expand All @@ -82,13 +98,14 @@ def loadElements(self):
except FileNotFoundError:
self.ui.Donation_label.setText("TEST 1...2...3...")

def unloadElements(self):
def _unloadElements(self):
self.scene.removeItem(self.item)
self.ui.Donation_label.setText("")
IPC.writeIPC(self.folders, "0")


def main(participant_conf):
"""Run it."""
w = MyForm(participant_conf)
w.exec()

Expand Down
13 changes: 13 additions & 0 deletions donation.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
"""A class to hold the Donation attributes and methods."""


class Donation:
"""Donation Attributes.
Class exists to provide attributes for a donation based on what comes in
from the JSON so that it doesn't have to be traversed each time a donor
action needs to be taken.
API Variables:
name: the name of the donor for this donation.
If the donor wished to stay anonymous,
the variable is set to "Anonymous"
message: the message associated with the donation.
amount: the amount of the donation. If they blocked it from showing
it is set to 0.
"""

def __init__(self, name, message, amount):
Expand Down
11 changes: 10 additions & 1 deletion donor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ class Donor:
Class exists to provide attributes for a donor based on what comes in from
the JSON so that it doesn't have to be traversed each time a donor action
needs to be taken.
API Variables:
name: donor's name if provided, else Anonymous
donor_id: the ID assigned by the API (currently not used)
image_url: the URL for the donor's avatar (currently not used)
amount: the sum of all donations the donor has made this campaign
number_of_dononations: the number of donations the donor has made
this campaign
"""

def __init__(self, json):
Expand All @@ -16,7 +24,8 @@ def __init__(self, json):
def json_to_attributes(self, json):
"""Convert JSON to Donor attributes.
May be overwritten by child classes."""
May be overwritten by child classes.
"""
if json.get('displayName') is not None:
self.name = json.get('displayName')
else:
Expand Down
9 changes: 6 additions & 3 deletions extralife_IO.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Holds all the file and internet input and output."""

import json
from urllib.request import Request, urlopen, HTTPError, URLError
import ssl
from urllib.request import HTTPError, Request, URLError, urlopen

import xdgenvpy


Expand Down Expand Up @@ -34,7 +35,7 @@ def get_JSON(url, order_by_donations=False):
and this is not an intermittent issue:
please open an issue at:
https://github.com/djotaku/ELDonationTracker""")
return 0
return 0 # to be proper this should return an exemption
except URLError:
print(f"HTTP code: {payload.getcode()}")
print(f""" Timed out while getting JSON. """)
Expand Down Expand Up @@ -102,7 +103,8 @@ def write_config(self, config, default):
"""Write config to file.
At this point, only called from GUI. Commandline
user is expected to edit file manually."""
user is expected to edit file manually.
"""
if default:
with open('participant.conf', 'w') as outfile:
json.dump(config, outfile)
Expand Down Expand Up @@ -138,6 +140,7 @@ def get_GUI_values(self):
self.fields["donors_to_display"])

def get_if_in_team(self):
"""Return True if participant is in a team."""
# debug
# print(self.fields["team_id"])
if self.fields["team_id"] is None:
Expand Down
Loading

0 comments on commit 41d2cce

Please sign in to comment.