Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added NeoPixel FeatherWing #25

Merged
merged 17 commits into from
Feb 12, 2019
Merged

Conversation

makermelissa
Copy link
Collaborator

Ok, I finished the NeoPixel FeatherWing, which is based on my DotStar FeatherWing work.

@makermelissa makermelissa requested a review from a team February 6, 2019 04:02
Copy link
Contributor

@kattni kattni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! Thank you for extending the library the way you did, I really like that you didn't duplicate a lot of code.

I have a suggestion that affects a number of lines, but I won't comment on each one as there are many.

@@ -48,7 +48,7 @@ def __init__(self, clock=board.D13, data=board.D11, brightness=0.2):
self.rows = 6
self.columns = 12
self._auto_write = True
self._dotstar = dotstar.DotStar(clock, data, self.rows * self.columns,
self._display = dotstar.DotStar(clock, data, self.rows * self.columns,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider naming this matrix instead of display as we have a lot of display libraries within which we use that term. There are some FeatherWings with displays (or maybe only one?) and it might be a little confusing.

@caternuson
Copy link

Interesting inheritance. How about refactoring everything into a third generic class that both DotStar and NeoPixel could derive from?

@makermelissa
Copy link
Collaborator Author

Thanks @kattni. Matrix sounds good. I was just trying to use a generic term. @caternuson I started going down that path but there realized there were less disables required for pylint this way. Either way would work though if you'd prefer I change it to that.

@makermelissa
Copy link
Collaborator Author

Added @kattni's suggested change

@caternuson
Copy link

@makermelissa What's an example of one of the pylint disables?

@makermelissa
Copy link
Collaborator Author

I can't remember the exact one, but I put all of the functionality in the base class and because it self._display (now matrix) hadn't been assigned until the extended classes were initialized, Pylint was complaining that the methods/properties of display that I was calling in the base class didn't exist.

@caternuson
Copy link

Did you have a stubbed out placeholder in the base class for self._matrix? I'm thinking just set it to None in the base class's __int__() and then set it to a DotStar/NeoPixel instance in the derived classes.

Something like pixels in BaseClass here:

class DotStar:
    """DotStar class"""
    def __init__(self, clock, data):
        self.clock = clock
        self.data = data

    def show(self):
        """Show stuff."""
        print("I'm a DotStar with clock = {} and data = {}".format(self.clock, self.data))

class NeoPixel:
    """NeoPixel class"""
    def __init__(self, data):
        self.data = data

    def show(self):
        """Show stuff."""
        print("I'm a NeoPixel with data = {}".format(self.data))

class BaseThing:
    """Base class."""
    def __init__(self):
        self.pixels = None

    def show(self):
        """Show stuff."""
        self.pixels.show()

class DotStarThing(BaseThing):
    """DotStar class."""
    def __init__(self, clock, data):
        super().__init__()
        self.pixels = DotStar(clock, data)

class NeoPixelThing(BaseThing):
    """NeoPixel class."""
    def __init__(self, data):
        super().__init__()
        self.pixels = NeoPixel(data)

Test usage:

Adafruit CircuitPython 3.1.2 on 2019-01-07; Adafruit ItsyBitsy M4 Express with samd51g19
>>> import class_test
>>> d = class_test.DotStarThing(1,2)
>>> n = class_test.NeoPixelThing(8)
>>> d.show()
I'm a DotStar with clock = 1 and data = 2
>>> n.show()
I'm a NeoPixel with data = 8
>>> 

@makermelissa
Copy link
Collaborator Author

makermelissa commented Feb 7, 2019

I tried setting it to None and when I tried to set it in the child class I got pylint errors such as

E:117,25: Value 'self._display' is unsubscriptable (unsubscriptable-object)
E:119,16: 'self._display' does not support item assignment (unsupported-assignment-operation)

@caternuson
Copy link

Can you put the full code up in a branch in your repo and link it here.

@makermelissa
Copy link
Collaborator Author

You can see it in one of my above commits. Link is b862de5

@caternuson
Copy link

Hmmm. Quick scan of that, yah, that's what I'm thinking. Seems OK. Wonder if you're hitting this?
pylint-dev/pylint#1498

What if you ignore pylint and just try running it? Was it functional?

@makermelissa
Copy link
Collaborator Author

Yeah, it was functional. That's why I mentioned pylint disables.

@makermelissa
Copy link
Collaborator Author

And yes, that sounds like the issue I ran into.

@caternuson
Copy link

If you'd rather have gone with that class arrangement, I'd say it's OK to go ahead and add the disables. Seems like you only went with the current arrangement because of what appears to be a still open pylint bug.

You can add the disable globally, so you don't have to pepper it all over the place.

@makermelissa
Copy link
Collaborator Author

That's correct. I'll go ahead and make the changes and get them pushed.

@makermelissa
Copy link
Collaborator Author

Ok, it is now using the base class, has @kattni's suggestion, passes pylint, and functions perfectly.

@caternuson caternuson requested a review from a team February 7, 2019 21:48
@caternuson
Copy link

I'd suggest keeping all the methods public in the PixelMatrixFeatherWing class (no leading _). Then your two subclasses would only need to override __init__ to plumb in an actual _matrix object.

Also, move PixelMatrixFeatherWing to a separate file and then import it in the other two.

@makermelissa
Copy link
Collaborator Author

Yeah, the main reason I did it with private methods was to be able to provide FeatherWing specific examples for each function for purposes of RTD. However, I can make is so the docstrings reflect one wing or the other.

@makermelissa
Copy link
Collaborator Author

I moved PixelMatrix to a separate file. However, I'm waiting on a response about suggestions for code examples and RTD. In other words, if I remove all the public function calls from NeoPixel and DotStar then it will show RTD generated comments from the docstring of PixelMatrix on both files. (i.e. If I use the DotStar example it will show up under NeoPixel wing or vice versa) I would think most people probably won't have both wings. Plus PixelMatrix was never intended to be used on it's own since it's a base class. I could remove the example, but I feel like it would be more helpful to the end user to have those.

@tannewt
Copy link
Member

tannewt commented Feb 11, 2019

RTD comments on both sounds good to me. Why would you need to remove the example?

@makermelissa
Copy link
Collaborator Author

Unless there's a way of doing it that I'm not aware of, I believe RTD will split off whatever example is in the base class to the extended classes.

@tannewt
Copy link
Member

tannewt commented Feb 11, 2019

I'd move the full function examples into external example files. Then, in the function just include the related code rather than the full example and refer to the full example.

@makermelissa
Copy link
Collaborator Author

Ok @tannewt, thanks. I'll go ahead and do that. I think including the examples in the comments seems to only work well if classes don't share code. I'm doing something similar with the Alphanum/7-segment displays too so I'll apply the same approach.

@tannewt
Copy link
Member

tannewt commented Feb 11, 2019

Great! Happy to help unblock you. Thank you for all of the awesome changes.

@makermelissa
Copy link
Collaborator Author

I went ahead and removed all of the overrides except shift_up and shift_down in the neopixel featherwing library since they are laid out vertically in reverse of each other and shift_up on the neopixel being the same direction as shift_down on the dotstar.

@caternuson
Copy link

Nice! Looks good. I like it from a code layout / inheritance stand point.

You've tested this with hardware on both Wings?

@makermelissa
Copy link
Collaborator Author

Yes @caternuson, I tested all examples on both wings.

@caternuson
Copy link

@kattni I approved for CP Librarians. You good with changes too?

Copy link
Contributor

@kattni kattni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thanks again!

@makermelissa makermelissa merged commit 6e83321 into adafruit:master Feb 12, 2019
adafruit-adabot added a commit to adafruit/Adafruit_CircuitPython_Bundle that referenced this pull request Feb 13, 2019
Updating https://github.com/adafruit/Adafruit_CircuitPython_FeatherWing to 1.3.0 from 1.2.0:
  > Merge pull request adafruit/Adafruit_CircuitPython_FeatherWing#25 from makermelissa/master

Updating https://github.com/adafruit/Adafruit_CircuitPython_Bundle/circuitpython_library_list.md to NA from NA:
  > Added the following libraries: Adafruit_CircuitPython_Touchscreen
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants