Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #20373 > unrolled thread
| Started by | Bruce Eckel <lists.eckel@gmail.com> |
|---|---|
| First post | 2012-02-13 14:01 -0800 |
| Last post | 2012-02-15 19:21 +0100 |
| Articles | 7 — 4 participants |
Back to article view | Back to comp.lang.python
Automatic Type Conversion to String Bruce Eckel <lists.eckel@gmail.com> - 2012-02-13 14:01 -0800
Re: Automatic Type Conversion to String Chris Rebert <clp2@rebertia.com> - 2012-02-13 14:27 -0800
Re: Automatic Type Conversion to String Bruce Eckel <lists.eckel@gmail.com> - 2012-02-13 15:18 -0800
Re: Automatic Type Conversion to String Bruce Eckel <lists.eckel@gmail.com> - 2012-02-13 15:18 -0800
Re: Automatic Type Conversion to String Ulrich Eckhardt <ulrich.eckhardt@dominolaser.com> - 2012-02-14 15:26 +0100
Re: Automatic Type Conversion to String Bruce Eckel <lists.eckel@gmail.com> - 2012-02-15 06:58 -0800
Re: Automatic Type Conversion to String Ned Deily <nad@acm.org> - 2012-02-15 19:21 +0100
| From | Bruce Eckel <lists.eckel@gmail.com> |
|---|---|
| Date | 2012-02-13 14:01 -0800 |
| Subject | Automatic Type Conversion to String |
| Message-ID | <090e2893-7a1c-4b11-9e45-974ed33e7b77@i18g2000yqf.googlegroups.com> |
I'm creating a class to encapsulate OS paths, to reduce the visual
noise and typing from the os.path methods. I've got the class and nose
tests below, and everything works except the last test which I've
prefixed with XXX:
def XXXtest_should_work(self):
"""
Produces:
open(self.p2, 'w').write('')
TypeError: coercing to Unicode: need string or buffer, Path
found
"""
open(self.p2, 'w').write('')
assert self.p2
Note that I *have* a __str__(self) method to perform automatic
conversion to string, and I've commented out the __unicode__(self)
method because it wasn't getting called. The problem appears to be
that open() does not seem to be calling __str__ on its first argument,
but instead it appears to want a basestring and this doesn't
automatically call __str__.
I'm trying to write the Path class so I can just hand a Path object
to, for example, open() and have it produce the path string.
Thanks for any insights.
--------------------------- Class and tests, put in file path.py
------------------------------------
import os, os.path
class Path(object):
def __init__(self, *args):
"""
Each of *args is a piece of a path. Assemble them together.
"""
if len(args) == 0:
self.path = os.path.abspath('.')
else:
self.path = str(args[0]) # str() so you can add Path
objects
if self.path.endswith(':'):
self.path = os.path.join(self.path, os.sep)
for a in args[1:]:
self.path = os.path.join(self.path, str(a))
def __add__(self, other):
return Path(os.path.join(self.path, other))
def __iadd__(self, other): # path += path
self.path = os.path.join(self.path, other)
return self # Allows chaining
def __str__(self):
return self.path
# def __repr__(self):
# assert not self.path, "__repr__"
# return os.path.join(self.path)
# def __unicode__(self):
# assert not self.path, "__unicode__"
# print "Unicode called %s" % self.path
# return os.path.join(self.path)
def __nonzero__(self):
"""
Boolean test: does this path exist?
So you can say "if path:"
"""
return bool(os.path.exists(self.path))
"""
Nose tests. To run, you must first install nose:
pip install nose
Then:
nosetests path.py
"""
def test_platform():
"First draft tests are Windows-based"
import platform
assert platform.system() == 'Windows'
class test_paths():
def setUp(self):
self.paths = [
("C:\\"),
("C:\\", "Users", "Bruce Eckel", "Downloads",
"AtomicScala.zip"),
("C:\\", "Users", "Bruce Eckel", "Dropbox",
"AtomicScala"),
]
self.p1 = Path(self.paths[0])
self.s1 = os.path.join(self.paths[0], "\\")
self.p2 = Path(*self.paths[1])
self.s2 = os.path.join(*self.paths[1])
self.p3 = Path(*self.paths[2])
self.s3 = os.path.join(*self.paths[2])
self.p4 = self.p3 + "TestFile1.tmp"
self.s4 = os.path.join(self.s3, "TestFile1.tmp")
self.p5 = self.p3 + "TestFile2.tmp"
self.s5 = os.path.join(self.s3, "TestFile2.tmp")
self.p6 = Path("foo") + "bar" + "baz"
def test1(self):
"Root directory"
print self.p1
print self.s1
assert str(self.p1) == self.s1
def test2(self):
"Full path to file"
print "p2", self.p2
print "s2", self.s2
assert str(self.p2) == self.s2
def test3(self):
"Directory"
assert str(self.p3) == self.s3
def test4(self):
"Plus operator"
assert str(self.p4) == self.s4
def test5(self):
"Another temp file"
assert str(self.p5) == self.s5
def test6(self):
"Chained operator +"
assert str(self.p6) == r"foo\bar\baz"
def test7(self):
"Operator +="
self.p6 += "bingo"
assert str(self.p6) == r"foo\bar\baz\bingo"
def test8(self):
"Create a Path from a Path"
p = Path(self.p3)
assert p.path == self.s3
class test_existence:
"""
Test for directory and path existence
"""
def setUp(self):
base = Path("C:", "Users", "Bruce Eckel", "Downloads")
self.p1 = base + "TestFile1.tmp"
self.p2 = base + "TestFile2.tmp"
self.p3 = base + "TestFile3.tmp"
def test_basestring(self):
print type(self.p1)
assert isinstance(self.p1.path, basestring)
def test1(self):
"p1 existence"
open(self.p1.path, 'w').write('')
assert self.p1
def test2(self):
"p2 existence"
open(self.p2.path, 'w').write('')
assert self.p2
def test3(self):
"p3 existence"
assert not self.p3
def XXXtest_should_work(self):
"""
Produces:
open(self.p2, 'w').write('')
TypeError: coercing to Unicode: need string or buffer, Path
found
"""
open(self.p2, 'w').write('')
assert self.p2
[toc] | [next] | [standalone]
| From | Chris Rebert <clp2@rebertia.com> |
|---|---|
| Date | 2012-02-13 14:27 -0800 |
| Message-ID | <mailman.5782.1329172035.27778.python-list@python.org> |
| In reply to | #20373 |
On Mon, Feb 13, 2012 at 2:01 PM, Bruce Eckel <lists.eckel@gmail.com> wrote:
> I'm creating a class to encapsulate OS paths, to reduce the visual
> noise and typing from the os.path methods. I've got the class and nose
> tests below, and everything works except the last test which I've
> prefixed with XXX:
>
> def XXXtest_should_work(self):
> """
> Produces:
> open(self.p2, 'w').write('')
> TypeError: coercing to Unicode: need string or buffer, Path
> found
> """
> open(self.p2, 'w').write('')
> assert self.p2
>
> Note that I *have* a __str__(self) method to perform automatic
> conversion to string, and I've commented out the __unicode__(self)
> method because it wasn't getting called. The problem appears to be
> that open() does not seem to be calling __str__ on its first argument,
> but instead it appears to want a basestring and this doesn't
> automatically call __str__.
Right. Python is strongly-typed, so it requires a genuine str here (as
opposed to just something that's stringifyable) and doesn't do an
coercion call to str() for you. Just like how str.join() doesn't
automatically call str() on the elements of the list you give it. This
is to prevent silliness like trying to open() e.g. a dict. Your
alternatives are:
- Learn to live with having to write open(str(path_obj))
- Add a .open() method to Path, and use that instead of the open()
built-in function
- Have Path subclass `str` or `unicode`
> I'm trying to write the Path class so I can just hand a Path object
> to, for example, open() and have it produce the path string.
Impossible, short of subclassing `str` or `unicode`.
Cheers,
Chris
[toc] | [prev] | [next] | [standalone]
| From | Bruce Eckel <lists.eckel@gmail.com> |
|---|---|
| Date | 2012-02-13 15:18 -0800 |
| Message-ID | <12584848.58.1329175135396.JavaMail.geo-discussion-forums@ynii32> |
| In reply to | #20374 |
I'm willing to subclass str, but when I tried it before it became a little confusing -- I think mostly because anytime I assigned to self it seemed like it converted the whole object to a str rather than a Path. I suspect I don't know the proper idiom for doing this -- any hints? Thanks ...
[toc] | [prev] | [next] | [standalone]
| From | Bruce Eckel <lists.eckel@gmail.com> |
|---|---|
| Date | 2012-02-13 15:18 -0800 |
| Message-ID | <mailman.5785.1329175143.27778.python-list@python.org> |
| In reply to | #20374 |
I'm willing to subclass str, but when I tried it before it became a little confusing -- I think mostly because anytime I assigned to self it seemed like it converted the whole object to a str rather than a Path. I suspect I don't know the proper idiom for doing this -- any hints? Thanks ...
[toc] | [prev] | [next] | [standalone]
| From | Ulrich Eckhardt <ulrich.eckhardt@dominolaser.com> |
|---|---|
| Date | 2012-02-14 15:26 +0100 |
| Message-ID | <eh7q09-69s.ln1@satorlaser.homedns.org> |
| In reply to | #20379 |
Am 14.02.2012 00:18, schrieb Bruce Eckel: > I'm willing to subclass str, but when I tried it before it became a > little confusing -- I think mostly because anytime I assigned to self > it seemed like it converted the whole object to a str rather than a > Path. I suspect I don't know the proper idiom for doing this -- any > hints? Thanks ... Could it be that you missed the fact that strings are immutable? That means that you can't change the content of the object once it is initialized. In particular, it means that you e.g. have to override __new__ instead of __init__, because the content is already fixed when the latter is called. Python strings rather behave like Java strings than C++ strings. Uli
[toc] | [prev] | [next] | [standalone]
| From | Bruce Eckel <lists.eckel@gmail.com> |
|---|---|
| Date | 2012-02-15 06:58 -0800 |
| Message-ID | <dc097623-f377-4c7d-a065-13b58bf1cabd@n12g2000yqb.googlegroups.com> |
| In reply to | #20401 |
> Could it be that you missed the fact that strings are immutable? That > means that you can't change the content of the object once it is > initialized. In particular, it means that you e.g. have to override > __new__ instead of __init__, because the content is already fixed when > the latter is called. > > Uli Yes, that's what I missed, and it explains why I found examples of str inheritance using __new__. I think this might end up being a puzzle I poke at for awhile. Also, I discovered that the attempt to create a "Path" class goes back to 2006, where it created a lot of discussion and was finally shelved: http://www.python.org/dev/peps/pep-0355/ A significant part of the problem seems to be that there was no inheritance from str at the time, so maybe a lot of the issues they ran into could be solved now.
[toc] | [prev] | [next] | [standalone]
| From | Ned Deily <nad@acm.org> |
|---|---|
| Date | 2012-02-15 19:21 +0100 |
| Message-ID | <mailman.5839.1329330127.27778.python-list@python.org> |
| In reply to | #20443 |
In article <dc097623-f377-4c7d-a065-13b58bf1cabd@n12g2000yqb.googlegroups.com>, Bruce Eckel <lists.eckel@gmail.com> wrote: > Also, I discovered that the attempt to create a "Path" class goes back > to 2006, where it created a lot of discussion and was finally shelved: > http://www.python.org/dev/peps/pep-0355/ > > A significant part of the problem seems to be that there was no > inheritance from str at the time, so maybe a lot of the issues they > ran into could be solved now. You might want to take a look at pathlib, a current attempt at providing object-oriented paths, written by Antoine Pitrou, one of the Python core developers: http://pypi.python.org/pypi/pathlib -- Ned Deily, nad@acm.org
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web