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

paasio: implement exercise #751

Closed
ilya-khadykin opened this issue Oct 6, 2017 · 5 comments · Fixed by #2195
Closed

paasio: implement exercise #751

ilya-khadykin opened this issue Oct 6, 2017 · 5 comments · Fixed by #2195

Comments

@ilya-khadykin
Copy link
Contributor

There are exercises that are not yet implemented in Python track (the full list of them - #417 (comment)).
You can help us change this situation by implementing this one. Ref #417

The guide "Implement an exercise from specification" will help you succeed.

If you still have questions, I encourage you to ask them before starting working on the issue.

I also suggest claiming the issue by creating an empty PR as stated here

Please note that there are some special 'closing issue' keywords that you can put in description of your PR and Github will take care of closing the corresponding issue automatically after merge.
This simple thing helps us a lot, and makes our life a bit easier

@stale
Copy link

stale bot commented Nov 23, 2017

This issue has been automatically marked as abandoned because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@AnAccountForReportingBugs
Copy link
Contributor

I've been looking at this and have a few notes I'd like broader insight on.

  1. This exercise would require implementing a file-like and a "socket-like" object.
  2. The usual way to handle this is sub-classing or delegation.
  3. Sockets cannot be sub-classed. Instead, they must use a delegation pattern of some kind.
  4. Therefore, it seems that the correct way to do socket.socket would be to expect them to create a delegated class with proper methods and attributes.
  5. There are 31 methods and 3 attributes for sockets, should all be exposed by the delegation object, or just a subset of the most common ones?
  6. The major problem, it seems, is the file-like object.
  7. First is that they come in two types, text and binary. Should just one or both be a part of the exercises?
  8. It seems to me that the proper measure would be the actual binary calls but there is no easy way to get that from a TextIOBase without decoding and calling the buffer directly. Should this exercises just be limited to the amount the underlying objects or super() expose directly.
  9. Should the file-like also use delegated objects or subclass?
  10. Should all 24 methods and attributes be exposed or just a subset?
  11. Since file-like objects are usually returned via open(), do we want to shadow that built-in to return the new file-like class or have the students do that?

@yawpitch
Copy link
Contributor

yawpitch commented Mar 21, 2020

Admittedly I don't work with raw sockets very often, but why can socket.socket not be subclassed? I see that the file descriptor it creates is non-inheritable, but that's about is ability to be passed between processes and doesn't obviously preclude subclasses of socket.socket itself. That said, I'll admit that subclassing it well looks like a lot of work, since various methods currently use socket.socket internally and you'd need to rewrite those to reference your subclass as well.

I would think, though, that for the purposes of this exercise, we could simply require a MeteredSocket class that takes a socket we control as an argument and wraps its socket.send and socket.recv methods to collect statistics ... we need not delegate to all the methods, we can simply pretend that our PaaS offers a fairly limited socket implementation.

Same with the file-like object ... a MeteredFile could simply wrap an fd we control with stats-gathering fd.read and fd.write functionality .. for the sake of simplicity we could have the student expect something with the interface of IO.BufferedRandom, so they only have to consider the length of bytes objects rather than consider encoding.

So I'd say a rather simplistic delegation is more than enough ... while exhaustively wrapping the full pantheon of IO classes is certainly a heck of a good learning exercise I'd say it's well beyond the scope of Exercism's "fluency" mandate.

@AnAccountForReportingBugs
Copy link
Contributor

AnAccountForReportingBugs commented Mar 22, 2020

I appreciate your insight. To answer your first question, maybe saying you cannot wrap any socket, whether SOCK_RAW or not, might be a bit too hyperbolic. But, you cannot wrap any socket without doing large amounts of Python and bit of C. Unlike file-like objects, socket and _socket are written under the assumption that all sockets returned by the libc calls should be delegated to stdlib internal types. Its not the best design from an extensiblity point of view, but the whole API wants to mimic the POSIX/Berkeley calls and wasn't written with ABCs or having other objects use the same API (like binary vs text files, to name the most obvious) in mind. Therefore, subclassing can easily get you weird behavior, wrong calls, or wrong object types due to the dependency between object methods.

As to the rest and with your thoughts in mind, I'll look at some sort of delegation pattern with a passed-in parent. My initial thought would be to follow your suggestion giving the __init__ of MeteredSocket an already-connected or mocked socket and giving MeteredFile a BytesIO. The former would implement recv, send, and close, although I am tempted to add __enter__, __exit__, recvfrom, sendto, and sendall to demonstrate what they do because they are commonly used. The latter would have the seek, read, write, and close methods, although I am again tempted to add __enter__, __exit__, __iter__, and __next__ for similar reasons to the above.

@yawpitch
Copy link
Contributor

I'd say that having the student support the context manager and iterator protocols is perfectly valid and relatively easy to test as well. I'd be fine with adding the various socket methods, but be careful to remember that we're not trying to teach fluency in sockets, but in Python ... so if the method doesn't really rely on new or different concepts in Python then I'd consider it for a bonus task, or elide it altogether.

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 a pull request may close this issue.

5 participants