Can mock.mock_open.read return different values?

2018-03-12 Thread Tim Golden
I'm contributing to a codebase which makes heavy use of mock in the test 
suite, a technique which I'm aware of but have used only rarely. In one 
situation it uses mock.mock_open(read_data="...") and then asserts again 
mock_open.return_value.read.call_count.


A code change I've made results in an increase in the call count but 
also the open() I've introduced opens the file in binary mode and does 
something with the resulting data.


Hugely simplified, the new code and unchanged test looks like this:

import os, sys
import unittest
from unittest import mock

def read_file(filename):

#
# This section is new
#
with open(filename, "rb") as f:
text = f.read()
if text.startswith(b"#"):
pass

with open(filename) as f:
text = f.read()
if text.startswith("#"):
pass

return text

class TestS(unittest.TestCase):

def test_read_file(self):
mock_open = mock.mock_open(read_data="abc")
with mock.patch('builtins.open', mock_open):
data = read_file("abc")
assert mock_open.return_value.read.call_count == 1

if __name__ == '__main__':
unittest.main()


I would expect the test to fail because of the call_count change. But in 
fact it errors out because the newly-added "if test.startswith()" 
receives a string, not bytes, from the Mock's read_data functionality.


Ignore for the moment any question of changing the read_file 
implementation to assist testing. And leave aside the question of 
whether a mock_open is really a good test approach here.


Is there any way in which I can have the mock_open object return bytes 
for the first open and a string for the second? I've looked at setting a 
side_effect function against the mock_open.return_value.read Mock, but I 
can't see a way of having the function know whether it's supposed to be 
returning bytes or string.



TJG
--
https://mail.python.org/mailman/listinfo/python-list


__import__ fails randomly due to missing file

2018-03-12 Thread Arkadiusz Bulski
Hi,

For the record, I am the developer of Construct library. And the question
relates to it.
https://construct.readthedocs.io/en/latest/#

I have an issue of Travis failing randomly at test cases. The cause is
always __import__ failing to import a dynamically generated code. Library
generates a string, saves it to a file (closes the file too), then
__import__ it. I dont think there is anything wrong with the (generated
imported) code itself. It seems like its some sort of issue with the Python
runtime (or filesystem) not detecting the file because it was created only
a moment ago. I tried to solve it by adding os.sync() between writing the
file and importing it, but it seems to have only decreased the error rate,
not solved it. Frankly, this is a heisenbug. Re-running the Travis job
usually fixes it. Its random and happens very rarely. I havent pinpointed
it to any particular version of CPython or Pypy (although I dont remember
it ever happening on Pypy).

An example:
https://travis-ci.org/construct/construct/jobs/352213556

The code in question:
https://github.com/construct/construct/blob/d9c645ed0a75b5a2b64318113cf69cac822fd8f5/construct/core.py#L402-L414
https://github.com/construct/construct/blob/d9c645ed0a75b5a2b64318113cf69cac822fd8f5/construct/core.py#L179-L180

-- 
~ Arkadiusz Bulski
~ tel 503 357 111 lub WhatsApp/Telegram
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: __import__ fails randomly due to missing file

2018-03-12 Thread Paul Moore
On 12 March 2018 at 09:12, Arkadiusz Bulski  wrote:
> Hi,
>
> For the record, I am the developer of Construct library. And the question
> relates to it.
> https://construct.readthedocs.io/en/latest/#
>
> I have an issue of Travis failing randomly at test cases. The cause is
> always __import__ failing to import a dynamically generated code. Library
> generates a string, saves it to a file (closes the file too), then
> __import__ it. I dont think there is anything wrong with the (generated
> imported) code itself. It seems like its some sort of issue with the Python
> runtime (or filesystem) not detecting the file because it was created only
> a moment ago. I tried to solve it by adding os.sync() between writing the
> file and importing it, but it seems to have only decreased the error rate,
> not solved it. Frankly, this is a heisenbug. Re-running the Travis job
> usually fixes it. Its random and happens very rarely. I havent pinpointed
> it to any particular version of CPython or Pypy (although I dont remember
> it ever happening on Pypy).
>
> An example:
> https://travis-ci.org/construct/construct/jobs/352213556
>
> The code in question:
> https://github.com/construct/construct/blob/d9c645ed0a75b5a2b64318113cf69cac822fd8f5/construct/core.py#L402-L414
> https://github.com/construct/construct/blob/d9c645ed0a75b5a2b64318113cf69cac822fd8f5/construct/core.py#L179-L180

The import system caches os.stat information, so it's possible that if
you're creating the file and then relatively quickly doing the import,
there may be some cache effect going on (granularity of file
modification timestamps?) I don't know the details, but it might be
worth looking in that area...

Paul
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: __import__ fails randomly due to missing file

2018-03-12 Thread Arkadiusz Bulski
I inserted importlib.invalidate_caches() instead of os.sync() and at a
glance, it seems to have fixed it.

Big thanks Paul!


pon., 12 mar 2018 o 11:00 użytkownik Paul Moore 
napisał:

> On 12 March 2018 at 09:12, Arkadiusz Bulski  wrote:
> > Hi,
> >
> > For the record, I am the developer of Construct library. And the question
> > relates to it.
> > https://construct.readthedocs.io/en/latest/#
> >
> > I have an issue of Travis failing randomly at test cases. The cause is
> > always __import__ failing to import a dynamically generated code. Library
> > generates a string, saves it to a file (closes the file too), then
> > __import__ it. I dont think there is anything wrong with the (generated
> > imported) code itself. It seems like its some sort of issue with the
> Python
> > runtime (or filesystem) not detecting the file because it was created
> only
> > a moment ago. I tried to solve it by adding os.sync() between writing the
> > file and importing it, but it seems to have only decreased the error
> rate,
> > not solved it. Frankly, this is a heisenbug. Re-running the Travis job
> > usually fixes it. Its random and happens very rarely. I havent pinpointed
> > it to any particular version of CPython or Pypy (although I dont remember
> > it ever happening on Pypy).
> >
> > An example:
> > https://travis-ci.org/construct/construct/jobs/352213556
> >
> > The code in question:
> >
> https://github.com/construct/construct/blob/d9c645ed0a75b5a2b64318113cf69cac822fd8f5/construct/core.py#L402-L414
> >
> https://github.com/construct/construct/blob/d9c645ed0a75b5a2b64318113cf69cac822fd8f5/construct/core.py#L179-L180
>
> The import system caches os.stat information, so it's possible that if
> you're creating the file and then relatively quickly doing the import,
> there may be some cache effect going on (granularity of file
> modification timestamps?) I don't know the details, but it might be
> worth looking in that area...
>
> Paul
>
-- 
~ Arkadiusz Bulski
~ tel 503 357 111 lub WhatsApp/Telegram
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Flask: request vs Request

2018-03-12 Thread Christopher Mullins
>
> Could you please give some context when you reply, TIA
>

Whoops, thanks for the reminder Mark.

So what for the Request is used  for then?


In general when you see that something in Python starts with a capital
letter, that indicates a class. Check out the relevant section of the PEP8
coding style [1], this is a good reference to have on hand.  (This
generalization doesn't apply to builtin types which follow a separate
convention, also outlined in [1] -- and of course there are a numerous
exceptions.)

This holds for your variable in question "request" which is an instance of
the Request class.  Check out [2] for more information on this.  PyCharm
tries to do its best but I've had this problem too.  You can always open up
a python REPL and look at the object yourself:

>>> import flask
>>> r = flask.Request
>>> r

>>> dir(r)

and so on.  When I'm working in python I like to keep one of these open for
this purpose.

HTH,
Chris

[1] https://www.python.org/dev/peps/pep-0008/#class-names
[2] http://flask.pocoo.org/docs/0.12/api/#incoming-request-data
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Enumerating all 3-tuples

2018-03-12 Thread Robin Becker
It's possible to generalize the cantor pairing function to triples, but that may not give you what you want. Effectively you can 
generate an arbitrary number of triples using an iterative method. My sample code looked like this



import math

def cantor_pair(k1,k2):
return (((k1+k2)*(k1+k2+1))>>1) + k2

def inverse_cantor_pair(z):
w = int((math.sqrt(8*z+1)-1)/2.0)
t = (w*(w+1))>>1
j = z - t
i = w - j
return i, j

def cantor_triple(i,j,k):
return cantor_pair(cantor_pair(i,j),k)

def inverse_cantor_triple(z):
j,k = inverse_cantor_pair(z)
i,j = inverse_cantor_pair(j)
return i,j,k

if __name__=='__main__':
for z in xrange(100):
i,j,k = inverse_cantor_triple(z)
print z, repr((i,j,k))


or changing the construction

import math

def cantor_pair(k1,k2):
return (((k1+k2)*(k1+k2+1))>>1) + k2

def inverse_cantor_pair(z):
w = int((math.sqrt(8*z+1)-1)/2.0)
t = (w*(w+1))>>1
j = z - t
i = w - j
return i, j

def cantor_triple(i,j,k):
return cantor_pair(i,cantor_pair(j,k))

def inverse_cantor_triple(z):
i,k = inverse_cantor_pair(z)
j,k = inverse_cantor_pair(k)
return i,j,k

if __name__=='__main__':
for z in xrange(100):
i,j,k = inverse_cantor_triple(z)
print z, repr((i,j,k)), cantor_triple(i,j,k)==z

this give different outcomes, but both appear to be a correct mapping of 
non-negative integers to triplets.
--
Robin Becker

--
https://mail.python.org/mailman/listinfo/python-list


Re: Flask: request vs Request

2018-03-12 Thread Andrew Z
Thank you Christopher.

On Mar 12, 2018 09:10, "Christopher Mullins" 
wrote:

> Could you please give some context when you reply, TIA
>>
>
> Whoops, thanks for the reminder Mark.
>
> So what for the Request is used  for then?
>
>
> In general when you see that something in Python starts with a capital
> letter, that indicates a class. Check out the relevant section of the PEP8
> coding style [1], this is a good reference to have on hand.  (This
> generalization doesn't apply to builtin types which follow a separate
> convention, also outlined in [1] -- and of course there are a numerous
> exceptions.)
>
> This holds for your variable in question "request" which is an instance of
> the Request class.  Check out [2] for more information on this.  PyCharm
> tries to do its best but I've had this problem too.  You can always open up
> a python REPL and look at the object yourself:
>
> >>> import flask
> >>> r = flask.Request
> >>> r
> 
> >>> dir(r)
>
> and so on.  When I'm working in python I like to keep one of these open
> for this purpose.
>
> HTH,
> Chris
>
> [1] https://www.python.org/dev/peps/pep-0008/#class-names
> [2] http://flask.pocoo.org/docs/0.12/api/#incoming-request-data
>
>
>
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Enumerating all 3-tuples

2018-03-12 Thread Elliott Roper
On 10 Mar 2018, Paul Moore wrote
(in article):

> On 10 March 2018 at 02:18, MRAB  wrote:
> > On 2018-03-10 01:13, Steven D'Aprano wrote:
> > >
> > > I am trying to enumerate all the three-tuples (x, y, z) where each of x,
> > > y, z can range from 1 to ∞ (infinity).
> > >
> > > This is clearly unhelpful:
> > >
> > > for x in itertools.count(1):
> > > for y in itertools.count(1):
> > > for z in itertools.count(1):
> > > print(x, y, z)
> > >
> > > as it never advances beyond x=1, y=1 since the innermost loop never
> > > finishes.
> > >
> > > Georg Cantor to the rescue! (Well, almost...)
> [...]
> > > Can anyone help me out here?
> > Think about the totals of each triple. You'll get totals of 3, then totals
> > of 4, etc.
> >
> > This might help, although the order they come out might not be what you
> > want:
> >
> > def triples():
> > for total in itertools.count(1):
> > for i in range(1, total):
> > for j in range(1, total - i):
> > yield i, j, total - (i + j)
>
> Mathematically, that's the usual generalisation of Cantor's diagonal argument.
>
> Paul

Would a multi-dimensional Hilbert curve do the job? See the Wikipedia article 
for starters

-- 
To de-mung my e-mail address:- fsnospam$elliott$$ PGP Fingerprint: 1A96 3CF7 
637F 896B C810 E199 7E5C A9E4 8E59 E248

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Enumerating all 3-tuples

2018-03-12 Thread Robin Becker

On 12/03/2018 13:17, Robin Becker wrote:
It's possible to generalize the cantor pairing function to triples, but that may not give you what you want. Effectively you can 
generate an arbitrary number of triples using an iterative method. My sample code looked like this

ct mapping of non-negative integers to triplets.

An alternative approach gives more orderly sequences using a variable base 
number construction

class Tupilator(object):
def __init__(self,degree=3):
self.i = 0
self.n = 2
self.degree = degree

def next(self):
x = self.i
v = []
a =v.append
n = self.n
if not x: a(0)
while x>0:
x, d = divmod(x,n)
a(d)
if sum(v)==self.degree*(n-1):
self.n += 1
pad = self.degree - len(v)
if pad>0:
v += pad*[0]
self.i += 1
return tuple(v)

if __name__=='__main__':
t = Tupilator()
for z in xrange(100):
print z, t.next()


0 (0, 0, 0)
1 (1, 0, 0)
2 (0, 1, 0)
3 (1, 1, 0)
4 (0, 0, 1)
5 (1, 0, 1)
6 (0, 1, 1)
7 (1, 1, 1)
8 (2, 2, 0)
9 (0, 0, 1)
10 (1, 0, 1)
11 (2, 0, 1)
12 (0, 1, 1)
13 (1, 1, 1)
14 (2, 1, 1)
15 (0, 2, 1)
16 (1, 2, 1)
17 (2, 2, 1)
18 (0, 0, 2)
19 (1, 0, 2)
20 (2, 0, 2)
21 (0, 1, 2)
22 (1, 1, 2)
23 (2, 1, 2)
24 (0, 2, 2)
25 (1, 2, 2)
26 (2, 2, 2)
27 (3, 2, 1)
28 (0, 3, 1)
29 (1, 3, 1)
30 (2, 3, 1)
31 (3, 3, 1)
32 (0, 0, 2)
33 (1, 0, 2)
34 (2, 0, 2)
35 (3, 0, 2)
36 (0, 1, 2)
37 (1, 1, 2)
38 (2, 1, 2)
39 (3, 1, 2)
40 (0, 2, 2)



80 (0, 1, 3)
81 (1, 1, 3)
82 (2, 1, 3)
83 (3, 1, 3)
84 (4, 1, 3)
85 (0, 2, 3)
86 (1, 2, 3)
87 (2, 2, 3)
88 (3, 2, 3)
89 (4, 2, 3)
90 (0, 3, 3)
91 (1, 3, 3)
92 (2, 3, 3)
93 (3, 3, 3)
94 (4, 3, 3)
95 (0, 4, 3)
96 (1, 4, 3)
97 (2, 4, 3)
98 (3, 4, 3)
99 (4, 4, 3)





--
Robin Becker

--
https://mail.python.org/mailman/listinfo/python-list


Re: Initializing error

2018-03-12 Thread Michael F. Stemper

On 2018-03-10 09:41, Harsh Bhardwaj wrote:

On Mar 5, 2018 11:16 AM, "Harsh Bhardwaj"  wrote:

Plz fix this problem for me. I tried every way to fix this.
Windows 7(32-bit)


That's a pretty bad problem. Fortunately, there is a fix:


--
Michael F. Stemper
Soglin for governor.
--
https://mail.python.org/mailman/listinfo/python-list


Re: Enumerating all 3-tuples

2018-03-12 Thread Chris Angelico
On Tue, Mar 13, 2018 at 2:54 AM, Robin Becker  wrote:
> On 12/03/2018 13:17, Robin Becker wrote:
> An alternative approach gives more orderly sequences using a variable base
> number construction
>
>> 4 (0, 0, 1)
>> 9 (0, 0, 1)
>> 18 (0, 0, 2)
>> 32 (0, 0, 2)

I spy duplicates.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Initializing error

2018-03-12 Thread Chris Angelico
On Tue, Mar 13, 2018 at 2:53 AM, Michael F. Stemper
 wrote:
> On 2018-03-10 09:41, Harsh Bhardwaj wrote:
>>
>> On Mar 5, 2018 11:16 AM, "Harsh Bhardwaj"  wrote:
>>
>> Plz fix this problem for me. I tried every way to fix this.
>> Windows 7(32-bit)
>
>
> That's a pretty bad problem. Fortunately, there is a fix:
> 
>

And if that fix isn't appropriate to you, Bhardwaj, please notice that
the quoted text above is everything that we got. You cannot attach
images to your posts, and we cannot read your mind (not legally,
anyway). You'll have to ask your question with enough information for
us to answer it.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Enumerating all 3-tuples

2018-03-12 Thread Skip Montanaro
>>> 4 (0, 0, 1)
>>> 9 (0, 0, 1)
>>> 18 (0, 0, 2)
>>> 32 (0, 0, 2)
>
> I spy duplicates.

I didn't realize we'd started playing "I Spy

."
​ ​

Skip
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Enumerating all 3-tuples

2018-03-12 Thread Chris Angelico
On Tue, Mar 13, 2018 at 5:42 AM, Skip Montanaro
 wrote:
 4 (0, 0, 1)
 9 (0, 0, 1)
 18 (0, 0, 2)
 32 (0, 0, 2)
>>
>> I spy duplicates.
>
> I didn't realize we'd started playing "I Spy."
> 

We're actually playing Calvinball, but don't tell the others.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: test

2018-03-12 Thread Alister via Python-list
On Mon, 12 Mar 2018 13:43:01 -0500, Yuan Xue wrote:

> test

failed



-- 
Mollison's Bureaucracy Hypothesis:
If an idea can survive a bureaucratic review and be implemented
it wasn't worth doing.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Can mock.mock_open.read return different values?

2018-03-12 Thread codewizard
On Monday, March 12, 2018 at 4:51:53 AM UTC-4, Tim Golden wrote:
> I'm contributing to a codebase which makes heavy use of mock in the test 
> suite, a technique which I'm aware of but have used only rarely. In one 
> situation it uses mock.mock_open(read_data="...") and then asserts again 
> mock_open.return_value.read.call_count.
> 
> A code change I've made results in an increase in the call count but 
> also the open() I've introduced opens the file in binary mode and does 
> something with the resulting data.
> 
> Hugely simplified, the new code and unchanged test looks like this:
> 
> import os, sys
> import unittest
> from unittest import mock
> 
> def read_file(filename):
> 
>  #
>  # This section is new
>  #
>  with open(filename, "rb") as f:
>  text = f.read()
>  if text.startswith(b"#"):
>  pass
> 
>  with open(filename) as f:
>  text = f.read()
>  if text.startswith("#"):
>  pass
> 
>  return text
> 
> class TestS(unittest.TestCase):
> 
>  def test_read_file(self):
>  mock_open = mock.mock_open(read_data="abc")
>  with mock.patch('builtins.open', mock_open):
>  data = read_file("abc")
>  assert mock_open.return_value.read.call_count == 1
> 
> if __name__ == '__main__':
>  unittest.main()
> 
> 
> I would expect the test to fail because of the call_count change. But in 
> fact it errors out because the newly-added "if test.startswith()" 
> receives a string, not bytes, from the Mock's read_data functionality.
> 
> Ignore for the moment any question of changing the read_file 
> implementation to assist testing. And leave aside the question of 
> whether a mock_open is really a good test approach here.
> 
> Is there any way in which I can have the mock_open object return bytes 
> for the first open and a string for the second? I've looked at setting a 
> side_effect function against the mock_open.return_value.read Mock, but I 
> can't see a way of having the function know whether it's supposed to be 
> returning bytes or string.
> 
> 
> TJG

2 ways come to mind:

1. Have the side effect function check something that differentiates
those 2 calls. In this case, checking mode argument value should work.

2. Rely on the order of calls with a local side effect function
closing over a call number. Something like this (untested):

def test_read_file(self):
call_number = 0

def open_side_effect(filename, mode='r'):
call_number += 1

if call_number == 1:
 return b'some bytes'
if call_number == 2:
 return 'some string'

 with mock.patch(..., side_effect=open_side_effect):
  # test

Regards,
Igor.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: test

2018-03-12 Thread Cameron Simpson

On 17Mar2014 11:42, Mark H Harris  wrote:

On 3/16/14 5:07 AM, Chris “Kwpolska” Warrick wrote:

Why not use the mailing list instead?  It’s a much easier way to
access this place.


I prefer to 'pull' rather than receive the 'push'.

The newsreader idea is better because threading works better, and
because the interface is simpler. I don't know, just preference
I guess.


I use mutt for email. Great threading support. My usenetness has mostly lapsed, 
but I used to funnel groups into my mail filer, read with mutt (same tool for 
news and mail!), and have a script for sendmail which intercepted 
group.name@usenet and send that via NNTP (obviously my puller inserted those 
addresses in the pull).



What are most active pythoniacs doing with this these days?


I use the mailing lists and mutt for reading.

Cheers,
Cameron Simpson  (formerly [email protected])
--
https://mail.python.org/mailman/listinfo/python-list


test

2018-03-12 Thread Yuan Xue
test
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: test

2018-03-12 Thread Yuan Xue
Alister  writes:

> On Mon, 12 Mar 2018 13:43:01 -0500, Yuan Xue wrote:
>
>> test
>
> failed

Funny, I am wodering what type of persons are still using this clumsy
system, and their purposes of using it.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Enumerating all 3-tuples (Posting On Python-List Prohibited)

2018-03-12 Thread Ben Bacarisse
Lawrence D’Oliveiro  writes:

> On Sunday, March 11, 2018 at 2:40:16 PM UTC+13, Ben Bacarisse wrote:
>> It would be nice to avoid relying on any value-based ordering.
>
> I don’t see why. The set of elements has to have the same cardinality
> as the set of natural numbers, after all. Why not take advantage of
> that?

Maybe we are saying the same thing?  The elements from which the tuple
members are drawn need only be a sequence defined by a successor
function.  The values themselves need have no ordering nor, indeed, have
any of the arithmetic properties of N.

Of course you can always generate n-tuples of N and then map these to
n-tuples of the intended sequence but that seems inelegant.

-- 
Ben.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Stock quote AP

2018-03-12 Thread ROGER GRAYDON CHRISTMAN

On Mon, Mar 12, 2018 12:00 PM, Irv Kalb wrote:
>
> On Mar 10, 2018, at 9:26 PM, Chris Angelico  wrote:
>> 
>> On Sun, Mar 11, 2018 at 4:18 PM, Irv Kalb  wrote:
>> Hi,
>> 
>> I teach courses on beginning Python (Python3).  In one of my
>topics, I explain how we can write simple programs that reach out to the
>internet and download data (request/response).
>> 
>> I show a number of examples using:   urllib.request.urlopen(
> )  to get things like weather data, currency
>exchange rates, etc.
>> 
>> I just tried my examples again, and they are all working fine, except for
>one.  I had an example where I used the call above to get simple
>(American) stock quotes from Yahoo.  However, with this example, now
>I get a bunch errors.  In tracking it down, I found that Yahoo has shut down
>this public API, discontinued this service.
>> 
>> So ... I am looking for a replacement.  I have done quite a bit of
>searching, but I have not been able to find a simple way to get a stock quote
>(no need for historical data - most recent price is fine).  I have
>found many examples where people have built custom packages for doing this type
>of thing.  However, I am in a college environment, and I cannot install any new
>packages on the computers there.  I've also seen examples of people building
>SQL-style queries to get this type of information, but that's beyond what I am
>trying to teach.
>> 
>> Wondering if anyone has any example of an API where I could just make a
>call using Python Standard Library interfaces to get stock quotes?
>> 
>> 
>> Check out https://www.alphavantage.co/ for something you can query for
>> free. Extensive and amazingly useful. One of my students did some
>> second-tier analysis on the data they provide as a capstone project on
>> stock trading analysis.
>> 
>> You may want to consider, though, modifying the "no new packages"
>> rule. The 'requests' library is WAY better for teaching Python and web
>> APIs than the raw urllib. Get just a small handful of pip-installable
>> packages whitelisted and your life will be better.
>> 
>> ChrisA
>> 
>
>Hi Chris,
>
>Thank you very much for this.  It is very close to what I am looking for.  I
>had seen this early in my searches but I didn't go into it in detail because it
>looked like it was designed to give way more information than I was looking for
>- for example, the first example is about time series data.  
>
>I did look into it today, and I got a free API key to check it out.  It does
>have the ability to give just a stock quote for a symbol, but it looks like the
>minimum I can get back is a csv:
>
>symbol,price,volume,timestamp
>MSFT,96.1800,--,2018-03-09 16:01:30
>
>which is easy enough for me to break apart.  I just wish there was a way to
>eliminate the header line so I wouldn't have to go through an explanation about
>that.  
>
>Thanks very much.  If I can't find another one that just give back a price,
>I'll probably use this one.
>
>Irv
>
>
>


Have you introduced the concepts of dictionaries in your Python course yet?
In my introductory course, I present dictionaries even before if statements and
for loops,
since they have so many very useful features for data manipulation.

That first line in the csv file is perfect for use with a dictionary.
You would just need to get a dictionary Reader from the csv module,

import urllib.request

import io, csv

file = urllib.request.urlopen(site + filename)

data = io.TextIOWrapper(file, newline="", encoding="utf-8")

reader = csv.DictReader(data)

for row in reader:


At this point, you could get your data from row['symbol'], row['price']
If you want to pretend that you don't actually know what the headings are,
you could simply enumerate that row dictionary value, at it will tell
you both the heading the value.   Each line in the file would be a new
dictionary.

Roger Christman
Pennsylvania State University



-- 
https://mail.python.org/mailman/listinfo/python-list